-
-
Notifications
You must be signed in to change notification settings - Fork 54
/
Read_Single_Email.ino
472 lines (391 loc) · 16.6 KB
/
Read_Single_Email.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
/**
* This example shows how to read Email and store the message in SD card.
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*
*/
/** ////////////////////////////////////////////////
* Struct data names changed from v2.x.x to v3.x.x
* ////////////////////////////////////////////////
*
* "ESP_Mail_Session" changes to "Session_Config"
* "IMAP_Config" changes to "IMAP_Data"
*
* Changes in the examples
*
* ESP_Mail_Session session;
* to
* Session_Config config;
*
* IMAP_Config config;
* to
* IMAP_Data imap_data;
*
*/
/** Assign SD card type and FS used in src/ESP_Mail_FS.h and
* change the config for that card interfaces in src/extras/SDHelper.h
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#else
// Other Client defined here
// To use custom Client, define ENABLE_CUSTOM_CLIENT in src/ESP_Mail_FS.h.
// See the example Custom_Client.ino for how to use.
#endif
#include <ESP_Mail_Client.h>
// Provide the SD card interfaces setting and mounting
#include <extras/SDHelper.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
*
* Some Gmail user still not able to sign in using account password even above options were set up,
* for this case, use "App Password" to sign in instead.
* About Gmail "App Password", go to https://support.google.com/accounts/answer/185833?hl=en
*
* For Yahoo mail, log in to your yahoo mail in web browser and generate app password by go to
* https://login.yahoo.com/account/security/app-passwords/add/confirm?src=noSrc
*
* To use Gmai and Yahoo's App Password to sign in, define the AUTHOR_PASSWORD with your App Password
* and AUTHOR_EMAIL with your account email.
*/
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
#define IMAP_HOST "<host>"
/** The imap port e.g.
* 143 or esp_mail_imap_port_143
* 993 or esp_mail_imap_port_993
*/
#define IMAP_PORT 993
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Callback function to get the Email reading status */
void imapCallback(IMAP_Status status);
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* Print the selected folder info */
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
/* Print all messages from the message list */
void printMessages(MB_VECTOR<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(MB_VECTOR<IMAP_Attach_Item> &atts);
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
Serial.println();
Serial.println("**** Custom built WiFiNINA firmware need to be installed.****\n");
Serial.println("To install firmware, read the instruction here, https://github.com/mobizt/ESP-Mail-Client#install-custom-build-wifinina-firmware");
#endif
Serial.println();
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
multi.addAP(WIFI_SSID, WIFI_PASSWORD);
multi.run();
#else
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
#endif
Serial.print("Connecting to Wi-Fi");
unsigned long ms = millis();
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(300);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
if (millis() - ms > 10000)
break;
#endif
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
Serial.println();
/* Set the network reconnection option */
MailClient.networkReconnect(true);
// The WiFi credentials are required for Pico W
// due to it does not have reconnect feature.
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
#if defined(ESP_MAIL_DEFAULT_SD_FS) // defined in src/ESP_Mail_FS.h
// Mount SD card.
SD_Card_Mounting(); // See src/extras/SDHelper.h
#endif
/** Enable the debug via Serial port
* 0 for no debugging
* 1 for basic level debugging
*
* Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h
*/
imap.debug(1);
/* Set the callback function to get the reading results */
imap.callback(imapCallback);
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
* For ESP32, assign all of SPI pins
* MailClient.sdBegin(14,2,15,13)
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
* And for ESP8266, assign the CS pins of SPI port
* MailClient.sdBegin(15)
* Which pin 15 is the CS pin of SD card adapter
*/
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Declare the IMAP_Data object used for user defined IMAP operating options
* and contains the IMAP operating result
*/
IMAP_Data imap_data;
/* Set the storage to save the downloaded files and attachments */
imap_data.storage.saved_path = F("/email_data");
/** The file storage type e.g.
* esp_mail_file_storage_type_none,
* esp_mail_file_storage_type_flash, and
* esp_mail_file_storage_type_sd
*/
imap_data.storage.type = esp_mail_file_storage_type_sd;
/** Set to download heades, text and html messaeges,
* attachments and inline images respectively.
*/
imap_data.download.header = true;
imap_data.download.text = true;
imap_data.download.html = true;
imap_data.download.attachment = true;
imap_data.download.inlineImg = true;
/** Set to enable the results i.e. html and text messaeges
* which the content stored in the IMAPSession object is limited
* by the option imap_data.limit.msg_size.
* The whole message can be download through imap_data.download.text
* or imap_data.download.html which not depends on these enable options.
*/
imap_data.enable.html = true;
imap_data.enable.text = true;
/* Set to enable the sort the result by message UID in the decending order */
imap_data.enable.recent_sort = true;
/* Set to report the download progress via the default serial port */
imap_data.enable.download_status = true;
/* Header fields parsing is case insensitive by default to avoid uppercase header in some server e.g. iCloud
, to allow case sensitive parse, uncomment below line*/
// imap_data.enable.header_case_sensitive = true;
/* Set the limit of number of messages in the search results */
imap_data.limit.search = 5;
/** Set the maximum size of message stored in
* IMAPSession object in byte
*/
imap_data.limit.msg_size = 512;
/** Set the maximum attachments and inline images files size
* that can be downloaded in byte.
* The file which its size is largger than this limit may be saved
* as truncated file.
*/
imap_data.limit.attachment_size = 1024 * 1024 * 5;
// If ID extension was supported by IMAP server, assign the client identification
// name, version, vendor, os, os_version, support_url, address, command, arguments, environment
// Server ID can be optained from imap.serverID() after calling imap.connect and imap.id.
// imap_data.identification.name = "User";
// imap_data.identification.version = "1.0";
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
// Client identification can be sent to server later with
/**
* IMAP_Identification iden;
* iden.name = "user";
* iden.version = "1.0";
*
* if (imap.id(&iden))
* {
* Serial.println("\nSend Identification success");
* Serial.println(imap.serverID());
* }
* else
* Serial.println("\nSend Identification error, " + imap.errorReason());
*/
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* {Optional} */
printAllMailboxesInfo(imap);
/* Open or select the mailbox folder to read or search the message */
if (!imap.selectFolder(F("INBOX")))
return;
/* {Optional} */
printSelectedMailboxInfo(imap.selectedFolder());
/** Message UID to fetch or read e.g. 100.
* In this case we will get the UID from the max message number (lastest message)
*/
imap_data.fetch.uid = imap.getUID(imap.selectedFolder().msgCount());
// or fetch via the message sequence number
// imap_data.fetch.number = imap.selectedFolder().msgCount();
// if both imap_data.fetch.uid and imap_data.fetch.number were set,
// then total 2 messages will be fetched i.e. one using uid and other using number.
/* Set seen flag */
// The message with "Seen" flagged means the message was already read or seen by user.
// The default value of this option is set to false.
// If you want to set the message flag as "Seen", set this option to true.
// If this option is false, the message flag was unchanged.
// To set or remove flag from message, see Set_Flags.ino example.
// imap_data.fetch.set_seen = true;
/* Read or search the Email and close the session */
// When message was fetched or read, the /Seen flag will not set or message remained in unseen or unread status,
// as this is the purpose of library (not UI application), user can set the message status as read by set \Seen flag
// to message, see the Set_Flags.ino example.
MailClient.readMail(&imap);
/* Clear all stored data in IMAPSession object */
imap.empty();
}
void loop()
{
}
/* Callback function to get the Email reading status */
void imapCallback(IMAP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Show the result when reading finished */
if (status.success())
{
/* Print the result */
/* Get the message list from the message list data */
IMAP_MSG_List msgList = imap.data();
printMessages(msgList.msgItems, imap.headerOnly());
/* Clear all stored data in IMAPSession object */
imap.empty();
}
}
void printAllMailboxesInfo(IMAPSession &imap)
{
/* Declare the folder collection class to get the list of mailbox folders */
FoldersCollection folders;
/* Get the mailbox folders */
if (imap.getFolders(folders))
{
for (size_t i = 0; i < folders.size(); i++)
{
/* Iterate each folder info using the folder info item data */
FolderInfo folderInfo = folders.info(i);
ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
ESP_MAIL_PRINTF("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
ESP_MAIL_PRINTF("Predicted next UID: %d\n", sFolder.nextUID());
ESP_MAIL_PRINTF("Unseen Message Index: %d\n", sFolder.unseenIndex());
for (size_t i = 0; i < sFolder.flagCount(); i++)
ESP_MAIL_PRINTF("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
}
void printAttacements(MB_VECTOR<IMAP_Attach_Item> &atts)
{
ESP_MAIL_PRINTF("Attachment: %d file(s)\n****************************\n", atts.size());
for (size_t j = 0; j < atts.size(); j++)
{
IMAP_Attach_Item att = atts[j];
/** att.type can be
* esp_mail_att_type_none or 0
* esp_mail_att_type_attachment or 1
* esp_mail_att_type_inline or 2
*/
ESP_MAIL_PRINTF("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Description: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.description, att.creationDate);
}
Serial.println();
}
void printMessages(MB_VECTOR<IMAP_MSG_Item> &msgItems, bool headerOnly)
{
/** In devices other than ESP8266 and ESP32, if SD card was chosen as filestorage and
* the standard SD.h library included in ESP_Mail_FS.h, files will be renamed due to long filename
* (> 13 characters) is not support in the SD.h library.
* To show how its original file name, use imap.fileList().
*/
// Serial.println(imap.fileList());
for (size_t i = 0; i < msgItems.size(); i++)
{
/* Iterate to get each message data through the message item data */
IMAP_MSG_Item msg = msgItems[i];
Serial.println("****************************");
ESP_MAIL_PRINTF("Number: %d\n", msg.msgNo);
ESP_MAIL_PRINTF("UID: %d\n", msg.UID);
ESP_MAIL_PRINTF("Messsage-ID: %s\n", msg.ID);
ESP_MAIL_PRINTF("Flags: %s\n", msg.flags);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
ESP_MAIL_PRINTF("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
if (strlen(msg.acceptLang))
ESP_MAIL_PRINTF("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
ESP_MAIL_PRINTF("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
ESP_MAIL_PRINTF("From: %s\n", msg.from);
if (strlen(msg.sender))
ESP_MAIL_PRINTF("Sender: %s\n", msg.sender);
if (strlen(msg.to))
ESP_MAIL_PRINTF("To: %s\n", msg.to);
if (strlen(msg.cc))
ESP_MAIL_PRINTF("CC: %s\n", msg.cc);
if (strlen(msg.date))
{
ESP_MAIL_PRINTF("Date: %s\n", msg.date);
ESP_MAIL_PRINTF("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
ESP_MAIL_PRINTF("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
ESP_MAIL_PRINTF("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
ESP_MAIL_PRINTF("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
ESP_MAIL_PRINTF("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
ESP_MAIL_PRINTF("References: %s\n", msg.references);
if (strlen(msg.comments))
ESP_MAIL_PRINTF("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
ESP_MAIL_PRINTF("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
ESP_MAIL_PRINTF("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
ESP_MAIL_PRINTF("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
ESP_MAIL_PRINTF("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
ESP_MAIL_PRINTF("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
ESP_MAIL_PRINTF("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
ESP_MAIL_PRINTF("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
ESP_MAIL_PRINTF("\r\nRFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
printMessages(msg.rfc822, headerOnly);
}
if (msg.attachments.size() > 0)
printAttacements(msg.attachments);
}
Serial.println();
}
}