Sendmail upgraded to ESP-Mail-Client v3.4.9 from v1.2.0, using BearSSL instead of MbedTLS (#19460)

* `Sendmail` upgraded to ESP-Mail-Client v3.4.9 from v1.2.0, using BearSSL instead of MbedTLS

* Fix compilation on ESP8266

* Fix compilation

* fix compilation
This commit is contained in:
s-hadinger 2023-09-04 23:00:37 +02:00 committed by GitHub
parent 1ea12583d1
commit c2f8821b2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
488 changed files with 150895 additions and 32312 deletions

View File

@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
### Changed
- Berry fast_loop is now called every 5ms whatever the Sleep value
- Reduce IRAM consumption of HDMI CEC to 1453 bytes
- `Sendmail` upgraded to ESP-Mail-Client v3.4.9 from v1.2.0, using BearSSL instead of MbedTLS
### Fixed
- PCF8574 mode 1 with base relays exception 3/28 regression from v12.4.0.4 (#19408)

View File

@ -1032,7 +1032,7 @@ typedef struct {
* \param append_in issuer DN receiver callback (or `0`).
* \param append_in_ctx context for the issuer DN receiver callback.
*/
void br_x509_decoder_init(br_x509_decoder_context *ctx,
void br_x509_decoder_init_esp8266(br_x509_decoder_context *ctx,
void (*append_dn)(void *ctx, const void *buf, size_t len),
void *append_dn_ctx,
void (*append_in)(void *ctx, const void *buf, size_t len),
@ -1048,7 +1048,7 @@ void br_x509_decoder_init(br_x509_decoder_context *ctx,
* \param data certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void br_x509_decoder_push(br_x509_decoder_context *ctx,
void br_x509_decoder_push_tasmota(br_x509_decoder_context *ctx,
const void *data, size_t len);
/**

View File

@ -62,9 +62,9 @@ t0_parse7E_signed(const unsigned char **p)
/* static const unsigned char t0_datablock[]; */
void br_x509_decoder_init_main(void *t0ctx);
void br_x509_decoder_init_main_tasmota(void *t0ctx);
void br_x509_decoder_run(void *t0ctx);
void br_x509_decoder_run_tasmota(void *t0ctx);
@ -81,7 +81,7 @@ void br_x509_decoder_run(void *t0ctx);
/* see bearssl_x509.h */
void
br_x509_decoder_init(br_x509_decoder_context *ctx,
br_x509_decoder_init_esp8266(br_x509_decoder_context *ctx,
void (*append_dn)(void *ctx, const void *buf, size_t len),
void *append_dn_ctx,
void (*append_in)(void *ctx, const void *buf, size_t len),
@ -99,18 +99,18 @@ br_x509_decoder_init(br_x509_decoder_context *ctx,
ctx->append_in_ctx = append_in_ctx;
ctx->cpu.dp = &ctx->dp_stack[0];
ctx->cpu.rp = &ctx->rp_stack[0];
br_x509_decoder_init_main(&ctx->cpu);
br_x509_decoder_run(&ctx->cpu);
br_x509_decoder_init_main_tasmota(&ctx->cpu);
br_x509_decoder_run_tasmota(&ctx->cpu);
}
/* see bearssl_x509.h */
void
br_x509_decoder_push(br_x509_decoder_context *ctx,
br_x509_decoder_push_tasmota(br_x509_decoder_context *ctx,
const void *data, size_t len)
{
ctx->hbuf = data;
ctx->hlen = len;
br_x509_decoder_run(&ctx->cpu);
br_x509_decoder_run_tasmota(&ctx->cpu);
}
@ -381,12 +381,12 @@ name(void *ctx) \
T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
}
T0_DEFENTRY(br_x509_decoder_init_main, 93)
T0_DEFENTRY(br_x509_decoder_init_main_tasmota, 93)
#define T0_NEXT(t0ipp) (pgm_read_byte((*t0ipp)++))
void
br_x509_decoder_run(void *t0ctx)
br_x509_decoder_run_tasmota(void *t0ctx)
{
uint32_t *dp, *rp;
const unsigned char *ip;

View File

@ -731,7 +731,7 @@ extern "C" {
br_x509_pubkeyfingerprint_context *xc = (br_x509_pubkeyfingerprint_context *)ctx;
// Don't process anything but the first certificate in the chain
if (!xc->done_cert) {
br_x509_decoder_init(&xc->ctx, nullptr, nullptr, nullptr, nullptr);
br_x509_decoder_init_esp8266(&xc->ctx, nullptr, nullptr, nullptr, nullptr);
}
(void)server_name; // ignore server name
}
@ -748,7 +748,7 @@ extern "C" {
br_x509_pubkeyfingerprint_context *xc = (br_x509_pubkeyfingerprint_context *)ctx;
// Don't process anything but the first certificate in the chain
if (!xc->done_cert) {
br_x509_decoder_push(&xc->ctx, (const void*)buf, len);
br_x509_decoder_push_tasmota(&xc->ctx, (const void*)buf, len);
}
}

View File

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2021 mobizt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License
Copyright (c) 2023 mobizt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,258 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to get, set the access control list.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
IMAP_Rights_List acl_list;
Serial.println("\nGet ACLs...");
if (!imap.getACL("INBOX", &acl_list))
{
Serial.println("Get ACLs failed");
}
else
{
Serial.println("ACL...");
for (size_t i = 0; i < acl_list.size(); i++)
{
MailClient.printf("Identifier: %s, Rights: ", acl_list[i].identifier.c_str());
String r;
for (int j = esp_mail_imap_rights_administer; j < esp_mail_imap_rights_maxType; j++)
{
if (acl_list[i].rights[j])
r += (char)('a' + j);
}
Serial.println(r);
}
}
IMAP_Rights_Info acl;
acl.identifier = "Steve";
acl.rights[esp_mail_imap_rights_administer] = true;
acl.rights[esp_mail_imap_rights_create] = true;
acl.rights[esp_mail_imap_rights_create_c] = true;
acl.rights[esp_mail_imap_rights_delete_message] = true;
acl.rights[esp_mail_imap_rights_delete_d] = true;
acl.rights[esp_mail_imap_rights_delete_mailbox] = true;
acl.rights[esp_mail_imap_rights_expunge] = true;
acl.rights[esp_mail_imap_rights_lookup] = true;
acl.rights[esp_mail_imap_rights_insert] = true;
acl.rights[esp_mail_imap_rights_post] = true;
acl.rights[esp_mail_imap_rights_read] = true;
acl.rights[esp_mail_imap_rights_write] = true;
acl.rights[esp_mail_imap_rights_seen] = true;
Serial.println("\nSet ACLs...");
if (!imap.setACL("INBOX", &acl))
{
Serial.println("Set ACLs failed");
}
else
{
Serial.println("Set ACLs success");
}
Serial.println("\nGet my rights...");
if (!imap.myRights("INBOX", &acl))
{
Serial.println("Set my rights failed");
}
else
{
Serial.print("Rights: ");
String r;
for (int i = esp_mail_imap_rights_administer; i < esp_mail_imap_rights_maxType; i++)
{
if (acl.rights[i])
r += (char)('a' + i);
}
Serial.println(r);
}
Serial.println("\nDelete ACLs...");
if (!imap.deleteACL("INBOX", "Steve"))
{
Serial.println("Set ACLs failed");
}
else
{
Serial.println("Delete ACLs success");
}
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}

View File

@ -0,0 +1,239 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to append message to mailbox.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <data.h>
#include <ESP_Mail_Client.h>
// required IMAP and SMTP
#if defined(ENABLE_IMAP) && defined(ENABLE_SMTP)
#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>"
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
/* Callback function to get the Email reading status */
void imapCallback(IMAP_Status status)
{
/* Print the current status */
Serial.println(status.info());
}
#endif
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
// required IMAP and SMTP
#if defined(ENABLE_IMAP) && defined(ENABLE_SMTP)
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
ESP_Mail_Message message[2]; // The same usage as SMTP_Message
message[0].sender.name = "Fred Foobar";
message[0].sender.email = "foobar@Blurdybloop.example.COM";
message[0].subject = "afternoon meeting";
message[0].addRecipient("Joe Mooch", "mooch@owatagu.example.net");
message[0].text.content = "Hello Joe, do you think we can meet at 3:30 tomorrow?";
message[0].text.charSet = "us-ascii";
message[0].text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
ESP_Mail_Attachment att[2]; // The same usage as SMTP_Attachment
att[0].descr.filename = "shaun.png";
att[0].descr.mime = "image/png";
att[0].blob.data = shaun_png;
att[0].blob.size = sizeof(shaun_png);
att[0].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
message[0].addAttachment(att[0]);
message[1].sender.name = "Joe Mooch";
message[1].sender.email = "mooch@OWaTaGu.example.net";
message[1].subject = "Re: afternoon meeting";
message[1].addRecipient("Fred Foobar", "foobar@blurdybloop.example.com");
message[1].text.content = "3:30 is fine with me.";
message[1].text.charSet = "us-ascii";
message[1].text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
att[1].descr.filename = "mu_law.wav";
att[1].descr.mime = "audio/basic";
att[1].blob.data = mu_law_wave;
att[1].blob.size = sizeof(mu_law_wave);
att[1].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
message[1].addAttachment(att[1]);
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
if (!imap.selectFolder(F("INBOX")))
return;
// If MULTIAPPEND extension is supported, the multiple messages will send by a single APPEND command.
// If not, one message can append for a APPEND command.
// Outlook.com does not accept flag and date/time arguments in APPEND command
if (!MailClient.appendMessage(&imap, &message[0], false /* if not last message to append */, "\\Flagged" /* flags or empty string for Outlook.com */, "Thu, 16 Jun 2022 12:30:25 -0800 (PST)" /* date/time or empty string for Outlook.com */))
MailClient.printf("Message appending error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
if (!MailClient.appendMessage(&imap, &message[1], true /* last message to append */))
MailClient.printf("Message appending error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
#endif
}
void loop()
{
}

View File

@ -0,0 +1,220 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to copy messages from the mailbox to other folder.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Define the MessageList class to add the message to copy */
MessageList toCopy;
/* Add message uid to copy to the list */
toCopy.add(3);
toCopy.add(4);
// imap.createFolder("test");
/* Copy all messages in the list to the folder "test" */
if (imap.copyMessages(&toCopy, F("test")))
MailClient.printf("\nMessages copied\n");
/* Delete all messages in the list from the opened folder (move to trash) */
// imap.deleteMessages(&toCopy);
// imap.deleteolder("test");
// imap.deleteolder("test2");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,214 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to copy messages from the mailbox to other folder using message numbers ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Copy all messages using message sequence ranges (last 10 message numbers) to the folder "test"*/
int msg_last = imap.selectedFolder().msgCount();
int msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
String sequence_set2 = String(msg_begin) + ":" + String(msg_last);
if (imap.copyMessages(sequence_set2, false /* if sequence set are message numbers not UIDs */, F("test")))
MailClient.printf("\nCopying messages using message numbers ranges success\n");
else
MailClient.printf("\nError, copying messages using message numbers ranges\n");
// imap.deleteolder("test");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,214 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to copy messages from the mailbox to other folder using UIDs ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Copy all messages using UIDs ranges (last 10 UIDs) to the folder "test" */
int uid_last = imap.getUID(imap.selectedFolder().msgCount());
int uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
String sequence_set1 = String(uid_begin) + ":" + String(uid_last);
if (imap.copyMessages(sequence_set1, true /* if sequence set are the UIDs */, F("test")))
MailClient.printf("\nCopying messages using UIDs ranges success\n");
else
MailClient.printf("\nError, copying messages using UIDs ranges\n");
// imap.deleteolder("test");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,498 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email with custom character decoding for local language.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#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);
/* Callback function to decode the string based on character set of the content */
void customCharacterDecodingCallback(IMAP_Decoding_Info *decoding);
/* 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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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);
/* Set the callback function to decode the string based on the caracter set of string */
imap.characterDecodingCallback(customCharacterDecodingCallback);
/** 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
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 headers, 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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()
{
}
void To_UTF8(IMAP_Decoding_Info *decoding)
{
decoding->decodedString = "fake decoded string "; // return the decoded string
}
void customCharacterDecodingCallback(IMAP_Decoding_Info *decoding)
{
// Serial.println("***** Data Type *****");
// 0 or IMAP_Decoding_Info::message_part_type_header or
// 1 or IMAP_Decoding_Info::message_part_type_text
// Serial.println(decoding->type);
// Serial.println("***** Charset *****");
// Serial.println(decoding->charset);
// Serial.println("***** String to Decode *****");
// Serial.println(decoding->encoded);
// The original or decoded string should be return to the process via
// decoding->decodedString
// Then rturn the decoded string back to the process.
if (strlen(decoding->charset) == 0 || strcasecmp(decoding->charset, "utf-8") == 0 || strcasecmp(decoding->charset, "us-ascii") == 0) // return original
decoding->decodedString = decoding->data;
else // decode to UTF-8 or ASCII
To_UTF8(decoding);
}
/* Callback function to get the Email reading status */
void imapCallback(IMAP_Status status)
{
/* Print the current status */
MailClient.printf(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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,221 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to append new message to mailbox using the custom IMAP command.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(IMAP_Response res)
{
// The server responses will included tagged and/or untagged data.
// Tagged data is the status which begins with command identifier (tag) i.e. "A01" in this case.
// Tagged status responses included OK, NO, BAD, PREAUTH and BYE.
// Untagged data is the information or result of the request which begins with *
// When you send multiple commands with different tag simultaneously,
// tag will be used as command identifier.
MailClient.printf("> C: TAG %s\n", res.tag.c_str());
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.completed)
{
MailClient.printf("> C: Response finished with status %s\n\n", res.status.c_str());
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* 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;
/* Connect to the server */
if (!imap.customConnect(&config, customCommandCallback, F("A01") /* tag */))
return;
String cmd = F("LOGIN ");
cmd += AUTHOR_EMAIL;
cmd += F(" ");
cmd += AUTHOR_PASSWORD;
// You can also assign tag to the begining of the command e.g. "A01 FETCH 1 UID"
// Do not assign tag to command when you assign tag to the last parameter of function.
imap.sendCustomCommand(cmd, customCommandCallback, F("A02") /* tag */);
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.\n");
else
Serial.println("\nConnected with no Auth.\n");
imap.sendCustomCommand(F("SELECT \"INBOX\""), customCommandCallback, F("A03") /* tag */);
imap.sendCustomCommand(F("LIST \"\" *"), customCommandCallback, F("A04") /* tag */);
String appendMsg = "Date: Thu, 16 Jun 2022 12:30:25 -0800 (PST)\r\n";
appendMsg += "From: Jack <jack@host.com>\r\n";
appendMsg += "Subject: Greeting from ESP Mail\r\n";
appendMsg += "To: joe@host.com\r\n";
appendMsg += "Message-Id: <jack@host.com>\r\n";
appendMsg += "MIME-Version: 1.0\r\n";
appendMsg += "Content-Type: text/plain; charset=\"us-ascii\"\r\n";
appendMsg += "Content-transfer-encoding: 7bit\r\n";
appendMsg += "\r\n";
appendMsg += "Hello Joe, this is the append message\r\n";
String appendMsgCmd = "APPEND INBOX {" + String(appendMsg.length()) + "}";
imap.sendCustomCommand(appendMsgCmd, customCommandCallback, F("A05") /* tag */);
imap.sendCustomData(appendMsg, true /* flag states the last data to send */);
}
void loop()
{
}

View File

@ -0,0 +1,197 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send custom IMAP command and get the response.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(IMAP_Response res)
{
// The server responses will included tagged and/or untagged data.
// Tagged data is the status which begins with command identifier (tag) i.e. "A01" in this case.
// Tagged status responses included OK, NO, BAD, PREAUTH and BYE.
// Untagged data is the information or result of the request which begins with *
// When you send multiple commands with different tag simultaneously,
// tag will be used as command identifier.
MailClient.printf("> C: TAG %s\n", res.tag.c_str());
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.completed)
{
MailClient.printf("> C: Response finished with status %s\n\n", res.status.c_str());
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
// This debug required for showing debug info from imap.connect
imap.debug(1);
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.\n");
else
Serial.println("\nConnected with no Auth.\n");
// You can also assign tag to the begining of the command e.g. "A01 FETCH 1 UID"
// Do not assign tag to command when you assign tag to the last parameter of function.
imap.sendCustomCommand(F("SELECT \"INBOX\""), customCommandCallback, F("A01") /* tag */);
imap.sendCustomCommand(F("LIST \"\" *"), customCommandCallback, F("A02") /* tag */);
imap.sendCustomCommand(F("FETCH 1 UID"), customCommandCallback, F("A03") /* tag */);
}
void loop()
{
}

View File

@ -0,0 +1,197 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send custom IMAP command and get the response.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(IMAP_Response res)
{
// The server responses will included tagged and/or untagged data.
// Tagged data is the status which begins with command identifier (tag) i.e. "A01" in this case.
// Tagged status responses included OK, NO, BAD, PREAUTH and BYE.
// Untagged data is the information or result of the request which begins with *
// When you send multiple commands with different tag simultaneously,
// tag will be used as command identifier.
MailClient.printf("> C: TAG %s\n", res.tag.c_str());
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.completed)
{
MailClient.printf("> C: Response finished with status %s\n\n", res.status.c_str());
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* 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;
/* Connect to the server */
if (!imap.customConnect(&config, customCommandCallback, F("A01") /* tag */))
return;
String cmd = F("LOGIN ");
cmd += AUTHOR_EMAIL;
cmd += F(" ");
cmd += AUTHOR_PASSWORD;
// You can also assign tag to the begining of the command e.g. "A01 FETCH 1 UID"
// Do not assign tag to command when you assign tag to the last parameter of function.
imap.sendCustomCommand(cmd, customCommandCallback, F("A02") /* tag */);
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.\n");
else
Serial.println("\nConnected with no Auth.\n");
imap.sendCustomCommand(F("SELECT \"INBOX\""), customCommandCallback, F("A03") /* tag */);
imap.sendCustomCommand(F("LIST \"\" *"), customCommandCallback, F("A04") /* tag */);
imap.sendCustomCommand(F("FETCH 1 UID"), customCommandCallback, F("A05") /* tag */);
}
void loop()
{
}

View File

@ -0,0 +1,220 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to receive mailbox updates by sending the custom IMAP command IDLE.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
unsigned long lastIdleTerminatedMillis = 0;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(IMAP_Response res)
{
// The server responses will included tagged and/or untagged data.
// Tagged data is the status which begins with command identifier (tag) i.e. "A01" in this case.
// Tagged status responses included OK, NO, BAD, PREAUTH and BYE.
// Untagged data is the information or result of the request which begins with *
// When you send multiple commands with different tag simultaneously,
// tag will be used as command identifier.
MailClient.printf("> C: TAG %s\n", res.tag.c_str());
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.completed)
{
MailClient.printf("> C: Response finished with status %s\n\n", res.status.c_str());
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* 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;
/* Connect to the server */
if (!imap.customConnect(&config, customCommandCallback, F("A01") /* tag */))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.\n");
else
Serial.println("\nConnected with no Auth.\n");
String cmd = F("LOGIN ");
cmd += AUTHOR_EMAIL;
cmd += F(" ");
cmd += AUTHOR_PASSWORD;
// You can also assign tag to the begining of the command e.g. "A01 FETCH 1 UID"
// Do not assign tag to command when you assign tag to the last parameter of function.
imap.sendCustomCommand(cmd, customCommandCallback, F("A02") /* tag */);
imap.sendCustomCommand(F("SELECT \"INBOX\""), customCommandCallback, F("A03") /* tag */);
imap.sendCustomCommand(F("LIST \"\" *"), customCommandCallback, F("A04") /* tag */);
}
void loop()
{
if (imap.connected())
{
if (!imap.sendCustomCommand(F("IDLE"), customCommandCallback, F("A05") /* tag */))
{
// If error, need to re-connect if imap.connected() returns false and re-log in again
Serial.println("\nTCP connection closed!");
return;
}
if (millis() - lastIdleTerminatedMillis > 20 * 60 * 1000) // terminate the IDLE every 20 min.
{
lastIdleTerminatedMillis = millis();
imap.sendCustomCommand(F("DONE"), customCommandCallback, "" /* don't include tag for DONE command */);
}
}
}
/**
* The server MAY consider a client inactive if it has an IDLE command
* running, and if such a server has an inactivity timeout it MAY log
* the client off implicitly at the end of its timeout period. Because
* of that, clients using IDLE are advised to terminate the IDLE and
* re-issue it at least every 29 minutes to avoid being logged off.
*/

View File

@ -0,0 +1,256 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to assign the custom ports with protocols to access IMAP server.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.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 // Plain or TLS with STARTTLS
* 993 or esp_mail_imap_port_993
*/
#define IMAP_PORT esp_mail_imap_port_143
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* Print the selected folder info */
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/** 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
*/
/* 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;
/** Set the ports and protocols
* The port that assigned with config.server.port will map with the
* protocol assigned here
*/
config.ports_functions.list = new port_function[2];
config.ports_functions.size = 2;
config.ports_functions.list[0].port = 143;
config.ports_functions.list[0].protocol = esp_mail_protocol_tls;
config.ports_functions.list[1].port = 993;
config.ports_functions.list[1].protocol = esp_mail_protocol_ssl;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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());
/* Close the seeion in case the session is still open */
imap.closeSession();
/* Clear all stored data in IMAPSession object */
imap.empty();
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}

View File

@ -0,0 +1,368 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email and collect the stream data to print or store via the callback function.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#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>"
void mimeDataStreamCallback(MIME_Data_Stream_Info streaminfo);
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
int progress = 0;
int lastProgress = -1;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* Set the callback function to get MIME Data stream */
imap.mimeDataStreamCallback(mimeDataStreamCallback);
/** 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
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 headers, 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Open or select the mailbox folder to read or search the message */
if (!imap.selectFolder(F("INBOX")))
return;
/** 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());
/* 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()
{
}
void mimeDataStreamCallback(MIME_Data_Stream_Info streaminfo)
{
if (streaminfo.isFirstData)
{
progress = 0;
lastProgress = -1;
Serial.print("Message UID: ");
Serial.println(streaminfo.uid);
Serial.print("Content Type: ");
Serial.println(streaminfo.type);
Serial.print("Content Disposition: ");
Serial.println(streaminfo.disposition);
Serial.print("Text Character Set: ");
Serial.println(streaminfo.charSet);
Serial.print("Content Transfer Encoding: ");
Serial.println(streaminfo.transfer_encoding);
// The total octets of encoded or non-encoded MIME content.
// The size of decoded content may be different.
Serial.print("Total Octets: ");
Serial.println(streaminfo.octet_size);
if (strcmp(streaminfo.disposition, "attachment") == 0 || strcmp(streaminfo.disposition, "inline") == 0)
{
if (strcmp(streaminfo.disposition, "inline") == 0)
{
Serial.print("Content ID: ");
Serial.println(streaminfo.cid);
}
Serial.print("Name: ");
Serial.println(streaminfo.name);
Serial.print("File Name: ");
Serial.println(streaminfo.filename);
Serial.print("Size: ");
Serial.println(streaminfo.size);
Serial.print("Content Description: ");
Serial.println(streaminfo.description);
Serial.print("Creation Date: ");
Serial.println(streaminfo.date);
}
Serial.println("Content:");
}
progress = 100 * streaminfo.octet_count / streaminfo.octet_size;
if (progress != lastProgress && (progress == 0 || progress == 100 || lastProgress + 5 <= progress))
{
lastProgress = progress;
// The size of current decoded chunk data
Serial.print("Data Length: ");
Serial.print(streaminfo.data_size);
Serial.print(", Reading %: ");
Serial.println(progress);
}
// Decoded chunk data is available here
if (streaminfo.data)
{
// If streaminfo.transfer_encoding is 'base64',
// to print or send null terminated string from stream data
/**
char str[streaminfo.data_size + 1];
memcpy(str, streaminfo.data, streaminfo.data_size);
str[streaminfo.data_size] = 0;
Serial.print(str);
*/
// If streaminfo.transfer_encoding is not 'base64', the string can be
// taken directly from casting streaminfo.data as (const char*)streaminfo.data
// To write data to file (if fs is File class object that open in appended mode)
// fs.write((uint8_t *)streaminfo.data, streaminfo.data_size);
// streaminfo.data_size is not more than 512
}
if (streaminfo.isLastData)
{
Serial.println();
Serial.println();
}
}

View File

@ -0,0 +1,218 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to delete messages from the mailbox.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Define the MessageList class to add the message to delete */
MessageList toDelete;
/** Add message uid to delete to the list
* In this case we will delete last 10 messages by get the UID of these message
* and add it to the list
*/
for (int i = imap.selectedFolder().msgCount(); i > (int)imap.selectedFolder().msgCount() - 10 && i > 0; i--)
toDelete.add(imap.getUID(i));
/* Delete all messages in the list (move to trash) */
if (imap.deleteMessages(&toDelete))
Serial.println("\nMessages deleted");
/* Delete all messages permanently by assign the second param to true*/
// imap.deleteMessages(&toDelete, true);
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,229 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to delete messages from the mailbox using message numbers ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Copy all messages using UIDs ranges (last 10 message numbers) to the folder "test" */
int msg_last = imap.selectedFolder().msgCount();
int msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
String sequence_set1 = String(msg_begin) + ":" + String(msg_last);
if (imap.copyMessages(sequence_set1, true /* if sequence set are the UIDs */, F("test")))
Serial.println("\nCopying messages using message numbers ranges success");
else
Serial.println("\nError, copying messages using message numbers ranges");
/* Open or select the mailbox folder to read or search the message */
if (!imap.selectFolder(F("test")))
return;
delay(10000);
/* Delete all messages using UIDs ranges (last 10 message numbers) from the folder "test" */
msg_last = imap.selectedFolder().msgCount();
msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
sequence_set1 = String(msg_begin) + ":" + String(msg_last);
if (imap.deleteMessages(sequence_set1, true /* if sequence set are the UIDs */, false))
Serial.println("\nDeleting messages using message numbers ranges success");
else
Serial.println("\nError, Deleting messages using message numbers ranges");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,229 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to delete messages from the mailbox using UIDs ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Copy all messages using UIDs ranges (last 10 UIDs) to the folder "test" */
int uid_last = imap.getUID(imap.selectedFolder().msgCount());
int uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
String sequence_set1 = String(uid_begin) + ":" + String(uid_last);
if (imap.copyMessages(sequence_set1, true /* if sequence set are the UIDs */, F("test")))
Serial.println("Copying messages using UIDs ranges success");
else
Serial.println("Error, copying messages using UIDs ranges");
/* Open or select the mailbox folder to read or search the message */
if (!imap.selectFolder(F("test")))
return;
delay(10000);
/* Delete all messages using UIDs ranges (last 10 UIDs) from the folder "test" */
uid_last = imap.getUID(imap.selectedFolder().msgCount());
uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
sequence_set1 = String(uid_begin) + ":" + String(uid_last);
if (imap.deleteMessages(sequence_set1, true /* if sequence set are the UIDs */, false))
Serial.println("Deleting messages using UIDs ranges success");
else
Serial.println("Error, Deleting messages using UIDs ranges");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,334 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
/**
* This example shows how to send Email using EthernetClient.
*
* This example used ESP32 and WIZnet W5500 Ethernet module.
*
* Please see examples/SMTP/Ethernet and examples/SMTP/External_Client for more usage
*/
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#include <ESP_Mail_Client.h>
#include <Ethernet.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define IMAP_HOST "<host>"
#define IMAP_PORT 993
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
void imapCallback(IMAP_Status status);
void printAllMailboxesInfo(IMAPSession &imap);
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
void printMessages(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
void printAttacements(std::vector<IMAP_Attach_Item> &atts);
IMAPSession imap;
EthernetClient eth_client;
void networkConnection()
{
// Reset the network connection
WiFi.disconnect();
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
unsigned long ms = millis();
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(300);
if (millis() - ms >= 5000)
{
Serial.println(" failed!");
return;
}
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
Serial.println();
}
void networkStatusRequestCallback()
{
imap.setNetworkStatus(WiFi.status() == WL_CONNECTED);
}
void setup()
{
Serial.begin(115200);
Serial.println();
MailClient.networkReconnect(true);
// The WiFi credentials are required for SAMD21
// due to it does not have reconnect feature.
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
networkConnection();
imap.debug(1);
/*
For internal NTP client
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
MailClient.setUDPClient(&udp_client, 0 /* GMT offset */);
MailClient.networkReconnect(true);
imap.callback(imapCallback);
Session_Config config;
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
IMAP_Data imap_data;
imap_data.search.criteria.clear();
imap_data.search.unseen_msg = true;
imap_data.storage.saved_path = F("/email_data");
imap_data.storage.type = esp_mail_file_storage_type_flash;
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;
imap_data.enable.html = true;
imap_data.enable.text = true;
imap_data.enable.recent_sort = true;
imap_data.enable.download_status = true;
imap_data.limit.search = 5;
imap_data.limit.msg_size = 512;
imap_data.limit.attachment_size = 1024 * 1024 * 5;
imap.setClient(&eth_client);
imap.networkConnectionRequestCallback(networkConnection);
imap.networkStatusRequestCallback(networkStatusRequestCallback);
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
printAllMailboxesInfo(imap);
if (!imap.selectFolder(F("INBOX")))
return;
printSelectedMailboxInfo(imap.selectedFolder());
imap_data.fetch.uid = imap.getUID(imap.selectedFolder().msgCount());
MailClient.readMail(&imap);
imap.empty();
}
void loop()
{
}
void imapCallback(IMAP_Status status)
{
Serial.println(status.info());
if (status.success())
{
IMAP_MSG_List msgList = imap.data();
printMessages(msgList.msgItems, imap.headerOnly());
imap.empty();
}
}
void printAllMailboxesInfo(IMAPSession &imap)
{
FoldersCollection folders;
if (imap.getFolders(folders))
{
for (size_t i = 0; i < folders.size(); i++)
{
FolderInfo folderInfo = folders.info(i);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.printf("Attachment: %d file(s)\n****************************\n", atts.size());
for (size_t j = 0; j < atts.size(); j++)
{
IMAP_Attach_Item att = atts[j];
MailClient.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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly)
{
for (size_t i = 0; i < msgItems.size(); i++)
{
IMAP_MSG_Item msg = msgItems[i];
Serial.println("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,464 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email and update firmware if firmware file name in attachments matches.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::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);
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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Set the storage to save the downloaded files and attachments */
imap_data.storage.saved_path = F("/email_data");
/** 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;
/* Assign the attachment filename to compare, update firmware if it matches */
imap_data.firmware_update.attach_filename = "firmware.bin";
/* save (download) firmware to file? */
imap_data.firmware_update.save_to_file = false;
/**
* Device will reboot in if imap.isFirmwareUpdated() returns true in imapCallback function.
* To disable firmware update, call imap_data.firmware_update.attach_filename.clear(); or
* imap_data.firmware_update.attach_filename = "";
*
*/
/* 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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();
if (imap.isFirmwareUpdateSuccess())
{
Serial.println("****************************");
Serial.println("Firmware is already updated, restarting device...");
delay(2000);
#if defined(ESP32) || defined(ESP8266)
ESP.restart();
#elif defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_NANO_RP2040_CONNECT)
rp2040.restart();
#endif
}
}
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,215 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to get the quota root's resource usage and limits.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
IMAP_Quota_Root_Info info;
Serial.println("\nGet quota root...");
if (!imap.getQuota("", &info))
{
Serial.println("Get quota root failed");
}
else
{
MailClient.printf("Quota root: %s, Resource name: %s, Usage (k): %d, Limit (k): %d\n", info.quota_root.c_str(), info.name.c_str(), (int)info.usage, (int)info.limit);
}
IMAP_Quota_Roots_List quota_roots;
Serial.println("\nGet quota roots list for INBOX folder...");
if (!imap.getQuotaRoot("INBOX", &quota_roots))
{
Serial.println("\nGet quota roots list failed");
}
else
{
for (size_t i = 0; i < quota_roots.size(); i++)
MailClient.printf("%d, Quota root: %s, Resource name: %s, Usage (k): %d, Limit (k): %d\n", (int)i + 1, quota_roots[i].quota_root.c_str(), quota_roots[i].name.c_str(), (int)quota_roots[i].usage, (int)quota_roots[i].limit);
}
Serial.println("\nSet quota root...");
info.name = "STORAGE";
info.limit = 1024 * 1024; // 1048576 k or 1 G.
if (!imap.setQuota("", &info))
{
Serial.println("\nSet quota root failed");
}
else
{
Serial.println("\nSet quota root success");
}
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}

View File

@ -0,0 +1,446 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to get notification in realtime when incoming message arrived and other mailbox changes.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the selected folder update info */
void printPollingStatus(IMAPSession &imap);
/* 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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::vector<IMAP_Attach_Item> &atts);
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
/* Declare the global used Session_Config for user defined session credentials */
Session_Config config;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void connectWiFi()
{
WiFi.disconnect();
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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#endif
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
connectWiFi();
/** 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
*/
/* 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;
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/** Assign internet connection handler function
* in case of lost internet connection for re-listening the mailbox.
*/
config.network_connection_handler = connectWiFi;
// You can use TCP KeepAlive for more reliable of listen (idle) operation, please read this for detail.
// https://github.com/mobizt/ESP-Mail-Client#using-tcp-session-keepalive-in-esp8266-and-esp32
// You can use keepAlive in ESP8266 core version newer than v3.1.2.
// Or you can use git version (v3.1.2) https://github.com/esp8266/Arduino
#if defined(ESP32)
imap.keepAlive(5, 5, 1);
#endif
/* Set the TCP response read timeout in seconds */
// smtp.setTCPTimeout(10);
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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());
}
void loop()
{
/* imap.connect and imap.selectFolder or imap.openFolder nedded to be called once prior to listen */
// Listen for mailbox changes
if (!imap.listen())
return;
// Check the changes
if (imap.folderChanged())
printPollingStatus(imap);
// To stop listen, use imap.stopListen(); and to listen again, call imap.listen()
}
void printPollingStatus(IMAPSession &imap)
{
/* Declare the selected folder info class to get the info of selected mailbox folder */
SelectedFolderInfo sFolder = imap.selectedFolder();
/* Show the mailbox info */
MailClient.printf("\nMailbox status changed\n----------------------\nTotal Messages: %d\n", sFolder.msgCount());
if (sFolder.pollingStatus().type == imap_polling_status_type_new_message)
{
MailClient.printf("New message %d, has been addedd, reading message...\n", (int)sFolder.pollingStatus().messageNum);
// if (sFolder.recentCount() > 0)
// MailClient.printf("\nMesssage count which recent flag set: %d\n", sFolder.recentCount());
// we need to stop polling before do anything
imap.stopListen();
// Get the UID of new message and fetch
imap_data.fetch.uid = imap.getUID(sFolder.pollingStatus().messageNum);
MailClient.readMail(&imap, false);
}
else if (sFolder.pollingStatus().type == imap_polling_status_type_remove_message)
MailClient.printf("Message %d, has been removed\n\n", (int)sFolder.pollingStatus().messageNum);
else if (sFolder.pollingStatus().type == imap_polling_status_type_fetch_message)
MailClient.printf("Message %d, has been fetched with the argument %s\n\n", (int)sFolder.pollingStatus().messageNum, sFolder.pollingStatus().argument.c_str());
}
/* 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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly)
{
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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.printf("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
printMessages(msg.rfc822, headerOnly);
}
}
Serial.println();
}
}

View File

@ -0,0 +1,214 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to move messages from the mailbox to other folder.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Define the MessageList class to add the message to move */
MessageList toMove;
/* Add message uid to move to the list */
toMove.add(3);
toMove.add(4);
// imap.createFolder("test");
/* Move all messages in the list to the folder "test" */
if (imap.moveMessages(&toMove, F("test")))
Serial.println("\nMessages moved");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,213 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to move messages from the mailbox to other folder using message numbers ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Move all messages using message sequence ranges (last 10 message numbers) to the folder "test"*/
int msg_last = imap.selectedFolder().msgCount();
int msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
String sequence_set2 = String(msg_begin) + ":" + String(msg_last);
if (imap.moveMessages(sequence_set2, false /* if sequence set are message numbers not UIDs */, F("test")))
Serial.println("\nMoving messages using message numbers ranges success");
else
Serial.println("\nError, moving messages using message numbers ranges");
// imap.deleteolder("test");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,214 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to move messages from the mailbox to other folder using UIDs ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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;
/* Move all messages using UIDs ranges (last 10 UIDs) to the folder "test" */
int uid_last = imap.getUID(imap.selectedFolder().msgCount());
int uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
String sequence_set1 = String(uid_begin) + ":" + String(uid_last);
if (imap.moveMessages(sequence_set1, true /* if sequence set are the UIDs */, F("test")))
Serial.println("\nMoving messages using UIDs ranges success");
else
Serial.println("\nError, moving messages using UIDs ranges");
// imap.deleteolder("test");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}

View File

@ -0,0 +1,216 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to get the namespaces.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Open or select the mailbox folder to read or search the message */
if (!imap.selectFolder(F("INBOX")))
return;
IMAP_Namespaces_List ns_list;
Serial.println("\nGet namespaces...");
if (!imap.getNamespace(&ns_list))
{
Serial.println("\nGet namespaces failed");
}
else
{
if (ns_list.personal_namespaces.size() > 0)
{
Serial.println("\nPersonal Namespaces...");
for (size_t i = 0; i < ns_list.personal_namespaces.size(); i++)
{
MailClient.printf("Prefix: %s, Delimiter: %s\n", ns_list.personal_namespaces[i].prefix.c_str(), ns_list.personal_namespaces[i].delimiter.c_str());
}
}
if (ns_list.other_users_namespaces.size() > 0)
{
Serial.println("\nOther Users Namespaces...");
for (size_t i = 0; i < ns_list.other_users_namespaces.size(); i++)
{
MailClient.printf("Prefix: %s, Delimiter: %s\n", ns_list.other_users_namespaces[i].prefix.c_str(), ns_list.other_users_namespaces[i].delimiter.c_str());
}
}
if (ns_list.shared_namespaces.size() > 0)
{
Serial.println("\nShared Namespaces...");
for (size_t i = 0; i < ns_list.shared_namespaces.size(); i++)
{
MailClient.printf("Prefix: %s, Delimiter: %s\n", ns_list.shared_namespaces[i].prefix.c_str(), ns_list.shared_namespaces[i].delimiter.c_str());
}
}
}
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}

View File

@ -0,0 +1,472 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example will log in with the SASL XOAUTH2 mechanisme using OAuth2.0 access token.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only IMAP functions, you can exclude the SMTP from compilation, see ESP_Mail_FS.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>"
/** The OAuth2.0 access token
* The generation, exchange and refresh of the access token are not available
* in this library.
*
* To test this using GMail, get the OAuth2.0 access token from this web site
* https://developers.google.com/oauthplayground/
*
* 1. Select the following scope (in Step 1) from Gmail API V1
* https://mail.google.com/
* https://mail.google.com/
*
* 2. Click Authorize APIs button.
* 3. Cick Exchangeauthorization code for tokens.
* 4. From the response, look at access_token from the JSON payload node.
* 5. Copy that access token and paste to the AUTHOR_ACCESS_TOKEN value.
*
* The token will be expired in 3600 seconds (1 Hr).
* The AUTHOR_EMAIL above is the Email address that you granted to access the Gmail services.
*/
#define AUTHOR_ACCESS_TOKEN "<access token>"
/* 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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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.accessToken = AUTHOR_ACCESS_TOKEN;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Message UID to fetch or read e.g. 100 */
imap_data.fetch.uid = imap.getUID(imap.selectedFolder().msgCount());
/* Set seen flag*/
// imap_data.fetch.set_seen = true;
/* Search criteria */
imap_data.search.criteria.clear();
/* Also search the unseen message */
imap_data.search.unseen_msg = true;
/* 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_flash;
/** Set to download headers, 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
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());
/* 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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,477 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email using UIDs ranges or message numbers ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::vector<IMAP_Attach_Item> &atts);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void readEmailsUIDS()
{
int uid_last = imap.getUID(imap.selectedFolder().msgCount());
int uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
// Fetch last 10 UIDs
String sequence_set = String(uid_begin) + ":" + String(uid_last);
imap_data.fetch.sequence_set.string = sequence_set;
imap_data.fetch.sequence_set.UID = true; // The sequence set are UIDs ranges
imap_data.fetch.sequence_set.headerOnly = true; // Do not fetch the content, header only
MailClient.readMail(&imap, false /* do not close sessiopn */);
imap_data.limit.fetch = 5; // Set the limit of number of messages in the fetch results
}
void readEmailsNumbers()
{
int msg_last = imap.selectedFolder().msgCount();
int msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
String sequence_set = String(msg_begin) + ":" + String(msg_last);
imap_data.fetch.sequence_set.string = sequence_set;
imap_data.fetch.sequence_set.UID = false; // The sequence set are not UIDs
imap_data.fetch.sequence_set.headerOnly = true; // Do not fetch the content, header only
imap_data.limit.fetch = 5; // Set the limit of number of messages in the fetch results
// Read Email and close session
MailClient.readMail(&imap);
/* Clear all stored data in IMAPSession object */
imap.empty();
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
/* 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;
/* Set the storage to save the downloaded files and attachments */
imap_data.storage.saved_path = F("/email_data");
/** 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 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;
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
// 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
* MailClient.printf("nIdentification sending error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
*/
/* {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());
Serial.println("::::::::::::::::: Reading Emails using the UIDs ranges ::::::::::::::::");
readEmailsUIDS();
Serial.println("::::::::::: Reading Emails using the message numbers ranges :::::::::::");
readEmailsNumbers();
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,516 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email and store the message in SD card.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
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 headers, 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";
/* Set the TCP response read timeout in seconds */
// imap.setTCPTimeout(10);
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
/** Or connect without log in and log in later
if (!imap.connect(&config, &imap_data, false))
return;
if (!imap.loginWithPassword(AUTHOR_EMAIL, AUTHOR_PASSWORD))
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
* MailClient.printf("nIdentification sending error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
*/
if (!imap.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
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());
// if IMAP server supports CONDSTORE extension, the modification sequence can be assign to fetch command
// Note that modsequence value supports in this library is 32-bit integer
imap_data.fetch.modsequence = 123;
// To fetch only header part
// imap_data.fetch.headerOnly = true;
// 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;
/* Fetch or read only message header */
// imap_data.fetch.headerOnly = 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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,561 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email repeatedly.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
/** 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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::vector<IMAP_Attach_Item> &atts);
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
unsigned long readMillis = 0;
int totalMessage = 0;
int msgNum = 0;
int sign = -1;
/* Declare the global used Session_Config for user defined session credentials */
Session_Config config;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
// For Free Heap checking
#include "HeapStat.h"
HeapStat heapInfo;
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
*/
/* 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;
/* Message UID to fetch or read */
imap_data.fetch.uid.clear();
/* Search criteria */
imap_data.search.criteria.clear();
/* Also search the unseen message */
imap_data.search.unseen_msg = true;
/* 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 headers, text and html messaeges,
* attachments and inline images respectively.
*/
imap_data.download.header = false;
imap_data.download.text = false;
imap_data.download.html = false;
imap_data.download.attachment = false;
imap_data.download.inlineImg = false;
/** 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";
/* Set the TCP response read timeout in seconds */
// imap.setTCPTimeout(10);
/* 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
* MailClient.printf("nIdentification sending error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
*/
if (!imap.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
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());
totalMessage = imap.selectedFolder().msgCount();
/* Start fetch from last message */
msgNum = totalMessage;
sign = -1; // count down
/* To start fetch from first message */
// msgNum = 1;
// sign = 1;// count up
}
void loop()
{
if (millis() - readMillis > 10000 || readMillis == 0)
{
readMillis = millis();
// If session was closed, reconnect and re-select the mailbox
if (!imap.connected())
{
if (!imap.connect(&config, &imap_data))
return;
if (!imap.selectFolder(F("INBOX")))
return;
if (totalMessage == 0)
{
totalMessage = imap.selectedFolder().msgCount();
msgNum = totalMessage;
sign = -1;
}
}
if (msgNum <= 0)
{
msgNum = 1;
sign = 1;
}
else if (msgNum >= totalMessage)
{
msgNum = totalMessage;
sign = -1;
}
/* Message number to fetch or read */
imap_data.fetch.number = msgNum;
/* Set seen flag */
// imap_data.fetch.set_seen = true;
/* Fetch or read only message header */
// imap_data.fetch.headerOnly = true;
/** Read or search the Email and keep the TCP session to open
* The second parameter is for 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.
if (MailClient.readMail(&imap, false))
msgNum += sign;
/* Clear all stored data in IMAPSession object */
imap.empty();
msgNum += sign;
}
}
/* 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();
// Collect memory info
heapInfo.collect();
// Print memory info
heapInfo.print();
}
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::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("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,402 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to read Email repeatedly.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/**
* To use library in silent mode (no debug printing and callback), please define this macro in src/ESP_Mail_FS.h.
* #define SILENT_MODE
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#include <extras/SDHelper.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define IMAP_HOST "<host>"
#define IMAP_PORT 993
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
void printImapData(IMAP_Status status);
void printAllMailboxesInfo(IMAPSession &imap);
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
void printMessages(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
void printAttacements(std::vector<IMAP_Attach_Item> &atts);
IMAPSession imap;
unsigned long readMillis = 0;
int totalMessage = 0;
int msgNum = 0;
int sign = -1;
Session_Config config;
IMAP_Data imap_data;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
// For Free Heap checking
#include "HeapStat.h"
HeapStat heapInfo;
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
MailClient.networkReconnect(true);
#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
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
imap_data.fetch.uid.clear();
imap_data.search.criteria.clear();
imap_data.search.unseen_msg = true;
imap_data.storage.saved_path = F("/email_data");
imap_data.storage.type = esp_mail_file_storage_type_sd;
imap_data.download.header = false;
imap_data.download.text = false;
imap_data.download.html = false;
imap_data.download.attachment = false;
imap_data.download.inlineImg = false;
imap_data.enable.html = true;
imap_data.enable.text = true;
imap_data.enable.recent_sort = true;
imap_data.enable.download_status = true;
imap_data.limit.search = 5;
imap_data.limit.msg_size = 512;
imap_data.limit.attachment_size = 1024 * 1024 * 5;
if (!imap.connect(&config, &imap_data))
{
MailClient.printf("Connection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
printAllMailboxesInfo(imap);
if (!imap.selectFolder(F("INBOX")))
{
MailClient.printf("Folder selection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
printSelectedMailboxInfo(imap.selectedFolder());
totalMessage = imap.selectedFolder().msgCount();
msgNum = totalMessage;
sign = -1; // count down
}
void loop()
{
if (millis() - readMillis > 10000 || readMillis == 0)
{
readMillis = millis();
if (!imap.connected())
{
if (!imap.connect(&config, &imap_data))
return;
if (!imap.selectFolder(F("INBOX")))
return;
if (totalMessage == 0)
{
totalMessage = imap.selectedFolder().msgCount();
msgNum = totalMessage;
sign = -1;
}
}
if (msgNum <= 0)
{
msgNum = 1;
sign = 1;
}
else if (msgNum >= totalMessage)
{
msgNum = totalMessage;
sign = -1;
}
imap_data.fetch.number = msgNum;
if (MailClient.readMail(&imap, false))
{
printImapData(imap.status());
}
else
{
MailClient.printf("Message reading error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
}
imap.empty();
msgNum += sign;
}
}
void printImapData(IMAP_Status status)
{
if (status.success())
{
IMAP_MSG_List msgList = imap.data();
printMessages(msgList.msgItems, imap.headerOnly());
imap.empty();
heapInfo.collect();
heapInfo.print();
Serial.println();
}
}
void printAllMailboxesInfo(IMAPSession &imap)
{
FoldersCollection folders;
if (imap.getFolders(folders))
{
for (size_t i = 0; i < folders.size(); i++)
{
FolderInfo folderInfo = folders.info(i);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.printf("Attachment: %d file(s)\n****************************\n", atts.size());
for (size_t j = 0; j < atts.size(); j++)
{
IMAP_Attach_Item att = atts[j];
MailClient.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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly)
{
for (size_t i = 0; i < msgItems.size(); i++)
{
IMAP_MSG_Item msg = msgItems[i];
Serial.println("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,352 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to search the unread messages and read them.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/**
* To use library in silent mode (no debug printing and callback), please define this macro in src/ESP_Mail_FS.h.
* #define SILENT_MODE
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#include <extras/SDHelper.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define IMAP_HOST "<host>"
#define IMAP_PORT 993
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
void imapCallback(IMAP_Status status);
void printAllMailboxesInfo(IMAPSession &imap);
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
void printMessageData();
IMAPSession imap;
Session_Config config;
IMAP_Data imap_data;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
// Max messages in the search result
int max_result = 5;
// Array to store the UID of messages in search result
int msg_uid[5];
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#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);
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
// Clear all these fetch options to perform search
imap_data.fetch.uid.clear();
imap_data.fetch.number.clear();
imap_data.fetch.sequence_set.string.clear();
imap_data.search.unseen_msg = true;
// Don't download all to filesystem
imap_data.download.header = false;
imap_data.download.text = false;
imap_data.download.html = false;
imap_data.download.attachment = false;
imap_data.download.inlineImg = false;
// Store html/text message body in IMAPSession object
imap_data.enable.html = true;
imap_data.enable.text = true;
imap_data.enable.recent_sort = true;
// Max messages in the search result
imap_data.limit.search = max_result;
imap_data.limit.msg_size = 128;
if (!imap.connect(&config, &imap_data))
{
MailClient.printf("Connection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
printAllMailboxesInfo(imap);
if (!imap.selectFolder(F("INBOX")))
{
MailClient.printf("Folder selection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
printSelectedMailboxInfo(imap.selectedFolder());
// We search the unseen messages first to get its UID and stored in msg_uid.
imap_data.search.criteria = F("SEARCH UNSEEN");
MailClient.readMail(&imap, false /* keep session open for fetching message in opened mailbox later */);
// We already get the search result message, fetch it
// Fetch the messages using UID stored in msg_uid one by one
for (int i = 0; i < max_result; i++)
{
imap_data.search.criteria.clear();
// Mark this message as read
MailClient.addFlag(&imap, msg_uid[i], F("\\Seen"), false /* Close session */, false /* Ignore response */);
// Now Fech message by UID stored in msg_uid
imap_data.fetch.uid = msg_uid[i];
MailClient.readMail(&imap, false /* keep session open for fetching message in opened mailbox later */);
}
imap.closeSession();
imap.empty();
}
void loop()
{
}
void imapCallback(IMAP_Status status)
{
Serial.println(status.info());
if (status.success())
{
// If this is the search result (imap contains only header info),
// store the message UID that we can fetch for its body later.
if (imap.headerOnly())
{
max_result = imap.data().msgItems.size();
for (size_t i = 0; i < imap.data().msgItems.size(); i++)
msg_uid[i] = imap.data().msgItems[i].UID;
}
else
{
// This is the fetch result, print the whole message (header + body)
printMessageData();
}
imap.empty();
}
}
void printAllMailboxesInfo(IMAPSession &imap)
{
FoldersCollection folders;
if (imap.getFolders(folders))
{
for (size_t i = 0; i < folders.size(); i++)
{
FolderInfo folderInfo = folders.info(i);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printMessageData()
{
IMAP_MSG_Item msg = imap.data().msgItems[0]; // msgItems contains only one message from fetch
Serial.println("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
Serial.println();
}

View File

@ -0,0 +1,533 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to search all messages with the keywords in the opened mailbox folder.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.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 // Plain or TLS with STARTTLS
* 993 or esp_mail_imap_port_993
*/
#define IMAP_PORT esp_mail_imap_port_143
/* 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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
/* Print all attachments info from the message */
void printAttacements(std::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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/** 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
*/
/* 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;
/* We will clear fetching message UID as it used to determine the reading mode i.e., search and fetch */
imap_data.fetch.uid.clear();
/** Search criteria
*
* A search key can also be a parenthesized list of one or more search keys
* (e.g., for use with the OR and NOT keys).
*
* Since IMAP protocol uses Polish notation, the search criteria which in the polish notation form can be.
*
* To search the message from "someone@email.com" with the subject "my subject" since 1 Jan 2021, your search criteria can be
* UID SEARCH (OR SUBJECT "my subject" FROM "someone@email.com") SINCE "Fri, 1 Jan 2021 21:52:25 -0800"
*
* To search the message from "mail1@domain.com" or from "mail2@domain.com", the search criteria will be
* UID SEARCH OR FROM mail1@domain.com FROM mail2@domain.com
*
* For more details on using parentheses, AND, OR and NOT search keys in search criteria.
* https://www.limilabs.com/blog/imap-search-requires-parentheses
*
*For keywords used in search criteria, see
* https://github.com/mobizt/ESP-Mail-Client/tree/master/src#search-criteria
*
* Use "SEARCH UNSEEN" for unread messages search
* Use "SEARCH RECENT" for messages with the \\RECENT flag set
* Use "ON _date_" for messages with Date header matching _date_
* Use "BEFORE _date_" for messages with Date header before _date_
*/
imap_data.search.criteria = F("SEARCH RECENT");
/* Also search the unseen message */
imap_data.search.unseen_msg = true;
/* 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_flash;
/** Set to download headers, 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";
/* Set the TCP response read timeout in seconds */
// imap.setTCPTimeout(10);
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
/** Or connect without log in and log in later
if (!imap.connect(&config, &imap_data, false))
return;
if (!imap.loginWithPassword(AUTHOR_EMAIL, AUTHOR_PASSWORD))
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
* MailClient.printf("nIdentification sending error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
*/
if (!imap.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
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());
/** Read or search the Email and keep the TCP session to open
* The second parameter is for close the session.
*/
MailClient.readMail(&imap, false);
/* Clear all stored data in IMAPSession object */
imap.empty();
/** Open or select other mailbox folder
* The folder that previousely opened will be closed
*/
if (imap.selectFolder(F("Junk")))
{
/* {Optional} */
printSelectedMailboxInfo(imap.selectedFolder());
/** Config to search all messages in the opened mailboax (Search mode)
* For keywords used in search criteria, see
* https://github.com/mobizt/ESP-Mail-Client/tree/master/src#search-criteria
*/
imap_data.search.criteria = F("SEARCH ALL"); // or "SEARCH NEW" for recent received messages
/* We will clear fetching message UID as it used to determine the reading mode i.e., search and fetch */
imap_data.fetch.uid.clear();
/* Search the Email and close the session */
MailClient.readMail(&imap);
}
/* Close the seeion in case the session is still open */
imap.closeSession();
/* 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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.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
*/
MailClient.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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly)
{
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("****************************");
// Message sequence number
MailClient.printf("Number: %d\n", msg.msgNo);
// Message UID
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
/* If the result contains the message info (Fetch mode) */
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,327 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to search all messages with the keywords in the opened mailbox folder.
/**
* To use library in silent mode (no debug printing and callback), please define this macro in src/ESP_Mail_FS.h.
* #define SILENT_MODE
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define IMAP_HOST "<host>"
#define IMAP_PORT esp_mail_imap_port_143
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
void printImapData(IMAP_Status status);
void printAllMailboxesInfo(IMAPSession &imap);
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
void printMessages(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly);
void printAttacements(std::vector<IMAP_Attach_Item> &atts);
IMAPSession imap;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
Session_Config config;
config.server.host_name = IMAP_HOST;
config.server.port = IMAP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
IMAP_Data imap_data;
imap_data.fetch.uid.clear();
imap_data.search.criteria = F("SEARCH RECENT");
imap_data.search.unseen_msg = true;
imap_data.storage.saved_path = F("/email_data");
imap_data.storage.type = esp_mail_file_storage_type_flash;
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;
imap_data.enable.html = true;
imap_data.enable.text = true;
imap_data.enable.recent_sort = true;
imap_data.enable.download_status = true;
imap_data.limit.search = 5;
imap_data.limit.msg_size = 512;
imap_data.limit.attachment_size = 1024 * 1024 * 5;
imap.setTCPTimeout(10);
if (!imap.connect(&config, &imap_data))
{
MailClient.printf("Connection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
if (imap.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
printAllMailboxesInfo(imap);
if (!imap.selectFolder(F("INBOX")))
{
MailClient.printf("Folder selection error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
return;
}
printSelectedMailboxInfo(imap.selectedFolder());
if (MailClient.readMail(&imap, false))
{
printImapData(imap.status());
}
else
{
MailClient.printf("Message searching error, Error Code: %d, Reason: %s", imap.errorCode(), imap.errorReason().c_str());
}
imap.closeSession();
imap.empty();
}
void loop()
{
}
void printImapData(IMAP_Status status)
{
if (status.success())
{
MailClient.printf("\nFound %d messages\n\n", imap.selectedFolder().searchCount());
IMAP_MSG_List msgList = imap.data();
printMessages(msgList.msgItems, imap.headerOnly());
imap.empty();
}
}
void printAllMailboxesInfo(IMAPSession &imap)
{
FoldersCollection folders;
if (imap.getFolders(folders))
{
for (size_t i = 0; i < folders.size(); i++)
{
FolderInfo folderInfo = folders.info(i);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}
void printAttacements(std::vector<IMAP_Attach_Item> &atts)
{
MailClient.printf("Attachment: %d file(s)\n****************************\n", atts.size());
for (size_t j = 0; j < atts.size(); j++)
{
IMAP_Attach_Item att = atts[j];
MailClient.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(std::vector<IMAP_MSG_Item> &msgItems, bool headerOnly)
{
for (size_t i = 0; i < msgItems.size(); i++)
{
IMAP_MSG_Item msg = msgItems[i];
Serial.println("****************************");
MailClient.printf("Number: %d\n", msg.msgNo);
MailClient.printf("UID: %d\n", msg.UID);
// The attachment status in search may be true in case the "multipart/mixed"
// content type header was set with no real attachtment included.
MailClient.printf("Attachment: %s\n", msg.hasAttachment ? "yes" : "no");
MailClient.printf("Messsage-ID: %s\n", msg.ID);
if (strlen(msg.flags))
MailClient.printf("Flags: %s\n", msg.flags);
if (strlen(msg.acceptLang))
MailClient.printf("Accept Language: %s\n", msg.acceptLang);
if (strlen(msg.contentLang))
MailClient.printf("Content Language: %s\n", msg.contentLang);
if (strlen(msg.from))
MailClient.printf("From: %s\n", msg.from);
if (strlen(msg.sender))
MailClient.printf("Sender: %s\n", msg.sender);
if (strlen(msg.to))
MailClient.printf("To: %s\n", msg.to);
if (strlen(msg.cc))
MailClient.printf("CC: %s\n", msg.cc);
if (strlen(msg.bcc))
MailClient.printf("BCC: %s\n", msg.bcc);
if (strlen(msg.date))
{
MailClient.printf("Date: %s\n", msg.date);
MailClient.printf("Timestamp: %d\n", (int)MailClient.Time.getTimestamp(msg.date));
}
if (strlen(msg.subject))
MailClient.printf("Subject: %s\n", msg.subject);
if (strlen(msg.reply_to))
MailClient.printf("Reply-To: %s\n", msg.reply_to);
if (strlen(msg.return_path))
MailClient.printf("Return-Path: %s\n", msg.return_path);
if (strlen(msg.in_reply_to))
MailClient.printf("In-Reply-To: %s\n", msg.in_reply_to);
if (strlen(msg.references))
MailClient.printf("References: %s\n", msg.references);
if (strlen(msg.comments))
MailClient.printf("Comments: %s\n", msg.comments);
if (strlen(msg.keywords))
MailClient.printf("Keywords: %s\n", msg.keywords);
if (!headerOnly)
{
if (strlen(msg.text.content))
MailClient.printf("Text Message: %s\n", msg.text.content);
if (strlen(msg.text.charSet))
MailClient.printf("Text Message Charset: %s\n", msg.text.charSet);
if (strlen(msg.text.transfer_encoding))
MailClient.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
if (strlen(msg.html.content))
MailClient.printf("HTML Message: %s\n", msg.html.content);
if (strlen(msg.html.charSet))
MailClient.printf("HTML Message Charset: %s\n", msg.html.charSet);
if (strlen(msg.html.transfer_encoding))
MailClient.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
if (msg.rfc822.size() > 0)
{
MailClient.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();
}
}

View File

@ -0,0 +1,339 @@
/**
* This example shows how to set messages flags.
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*
*/
// This example shows how to set messages flags.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* Print the selected folder info */
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/** 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Set seen flag */
// imap_data.fetch.set_seen = true;
/* Search criteria */
imap_data.search.criteria.clear();
/* Also search the unseen message */
imap_data.search.unseen_msg = true;
/* 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_flash;
/** Set to download headers, 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;
/* 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
/* {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 */
int uid = imap.getUID(imap.selectedFolder().msgCount());
/** Set \Seen and \Answered to flags for message with UID
* The seesion will keep open.
*/
if (MailClient.setFlag(&imap, uid, F("\\Seen \\Answered"), false))
Serial.println("\nSetting FLAG success");
else
Serial.println("\nError, setting FLAG");
/* Add \Seen and \Answered to flags for message with UID 100 */
// MailClient.addFlag(imap, 100, "\\Seen \\Answered", false);
/* Remove \Seen and \Answered from flags for message with UID 100 */
// MailClient.removeFlag(imap, 100, "\\Seen \\Answered", false);
/* Remove Seen and Answered flags from messages using UID ranges (last 10 UIDs) */
int uid_last = imap.getUID(imap.selectedFolder().msgCount());
int uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
String sequence_set1 = String(uid_begin) + ":" + String(uid_last);
if (MailClient.removeFlag(&imap, sequence_set1, true /* if sequence set are the UIDs */, F("\\Seen \\Answered"), false /* Close session */, false /* Ignore response */))
Serial.println("\nRemoving FLAG with UIDs ranges success");
else
Serial.println("\nError, removing FLAG with UIDs ranges");
/* Remove Seen and Answered flags from messages using message sequence ranges (last 10 message numbers) */
int msg_last = imap.selectedFolder().msgCount();
int msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
String sequence_set2 = String(msg_begin) + ":" + String(msg_last);
if (MailClient.removeFlag(&imap, sequence_set2, false /* if sequence set are message numbers not UIDs */, F("\\Seen \\Answered"), false /* Close session */, false /* Ignore response */))
Serial.println("\nRemoving FLAG with message numbers ranges success");
else
Serial.println("\nError, removing FLAG with message numbers ranges");
imap_data.fetch.uid = uid;
/* Read or search the Email and close the session */
MailClient.readMail(&imap);
/* Clear all stored data in IMAPSession object */
imap.empty();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}

View File

@ -0,0 +1,309 @@
/**
* This example shows how to set messages flags.
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*
*/
// This example shows how to set messages flags using message numbers ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* Print the selected folder info */
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/** 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Set seen flag */
// imap_data.fetch.set_seen = true;
/* Search criteria */
imap_data.search.criteria.clear();
/* Also search the unseen message */
imap_data.search.unseen_msg = true;
/* 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_flash;
/** Set to download headers, 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;
/* 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
/* {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());
/* Add Seen and Answered flags from messages using message numbers ranges (last 10 message numbers) */
int msg_last = imap.selectedFolder().msgCount();
int msg_begin = msg_last > 10 ? msg_last - 10 : msg_last;
String sequence_set1 = String(msg_begin) + ":" + String(msg_last);
if (MailClient.addFlag(&imap, sequence_set1, false /* if sequence set are message numbers not UIDs */, F("\\Seen \\Answered"), false /* Close session */, false /* Ignore response */))
Serial.println("\nAdding FLAG with message numbers ranges success");
else
Serial.println("\nError, adding FLAG with message numbers ranges");
/* Remove Seen and Answered flags from messages using message numbers ranges (last 10 message numbers) */
if (MailClient.removeFlag(&imap, sequence_set1, false /* if sequence set are message numbers not UIDs */, F("\\Seen \\Answered"), false /* Close session */, false /* Ignore response */))
Serial.println("\nRemoving FLAG with message numbers ranges success");
else
Serial.println("\nError, removing FLAG with message numbers ranges");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}

View File

@ -0,0 +1,310 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to set messages flags.
// This example shows how to set messages flags using UIDs ranges.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For ESP8266, with BearSSL WiFi Client
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
* may cause your device out of memory reset in case the memory
* allocation error.
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.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>"
/* Print the list of mailbox folders */
void printAllMailboxesInfo(IMAPSession &imap);
/* Print the selected folder info */
void printSelectedMailboxInfo(SelectedFolderInfo sFolder);
/* 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)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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);
/** 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;
/* Define the IMAP_Data object used for user defined IMAP operating options. */
IMAP_Data imap_data;
/* Set seen flag */
// imap_data.fetch.set_seen = true;
/* Search criteria */
imap_data.search.criteria.clear();
/* Also search the unseen message */
imap_data.search.unseen_msg = true;
/* 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_flash;
/** Set to download headers, 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;
/* 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;
/* Connect to the server */
if (!imap.connect(&config, &imap_data))
return;
/* {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());
/* Add Seen and Answered flags from messages using UID ranges (last 10 UIDs) */
int uid_last = imap.getUID(imap.selectedFolder().msgCount());
int uid_begin = uid_last > 10 ? uid_last - 10 : uid_last;
String sequence_set1 = String(uid_begin) + ":" + String(uid_last);
if (MailClient.addFlag(&imap, sequence_set1, true /* if sequence set are the UIDs */, F("\\Seen \\Answered"), false /* Close session */, false /* Ignore response */))
Serial.println("\nAdding FLAG with UIDs ranges success");
else
Serial.println("\nError, adding FLAG with UIDs ranges");
/* Remove Seen and Answered flags from messages using UID ranges (last 10 UIDs) */
if (MailClient.removeFlag(&imap, sequence_set1, true /* if sequence set are the UIDs */, F("\\Seen \\Answered"), false /* Close session */, false /* Ignore response */))
Serial.println("\nRemoving FLAG with UIDs ranges success");
else
Serial.println("\nError, removing FLAG with UIDs ranges");
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
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);
MailClient.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
}
}
}
void printSelectedMailboxInfo(SelectedFolderInfo sFolder)
{
/* Show the mailbox info */
MailClient.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("UID Validity: %d\n", sFolder.uidValidity());
MailClient.printf("Predicted next UID: %d\n", sFolder.nextUID());
if (sFolder.unseenIndex() > 0)
MailClient.printf("First Unseen Message Number: %d\n", sFolder.unseenIndex());
else
MailClient.printf("Unseen Messages: No\n");
if (sFolder.modSeqSupported())
MailClient.printf("Highest Modification Sequence: %llu\n", sFolder.highestModSeq());
for (size_t i = 0; i < sFolder.flagCount(); i++)
MailClient.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
if (sFolder.flagCount(true))
{
for (size_t i = 0; i < sFolder.flagCount(true); i++)
MailClient.printf("%s%s%s", i == 0 ? "Permanent Flags: " : ", ", sFolder.flag(i, true).c_str(), i == sFolder.flagCount(true) - 1 ? "\n" : "");
}
}

View File

@ -0,0 +1,219 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send Email using custom commands.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587 // See STARTTLS.ino example
*/
#define SMTP_PORT esp_mail_smtp_port_465 // port 465 is not available for Outlook.com
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
"-----END CERTIFICATE-----\n";
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(SMTP_Response res)
{
// The res.id is the command identifier number that use to identify the source of command.
// The command identifier number can be set via the last parameter of customConnect and sendCustomCommand functions.
// If command identifier number was not set in those functions, the res.id received will be auto increased and begins with 0
MailClient.printf("> C: Command ID %d\n", res.id);
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.statusCode > 0)
{
MailClient.printf("> C: Response finished with status code %d\n\n", res.statusCode);
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/* Connect to the server */
if (!smtp.connect(&config))
return;
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
// Please don't forget to change sender@xxxxxx.com to your email
if (smtp.sendCustomCommand(F("MAIL FROM:<sender@xxxxxx.com>"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Please don't forget to change recipient@xxxxx.com with your recipient email
if (smtp.sendCustomCommand(F("RCPT TO:<recipient@xxxxx.com>"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(F("DATA"), customCommandCallback) != 354)
{
smtp.closeSession();
return;
}
// Send data with command which terminated with dot '.'
if (smtp.sendCustomCommand(F("Subject: Test sending Email\r\nHello World!\r\n."), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Do not use this command in ESP8266 due to memory leaks in ESP8266 core BearSSL.
// smtp.sendCustomCommand(F("QUIT"), customCommandCallback);
smtp.closeSession();
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}

View File

@ -0,0 +1,248 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send Email using custom commands.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587 // See STARTTLS.ino example
*/
#define SMTP_PORT esp_mail_smtp_port_465 // port 465 is not available for Outlook.com
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
"-----END CERTIFICATE-----\n";
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(SMTP_Response res)
{
// The res.id is the command identifier number that use to identify the source of command.
// The command identifier number can be set via the last parameter of customConnect and sendCustomCommand functions.
// If command identifier number was not set in those functions, the res.id received will be auto increased and begins with 0
MailClient.printf("> C: Command ID %d\n", res.id);
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.statusCode > 0)
{
MailClient.printf("> C: Response finished with status code %d\n\n", res.statusCode);
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/* Connect to the server */
if (smtp.customConnect(&config /* session credentials */, customCommandCallback) != 220)
{
Serial.println("! E: Unable to connect to server");
return;
}
if (smtp.sendCustomCommand(F("EHLO 127.0.0.1"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(F("AUTH LOGIN"), customCommandCallback) != 334)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(MailClient.toBase64(config.login.email), customCommandCallback) != 334)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(MailClient.toBase64(config.login.password), customCommandCallback) != 235)
{
smtp.closeSession();
return;
}
if (smtp.isAuthenticated())
Serial.println("Successfully logged in.\n");
else
Serial.println("Connected with no Auth.\n");
// Please don't forget to change sender@xxxxxx.com to your email
if (smtp.sendCustomCommand(F("MAIL FROM:<sender@xxxxxx.com>"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Please don't forget to change recipient@xxxxx.com with your recipient email
if (smtp.sendCustomCommand(F("RCPT TO:<recipient@xxxxx.com>"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(F("DATA"), customCommandCallback) != 354)
{
smtp.closeSession();
return;
}
if (!smtp.sendCustomData(F("Subject: Test sending Email\r\n")))
{
smtp.closeSession();
return;
}
if (!smtp.sendCustomData(F("Hello World!\r\n")))
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(F("."), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Do not use this command in ESP8266 due to memory leaks in ESP8266 core BearSSL.
// smtp.sendCustomCommand(F("QUIT"), customCommandCallback);
smtp.closeSession();
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}

View File

@ -0,0 +1,268 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send Email using custom commands.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465 // port 465 is not available for Outlook.com
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587 // for STARTTLS
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
"-----END CERTIFICATE-----\n";
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void customCommandCallback(SMTP_Response res)
{
// The res.id is the command identifier number that use to identify the source of command.
// The command identifier number can be set via the last parameter of customConnect and sendCustomCommand functions.
// If command identifier number was not set in those functions, the res.id received will be auto increased and begins with 0
MailClient.printf("> C: Command ID %d\n", res.id);
MailClient.printf("< S: %s\n", res.text.c_str());
if (res.statusCode > 0)
{
MailClient.printf("> C: Response finished with status code %d\n\n", res.statusCode);
}
}
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
bool tls = false;
/* Connect to the server */
if (smtp.customConnect(&config /* session credentials */, customCommandCallback) != 220)
{
Serial.println("! E: Unable to connect to server");
return;
}
init:
if (smtp.sendCustomCommand(F("EHLO 127.0.0.1"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Only for SMTP port 587 in supported server that accepts STARTTLS
if (!tls)
{
if (smtp.sendCustomCommand(F("STARTTLS"), customCommandCallback) != 220)
{
smtp.closeSession();
return;
}
tls = true;
// Send greeting again
goto init;
}
if (smtp.sendCustomCommand(F("AUTH LOGIN"), customCommandCallback) != 334)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(MailClient.toBase64(config.login.email), customCommandCallback) != 334)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(MailClient.toBase64(config.login.password), customCommandCallback) != 235)
{
smtp.closeSession();
return;
}
if (smtp.isAuthenticated())
Serial.println("Successfully logged in.\n");
else
Serial.println("Connected with no Auth.\n");
// Please don't forget to change sender@xxxxxx.com to your email
if (smtp.sendCustomCommand(F("MAIL FROM:<sender@xxxxxx.com>"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Please don't forget to change recipient@xxxxx.com with your recipient email
if (smtp.sendCustomCommand(F("RCPT TO:<recipient@xxxxx.com>"), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(F("DATA"), customCommandCallback) != 354)
{
smtp.closeSession();
return;
}
if (!smtp.sendCustomData(F("Subject: Test sending Email\r\n")))
{
smtp.closeSession();
return;
}
if (!smtp.sendCustomData(F("Hello World!\r\n")))
{
smtp.closeSession();
return;
}
if (smtp.sendCustomCommand(F("."), customCommandCallback) != 250)
{
smtp.closeSession();
return;
}
// Do not use this command in ESP8266 due to memory leaks in ESP8266 core BearSSL.
// smtp.sendCustomCommand(F("QUIT"), customCommandCallback);
smtp.closeSession();
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}

View File

@ -0,0 +1,376 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send text Email via the custom port.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT 2525 // non-standard port (TLS)
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
"-----END CERTIFICATE-----\n";
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/** Set the ports and protocols
* This allows non-standard port to work with this library
* The port that assigned with config.server.port will map with the
* protocol assigned here
*/
config.ports_functions.list = new port_function[4];
config.ports_functions.size = 4;
config.ports_functions.list[0].port = 25;
config.ports_functions.list[0].protocol = esp_mail_protocol_plain_text;
config.ports_functions.list[1].port = 465;
config.ports_functions.list[1].protocol = esp_mail_protocol_ssl;
config.ports_functions.list[2].port = 587;
config.ports_functions.list[2].protocol = esp_mail_protocol_tls;
config.ports_functions.list[3].port = 2525;
config.ports_functions.list[3].protocol = esp_mail_protocol_tls;
/** In ESP32, timezone environment will not keep after wake up boot from sleep.
* The local time will equal to GMT time.
*
* To sync or set time with NTP server with the valid local time after wake up boot,
* set both gmt and day light offsets to 0 and assign the timezone environment string e.g.
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 0;
config.time.day_light_offset = 0;
config.time.timezone_env_string = "JST-9"; // for Tokyo
* The library will get (sync) the time from NTP server without GMT time offset adjustment
* and set the timezone environment variable later.
*
* This timezone environment string will be stored to flash or SD file named "/tz_env.txt"
* which set via config.time.timezone_file.
*
* See the timezone environment string list from
* https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
*
*/
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail"); // This witll be used with 'MAIL FROM' command and 'From' header field.
message.sender.email = AUTHOR_EMAIL; // This witll be used with 'From' header field.
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL); // This will be used with RCPT TO command and 'To' header field.
String textMsg = "This is simple plain text message";
message.text.content = textMsg;
/** If the message to send is a large string, to reduce the memory used from internal copying while sending,
* you can assign string to message.text.blob by cast your string to uint8_t array like this
*
* String myBigString = "..... ......";
* message.text.blob.data = (uint8_t *)myBigString.c_str();
* message.text.blob.size = myBigString.length();
*
* or assign string to message.text.nonCopyContent, like this
*
* message.text.nonCopyContent = myBigString.c_str();
*
* Only base64 encoding is supported for content transfer encoding in this case.
*/
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
// If this is a reply message
// message.in_reply_to = "<parent message id>";
// message.references = "<parent references> <parent message id>";
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
// message.response.reply_to = "someone@somemail.com";
// message.response.return_path = "someone@somemail.com";
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
// For Root CA certificate verification (ESP8266 and ESP32 only)
// config.certificate.cert_data = rootCACert;
// or
// config.certificate.cert_file = "/path/to/der/file";
// config.certificate.cert_file_storage_type = esp_mail_file_storage_type_flash; // esp_mail_file_storage_type_sd
// config.certificate.verify = true;
// The WiFiNINA firmware the Root CA certification can be added via the option in Firmware update tool in Arduino IDE
/* Connect to server with the session config */
// Library will be trying to sync the time with NTP server if time is never sync or set.
// This is 10 seconds blocking process.
// If time reading was timed out, the error "NTP server time reading timed out" will show via debug and callback function.
// You can manually sync time by yourself with NTP library or calling configTime in ESP32 and ESP8266.
// Time can be set manually with provided timestamp to function smtp.setSystemTime.
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,287 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email using ESP32 and LAN8720 Ethernet module.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/**
* There are many sources for LAN8720 and ESP32 interconnection on the internet which may
* work for your LAN8720 board.
*
* Some methods worked unless no IP is available.
*
* This modification and interconnection provided in this example are mostly worked as
* the 50 MHz clock was created internally in ESP32 which GPIO 17 is set to be output of this clock
* and feeds to the LAN8720 chip XTAL input.
*
* The on-board LAN8720 50 MHz XTAL chip will be disabled by connect its enable pin or pin 1 to GND.
*
* Please see the images in the folder "modified_LAN8720_board_images" for how to modify the LAN8720 board.
*
* The LAN8720 Ethernet modified board and ESP32 board wiring connection.
*
* ESP32 LAN8720
*
* GPIO17 - EMAC_CLK_OUT_180 nINT/REFCLK - LAN8720 XTAL1/CLKIN 4k7 Pulldown
* GPIO22 - EMAC_TXD1 TX1
* GPIO19 - EMAC_TXD0 TX0
* GPIO21 - EMAC_TX_EN TX_EN
* GPIO26 - EMAC_RXD1 RX1
* GPIO25 - EMAC_RXD0 RX0
* GPIO27 - EMAC_RX_DV CRS
* GPIO23 - MDC MDC
* GPIO18 - MDIO MDIO
* GND GND
* 3V3 VCC
*
*
* ESP32 Arduino SDK native Ethernet using ETH.h is currently support Ethernet PHY chips
*
* LAN8720, TLK101, RTL8201, DP83848, DM9051, KSZ8041 and KSZ8081.
*
* For ESP32 and other SPI MAC Ethernet modules, the external Client was used,
* see examples/SMTP/External_Client/EthernetClient/EthernetClient.ino
*
*/
#include <ESP_Mail_Client.h>
#ifdef ETH_CLK_MODE
#undef ETH_CLK_MODE
#endif
#define ETH_CLK_MODE ETH_CLOCK_GPIO17_OUT // RMII clock output from GPIO17
// Pin# of the enable signal for the external crystal oscillator (-1 to disable)
#define ETH_POWER_PIN -1
// Type of the Ethernet PHY (LAN8720 or TLK110)
#define ETH_TYPE ETH_PHY_LAN8720
// I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110)
#define ETH_ADDR 1
// Pin# of the I²C clock signal for the Ethernet PHY
#define ETH_MDC_PIN 23
// Pin# of the I²C IO signal for the Ethernet PHY
#define ETH_MDIO_PIN 18
static bool eth_connected = false;
#define SMTP_HOST "<host>"
#define SMTP_PORT 25
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
void smtpCallback(SMTP_Status status);
unsigned long sendMillis = 0;
void WiFiEvent(WiFiEvent_t event)
{
// Do not run any function here to prevent stack overflow or nested interrupt
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
switch (event)
{
case ARDUINO_EVENT_ETH_START:
Serial.println("ETH Started");
// set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case ARDUINO_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case ARDUINO_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex())
{
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case ARDUINO_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case ARDUINO_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
#else
switch (event)
{
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
// set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex())
{
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
#endif
}
void sendMail()
{
smtp.debug(1);
smtp.callback(smtpCallback);
Session_Config config;
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
String textMsg = "This is simple plain text message";
message.text.content = textMsg;
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
}
void setup()
{
Serial.begin(115200);
Serial.println();
WiFi.onEvent(WiFiEvent);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
}
void loop()
{
if (eth_connected && (millis() - sendMillis > 300000 || sendMillis == 0))
{
sendMillis = millis();
sendMail();
}
}
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,230 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email using ESP8266 and ENC28J60 Ethernet module.
// This example requires ESP8266 Arduino Core SDK v3.x.x
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/**
*
* The ENC28J60 Ethernet module and ESP8266 board, SPI port wiring connection.
*
* ESP8266 (Wemos D1 Mini or NodeMCU) ENC28J60
*
* GPIO12 (D6) - MISO SO
* GPIO13 (D7) - MOSI SI
* GPIO14 (D5) - SCK SCK
* GPIO16 (D0) - CS CS
* GND GND
* 3V3 VCC
*
*/
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <ENC28J60lwIP.h>
// #include <W5100lwIP.h>
// #include <W5500lwIP.h>
/**
* For ENC28J60 ethernet module, uncomment this line in ESP_Mail_FS.h
#define ENABLE_ESP8266_ENC28J60_ETH
* For W5500 ethernet module, uncomment this line in ESP_Mail_FS.h
#define ENABLE_ESP8266_W5500_ETH
* For W5100 ethernet module, uncomment this line in ESP_Mail_FS.h
#define ENABLE_ESP8266_W5100_ETH
*/
#include <ESP_Mail_Client.h>
#define SMTP_HOST "<host>"
#define SMTP_PORT 25
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
void smtpCallback(SMTP_Status status);
unsigned long sendMillis = 0;
#ifdef ESP8266_CORE_SDK_V3_X_X
#define ETH_CS_PIN 16 // D0
ENC28J60lwIP eth(ETH_CS_PIN);
// Wiznet5100lwIP eth(ETH_CS_PIN);
// Wiznet5500lwIP eth(ETH_CS_PIN);
#endif
void sendMail()
{
smtp.debug(1);
smtp.callback(smtpCallback);
Session_Config config;
/* Assign the pointer to Ethernet module lwip interface */
#ifdef ESP8266_CORE_SDK_V3_X_X
#if defined(ENABLE_ESP8266_ENC28J60_ETH)
config.spi_ethernet_module.enc28j60 = &eth;
#elif defined(ENABLE_ESP8266_W5100_ETH)
config.spi_ethernet_module.w5100 = &eth;
#elif defined(ENABLE_ESP8266_W5500_ETH)
config.spi_ethernet_module.w5500 = &eth;
#endif
#endif
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
String textMsg = "This is simple plain text message";
message.text.content = textMsg;
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
}
void setup()
{
Serial.begin(115200);
Serial.println();
#ifdef ESP8266_CORE_SDK_V3_X_X
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz?
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
eth.setDefault(); // use ethernet for default route
if (!eth.begin())
{
Serial.println("ethernet hardware not found ... sleeping");
while (1)
{
delay(1000);
}
}
else
{
Serial.print("connecting ethernet");
while (!eth.connected())
{
Serial.print(".");
delay(1000);
}
}
Serial.println();
Serial.print("ethernet IP address: ");
Serial.println(eth.localIP());
#else
Serial.println("This example requires ESP8266 Arduino Core SDK v3.x.x, please update.");
#endif
}
void loop()
{
#ifdef ESP8266_CORE_SDK_V3_X_X
if (millis() - sendMillis > 300000 || sendMillis == 0)
{
sendMillis = millis();
sendMail();
}
#endif
}
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,224 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
/**
* This example shows how to send Email using EthernetClient.
*
* This example used ESP32 and WIZnet W5500 Ethernet module.
*
* For ESP32 and LAN8720 see examples/SMTP/Ethernet/ESP32/Send_Text.ino
*
* ESP32 Arduino SDK native Ethernet using ETH.h is currently support Ethernet PHY chips
*
* LAN8720, TLK101, RTL8201, DP83848, DM9051, KSZ8041 and KSZ8081.
*
* For ESP8266, the native Ethernet is currently supported ENC28J60, W5100 and W5500.
*
* You do not need to set external Client with native Ethernet support PHY/MAC chips.
*
*
*/
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#include <ESP_Mail_Client.h>
#include <Ethernet.h>
#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 587
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
#define WIZNET_RESET_PIN 26 // Connect W5500 Reset pin to GPIO 26 of ESP32
#define WIZNET_CS_PIN 5 // Connect W5500 CS pin to GPIO 5 of ESP32
#define WIZNET_MISO_PIN 19 // Connect W5500 MISO pin to GPIO 19 of ESP32
#define WIZNET_MOSI_PIN 23 // Connect W5500 MOSI pin to GPIO 23 of ESP32
#define WIZNET_SCLK_PIN 18 // Connect W5500 SCLK pin to GPIO 18 of ESP32
unsigned long sentMillis = 0;
const int analog_pin = 34;
uint8_t Eth_MAC[] = {0x02, 0xF0, 0x0D, 0xBE, 0xEF, 0x01};
SMTPSession smtp;
EthernetClient eth_client;
void smtpCallback(SMTP_Status status);
void ResetEthernet()
{
Serial.println("Resetting WIZnet W5500 Ethernet Board... ");
pinMode(WIZNET_RESET_PIN, OUTPUT);
digitalWrite(WIZNET_RESET_PIN, HIGH);
delay(200);
digitalWrite(WIZNET_RESET_PIN, LOW);
delay(50);
digitalWrite(WIZNET_RESET_PIN, HIGH);
delay(200);
}
void networkConnection()
{
Ethernet.init(WIZNET_CS_PIN);
ResetEthernet();
Serial.println("Starting Ethernet connection...");
Ethernet.begin(Eth_MAC);
unsigned long to = millis();
while (Ethernet.linkStatus() == LinkOFF || millis() - to < 2000)
{
delay(100);
}
if (Ethernet.linkStatus() == LinkON)
{
Serial.print("Connected with IP ");
Serial.println(Ethernet.localIP());
}
else
{
Serial.println("Can't connect");
}
}
void networkStatusRequestCallback()
{
smtp.setNetworkStatus(Ethernet.linkStatus() == LinkON);
}
void sendEmail()
{
Session_Config config;
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
message.text.content = "This is simple plain text message";
smtp.setClient(&eth_client);
smtp.networkConnectionRequestCallback(networkConnection);
smtp.networkStatusRequestCallback(networkStatusRequestCallback);
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void setup()
{
Serial.begin(115200);
Serial.println();
networkConnection();
/*
For internal NTP client
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
MailClient.setUDPClient(&udp_client, 0 /* GMT offset */);
smtp.debug(1);
smtp.callback(smtpCallback);
}
void loop()
{
if (millis() - sentMillis > 120000 || sentMillis == 0)
{
sentMillis = millis();
sendEmail();
}
}
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,213 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example used TTGO T-A7670 (ESP32 with SIMCom SIMA7670) and TinyGSMClient.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
// To allow TinyGSM library integration, the following macro should be defined in src/ESP_Mail_FS.h or
// your custom config file src/Custom_ESP_Mail_FS.h.
// #define TINY_GSM_MODEM_SIM7600
#define TINY_GSM_MODEM_SIM7600 // SIMA7670 Compatible with SIM7600 AT instructions
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to the module)
// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1
// See all AT commands, if wanted
// #define DUMP_AT_COMMANDS
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
#define uS_TO_S_FACTOR 1000000ULL // Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 600 // Time ESP32 will go to sleep (in seconds)
#define UART_BAUD 115200
#define PIN_DTR 25
#define PIN_TX 26
#define PIN_RX 27
#define PWR_PIN 4
#define BAT_ADC 35
#define BAT_EN 12
#define PIN_RI 33
#define PIN_DTR 25
#define RESET 5
#define SD_MISO 2
#define SD_MOSI 15
#define SD_SCLK 14
#define SD_CS 13
#include <ESP_Mail_Client.h>
#include <TinyGsmClient.h>
TinyGsm modem(SerialAT);
TinyGsmClient gsm_client(modem);
#define SMTP_HOST "<host>"
#define SMTP_PORT esp_mail_smtp_port_587
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
void smtpCallback(SMTP_Status status);
void setup()
{
SerialMon.begin(115200);
smtp.debug(1);
smtp.callback(smtpCallback);
delay(10);
pinMode(BAT_EN, OUTPUT);
digitalWrite(BAT_EN, HIGH);
// A7670 Reset
pinMode(RESET, OUTPUT);
digitalWrite(RESET, LOW);
delay(100);
digitalWrite(RESET, HIGH);
delay(3000);
digitalWrite(RESET, LOW);
pinMode(PWR_PIN, OUTPUT);
digitalWrite(PWR_PIN, LOW);
delay(100);
digitalWrite(PWR_PIN, HIGH);
delay(1000);
digitalWrite(PWR_PIN, LOW);
DBG("Wait...");
delay(3000);
SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
// Restart takes quite some time
// To skip it, call init() instead of restart()
DBG("Initializing modem...");
if (!modem.init())
{
DBG("Failed to restart modem, delaying 10s and retrying");
return;
}
/*
2 Automatic
13 GSM Only
14 WCDMA Only
38 LTE Only
*/
modem.setNetworkMode(38);
if (modem.waitResponse(10000L) != 1)
{
DBG(" setNetworkMode faill");
}
String name = modem.getModemName();
DBG("Modem Name:", name);
String modemInfo = modem.getModemInfo();
DBG("Modem Info:", modemInfo);
Session_Config config;
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email using GSM module");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
message.text.content = "This is simple plain text message";
smtp.setGSMClient(&gsm_client, &modem, GSM_PIN, apn, gprsUser, gprsPass);
smtp.connect(&config);
if (!MailClient.sendMail(&smtp, &message))
Serial.println("Error sending Email, " + smtp.errorReason());
}
void loop()
{
}
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,187 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email using external WiFiClient.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define SMTP_HOST "<host>"
#define SMTP_PORT esp_mail_smtp_port_587
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
WiFiClient wifi_client;
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void smtpCallback(SMTP_Status status);
void networkStatusRequestCallback()
{
smtp.setNetworkStatus(WiFi.status() == WL_CONNECTED);
}
void networkConnectionRequestCallback()
{
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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
}
void setup()
{
Serial.begin(115200);
networkConnectionRequestCallback();
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
smtp.debug(1);
smtp.callback(smtpCallback);
Session_Config config;
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
smtp.setClient(&wifi_client);
smtp.networkStatusRequestCallback(networkStatusRequestCallback);
smtp.networkConnectionRequestCallback(networkConnectionRequestCallback);
smtp.connect(&config);
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
message.text.content = "This is simple plain text message";
if (!MailClient.sendMail(&smtp, &message))
Serial.println("Error sending Email, " + smtp.errorReason());
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,497 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send a reply message when specific email was received.
// The account 2 will send Hello message to account 1.
// The account 1 will poll the mailbox for incoming message, when new message received with matched subject
// and sent from account 2, the account 1 will send a reply messsage to account 2.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 "<imap host for account 1>"
#define IMAP_PORT 993
#define IMAP_AUTHOR_EMAIL "<email for account 1>"
#define IMAP_AUTHOR_PASSWORD "<password for account 1>"
#define REPLY_SMTP_AUTHOR_EMAIL "<email for account 1>"
#define REPLY_SMTP_AUTHOR_PASSWORD "<password for account 1>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define REPLY_SMTP_PORT 587
#define REPLY_SMTP_HOST "<smtp host for account 1>"
#define HELLO_SMTP_AUTHOR_EMAIL "<email for account 2>"
#define HELLO_SMTP_AUTHOR_PASSWORD "<password for account 2>"
#define HELLO_SMTP_PORT 587
#define HELLO_SMTP_HOST "<smtp host for account 2>"
void setupIMAP();
bool setupHelloSMTP();
bool setupReplySMTP();
void sendHelloMessage();
void sendReplyMessage(const char *subject, const char *reply_email, const char *msgID, const char *references);
/* Print the selected folder update info */
void printPollingStatus(IMAPSession &imap);
/* Callback function to get the Email reading status */
void imapCallback(IMAP_Status status);
/* Callback function to get the Email sending status */
void helloSMTPCallback(SMTP_Status status);
void replySMTPCallback(SMTP_Status status);
/* Declare the global used IMAPSession object for IMAP transport */
IMAPSession imap;
/* Declare the global used Session_Config for user defined IMAP session credentials */
Session_Config imap_config;
/** Define the IMAP_Data object used for user defined IMAP operating options
* and contains the IMAP operating result
*/
IMAP_Data imap_data;
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession hello_smtp;
SMTPSession reply_smtp;
/* Declare the global used Session_Config for user defined SMTP session credentials */
Session_Config hello_smtp_config;
Session_Config reply_smtp_config;
bool imapSetupOk = false;
unsigned long helloSendingMillis = 0;
String sendingSubject = "ESP Mail Hello Test!";
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
Serial.print("Setup and connect to IMAP server... ");
setupIMAP();
if (!imapSetupOk)
return;
}
void loop()
{
/* imap.connect and imap.selectFolder or imap.openFolder nedded to be called once prior to listen */
// Listen for mailbox changes
if (!imap.listen())
return;
// Check the changes
if (imap.folderChanged())
printPollingStatus(imap);
// To stop listen, use imap.stopListen(); and to listen again, call imap.listen()
if (millis() - helloSendingMillis > 5 * 60 * 1000 || helloSendingMillis == 0)
{
helloSendingMillis = millis();
Serial.print("Sending Hello message... ");
sendHelloMessage();
}
}
void setupIMAP()
{
imap.debug(1);
/* Set the callback function to get the reading results */
imap.callback(imapCallback);
/* Set the imap app config */
imap_config.server.host_name = IMAP_HOST;
imap_config.server.port = IMAP_PORT;
imap_config.login.email = IMAP_AUTHOR_EMAIL;
imap_config.login.password = IMAP_AUTHOR_PASSWORD;
/* Connect to the server */
if (!imap.connect(&imap_config, &imap_data))
return;
if (imap.isAuthenticated())
Serial.println("\nIMAP client, successfully logged in.");
else
Serial.println("\nIMAP client, connected with no Auth.");
/* Open or select the mailbox folder to read or search the message */
if (!imap.selectFolder(F("INBOX")))
return;
imapSetupOk = true;
}
bool setupHelloSMTP()
{
hello_smtp.debug(1);
/* Set the callback function to get the sending results */
hello_smtp.callback(helloSMTPCallback);
/* Set the session config */
hello_smtp_config.server.host_name = HELLO_SMTP_HOST;
hello_smtp_config.server.port = HELLO_SMTP_PORT;
hello_smtp_config.login.email = HELLO_SMTP_AUTHOR_EMAIL;
hello_smtp_config.login.password = HELLO_SMTP_AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
hello_smtp_config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
hello_smtp_config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
hello_smtp_config.time.gmt_offset = 3;
hello_smtp_config.time.day_light_offset = 0;
/* Connect to the server */
if (!hello_smtp.connect(&hello_smtp_config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", hello_smtp.statusCode(), hello_smtp.errorCode(), hello_smtp.errorReason().c_str());
return false;
}
if (imap.isAuthenticated())
Serial.println("\nHello SMTP client, successfully logged in.");
else
Serial.println("\nHello SMTP client, connected with no Auth.");
return true;
}
bool setupReplySMTP()
{
reply_smtp.debug(1);
/* Set the callback function to get the sending results */
reply_smtp.callback(replySMTPCallback);
/* Set the session config */
reply_smtp_config.server.host_name = REPLY_SMTP_HOST;
reply_smtp_config.server.port = REPLY_SMTP_PORT;
reply_smtp_config.login.email = REPLY_SMTP_AUTHOR_EMAIL;
reply_smtp_config.login.password = REPLY_SMTP_AUTHOR_PASSWORD;
reply_smtp_config.login.user_domain = F("127.0.0.1");
/* Connect to the server */
if (!reply_smtp.connect(&reply_smtp_config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", reply_smtp.statusCode(), reply_smtp.errorCode(), reply_smtp.errorReason().c_str());
return false;
}
if (imap.isAuthenticated())
Serial.println("\nReply SMTP client, successfully logged in.");
else
Serial.println("\nReply SMTP client, connected with no Auth.");
return true;
}
void sendHelloMessage()
{
if (!setupHelloSMTP())
return;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = HELLO_SMTP_AUTHOR_EMAIL;
message.subject = sendingSubject.c_str();
message.addRecipient(F("Me"), IMAP_AUTHOR_EMAIL);
message.response.reply_to = HELLO_SMTP_AUTHOR_EMAIL; // only email address, excluded < and >
message.text.content = F("Hello Me!");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&hello_smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", hello_smtp.statusCode(), hello_smtp.errorCode(), hello_smtp.errorReason().c_str());
}
void sendReplyMessage(const char *subject, const char *reply_email, const char *msgID, const char *references)
{
if (!setupReplySMTP())
return;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = REPLY_SMTP_AUTHOR_EMAIL;
String reSubject = "RE: ";
reSubject += subject;
message.subject = reSubject;
message.addRecipient(F("Me"), reply_email);
message.in_reply_to = msgID;
String ref = references;
if (strlen(references) > 0)
ref += " ";
ref += msgID;
message.references = ref;
message.text.content = F("Yeah!, it works.");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&reply_smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", reply_smtp.statusCode(), reply_smtp.errorCode(), reply_smtp.errorReason().c_str());
}
void printPollingStatus(IMAPSession &imap)
{
/* Declare the selected folder info class to get the info of selected mailbox folder */
SelectedFolderInfo sFolder = imap.selectedFolder();
if (sFolder.pollingStatus().type == imap_polling_status_type_new_message)
{
/* Show the mailbox info */
MailClient.printf("\nMailbox status changed\n----------------------\nTotal Messages: %d\n", sFolder.msgCount());
MailClient.printf("New message %d, has been addedd, reading message...\n", (int)sFolder.pollingStatus().messageNum);
// we need to stop polling before do anything
imap.stopListen();
// Get the UID of new message and fetch
imap_data.fetch.uid = imap.getUID(sFolder.pollingStatus().messageNum);
// 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, false);
}
}
/* 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())
{
/* Get the message list from the message list data */
IMAP_MSG_List msgList = imap.data();
if (strcmp(msgList.msgItems[0].subject, sendingSubject.c_str()) == 0)
{
Serial.print("Sending Reply message... ");
std::string replyEmail = msgList.msgItems[0].reply_to;
// remove < at the beginning and > at the end.
replyEmail.erase(0, 1);
replyEmail.pop_back();
sendReplyMessage(msgList.msgItems[0].subject, replyEmail.c_str(), msgList.msgItems[0].ID, msgList.msgItems[0].references);
}
/* Clear all stored data in IMAPSession object */
imap.empty();
}
}
/* Callback function to get the Email sending status */
void helloSMTPCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
struct tm dt;
for (size_t i = 0; i < hello_smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = hello_smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up
hello_smtp.sendingResult.clear();
}
}
void replySMTPCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
struct tm dt;
for (size_t i = 0; i < reply_smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = reply_smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
reply_smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,304 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to log in with the SASL XOAUTH2 mechanisme using OAuth2.0 access token and send Email.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
/** For Gmail, to send the Email via port 465 (SSL), less secure app option
* should be enabled in the account settings. https://myaccount.google.com/lesssecureapps?pli=1
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT 25
/* The user Email for OAuth2.0 access token */
#define AUTHOR_EMAIL "<email>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/** The OAuth2.0 access token
* The generation, exchange and refresh of the access token are not available
* in this library.
*
* To test this using GMail, get the OAuth2.0 access token from this web site
* https://developers.google.com/oauthplayground/
*
*
* 1. Select the following scope (in Step 1) from Gmail API V1
* https://mail.google.com/
* https://mail.google.com/
*
* 2. Click Authorize APIs button.
* 3. Cick Exchangeauthorization code for tokens.
* 4. From the response, look at access_token from the JSON payload node.
* 5. Copy that access token and paste to the AUTHOR_ACCESS_TOKEN value.
*
* The token will be expired in 3600 seconds (1 Hr).
* The AUTHOR_EMAIL above is the Email address that you granted to access the Gmail services.
*/
#define AUTHOR_ACCESS_TOKEN "<access token>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.accessToken = AUTHOR_ACCESS_TOKEN;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending Email using Access token");
message.addRecipient(F("Admin"), RECIPIENT_EMAIL);
message.text.content = F("This is simple plain text message");
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,369 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email with attachments and inline images.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
/* This is for attachment data */
#include "blob_data.h"
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Enable the chunked data transfer with pipelining for large message if server supported */
message.enable.chunking = true;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending Email with attachments and inline images");
message.addRecipient(F("user1"), RECIPIENT_EMAIL);
message.html.content = F("<span style=\"color:#ff0000;\">This message contains 3 inline images and 1 attachment file.</span><br/><br/><img src=\"firebase_logo.png\" width=\"80\" height=\"60\"> <img src=\"tree.gif\" width=\"40\" height=\"60\"> <img src=\"bird.gif\" width=\"116\" height=\"75\">");
/** The HTML text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("utf-8");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
message.text.content = F("This message contains 3 inline images and 1 attachment file.\r\nThe inline images were not shown in the plain text message.");
message.text.charSet = F("utf-8");
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <user1@gmail.com>"));
/* The attachment data item */
SMTP_Attachment att[4];
int attIndex = 0;
/** Set the inline image info e.g.
* file name, MIME type, BLOB data, BLOB data size,
* transfer encoding (should be base64 for inline image)
*/
att[attIndex].descr.filename = F("firebase_logo.png");
att[attIndex].descr.mime = F("image/png");
att[attIndex].blob.data = firebase_logo_png;
att[attIndex].blob.size = sizeof(firebase_logo_png);
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att[attIndex]);
/** Set the inline image info e.g.
* file name, MIME type, BLOB data, BLOB data size.
* The default transfer encoding is base64.
*/
attIndex++;
att[attIndex].descr.filename = F("tree.gif");
att[attIndex].descr.mime = F("image/gif");
att[attIndex].blob.data = tree_img_gif;
att[attIndex].blob.size = sizeof(tree_img_gif);
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att[attIndex]);
/** Set the inline image info e.g.
* file name, MIME type, BLOB data, BLOB data size.
* The default transfer encoding is base64.
*/
attIndex++;
att[attIndex].descr.filename = F("bird.gif");
att[attIndex].descr.mime = F("image/gif");
att[attIndex].blob.data = bird_img_gif;
att[attIndex].blob.size = sizeof(bird_img_gif);
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att[attIndex]);
/* Prepare the attachment data (from ram) */
uint8_t *a = new uint8_t[512];
int j = 0;
for (int i = 0; i < 512; i++)
{
a[i] = j;
j++;
if (j > 255)
j = 0;
}
/** Set the attachment info e.g.
* file name, MIME type, BLOB data, BLOB data size.
* The default transfer encoding is base64.
*/
attIndex++;
att[attIndex].descr.filename = F("test.dat");
att[attIndex].descr.mime = F("application/octet-stream");
att[attIndex].blob.data = a;
att[attIndex].blob.size = 512;
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add attachment to the message */
message.addAttachment(att[attIndex]);
/* Connect to the server */
if (!smtp.connect(&config))
return;
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending the Email and close the session */
if (!MailClient.sendMail(&smtp, &message, true))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,443 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email with attachments and inline images stored in SD card.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// Provide the SD card interfaces setting and mounting
#include <extras/SDHelper.h>
// To use only SMTP functions, you can exclude the IMAP from compilation, see ESP_Mail_FS.h.
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
#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
Serial.println("Preparing SD file attachments...");
const char *orangeImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RMQ0AMAgAsCFgftHLiQpsENJaaFT+fqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBGi/oCaOpTXoAAAAASUVORK5CYII=";
// Write demo data to file
static uint8_t buf[512];
// SDFat?
#if defined(ESP_MAIL_USE_SDFAT) // ESP_MAIL_USE_SDFAT is auto defined when you set to use SdFat in src/ESP_Mail_FS.h
SdFile file;
file.open("/orange.png", O_RDWR | O_CREAT);
file.print(orangeImg);
file.close();
file.open("/bin1.dat", O_RDWR | O_CREAT);
buf[0] = 'H';
buf[1] = 'E';
buf[2] = 'A';
buf[3] = 'D';
file.write(buf, 4);
size_t i;
for (i = 0; i < 4; i++)
{
memset(buf, i + 1, 512);
file.write(buf, 512);
}
buf[0] = 'T';
buf[1] = 'A';
buf[2] = 'I';
buf[3] = 'L';
file.write(buf, 4);
file.close();
#else
#if defined(ESP32)
File file = ESP_MAIL_DEFAULT_SD_FS.open("/orange.png", FILE_WRITE);
#else
File file = ESP_MAIL_DEFAULT_SD_FS.open("/orange.png", "w");
#endif
file.print(orangeImg);
file.close();
#if defined(ESP32)
file = ESP_MAIL_DEFAULT_SD_FS.open("/bin1.dat", FILE_WRITE);
#else
file = ESP_MAIL_DEFAULT_SD_FS.open("/bin1.dat", "w");
#endif
buf[0] = 'H';
buf[1] = 'E';
buf[2] = 'A';
buf[3] = 'D';
file.write(buf, 4);
size_t i;
for (i = 0; i < 4; i++)
{
memset(buf, i + 1, 512);
file.write(buf, 512);
}
buf[0] = 'T';
buf[1] = 'A';
buf[2] = 'I';
buf[3] = 'L';
file.write(buf, 4);
file.close();
#endif
#endif
/* 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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Enable the chunked data transfer with pipelining for large message if server supported */
message.enable.chunking = true;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending Email with attachments and inline images from SD card and Flash");
message.addRecipient(F("user1"), RECIPIENT_EMAIL);
/** Two alternative content versions are sending in this example e.g. plain text and html */
String htmlMsg = "<span style=\"color:#ff0000;\">This message contains 1 inline image and 1 attachment file.</span><br/><br/><img src=\"orange.png\" width=\"100\" height=\"100\">";
message.html.content = htmlMsg;
/** The HTML text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("utf-8");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
message.text.content = F("This message contains 1 inline image and 1 attachment file.\r\nThe inline image will not show in the plain text message.");
message.text.charSet = F("utf-8");
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <user1@gmail.com>"));
/* The attachment data item */
SMTP_Attachment att[2];
int attIndex = 0;
/** Set the inline image info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
att[attIndex].descr.filename = F("orange.png");
att[attIndex].descr.mime = F("image/png");
att[attIndex].file.path = F("/orange.png");
/** 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
*/
att[attIndex].file.storage_type = esp_mail_file_storage_type_sd;
/* Need to be base64 transfer encoding for inline image */
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/** The orange.png file is already base64 encoded file.
* Then set the content encoding to match the transfer encoding
* which no encoding was taken place prior to sending.
*/
att[attIndex].descr.content_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att[attIndex]);
/** Set the attachment info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
attIndex++;
att[attIndex].descr.filename = F("bin1.dat");
att[attIndex].descr.mime = F("application/octet-stream"); // binary data
att[attIndex].descr.description = F("This is binary data");
att[attIndex].file.path = F("/bin1.dat");
att[attIndex].file.storage_type = esp_mail_file_storage_type_sd;
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add attachment to the message */
message.addAttachment(att[attIndex]);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending the Email and close the session */
if (!MailClient.sendMail(&smtp, &message, true))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,411 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email with attachments and inline images stored in SPIFFS/LittleFS filesystem.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only SMTP functions, you can exclude the IMAP from compilation, see ESP_Mail_FS.h.
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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_FLASH_FS) // defined in src/ESP_Mail_FS.h
// Mount SPIFFS/LittleFS filesystem.
ESP_MAIL_DEFAULT_FLASH_FS.begin();
Serial.println("Preparing flash file attachments...");
const char *orangeImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RMQ0AMAgAsCFgftHLiQpsENJaaFT+fqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBGi/oCaOpTXoAAAAASUVORK5CYII=";
// Write demo data to file
static uint8_t buf[512];
#if defined(ESP32)
File file = ESP_MAIL_DEFAULT_FLASH_FS.open("/orange.png", FILE_WRITE);
#else
File file = ESP_MAIL_DEFAULT_FLASH_FS.open("/orange.png", "w");
#endif
file.print(orangeImg);
file.close();
#if defined(ESP32)
file = ESP_MAIL_DEFAULT_FLASH_FS.open("/bin1.dat", FILE_WRITE);
#else
file = ESP_MAIL_DEFAULT_FLASH_FS.open("/bin1.dat", "w");
#endif
buf[0] = 'H';
buf[1] = 'E';
buf[2] = 'A';
buf[3] = 'D';
file.write(buf, 4);
size_t i;
for (i = 0; i < 4; i++)
{
memset(buf, i + 1, 512);
file.write(buf, 512);
}
buf[0] = 'T';
buf[1] = 'A';
buf[2] = 'I';
buf[3] = 'L';
file.write(buf, 4);
file.close();
#endif
/* Set the network reconnection option */
MailClient.networkReconnect(true);
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Enable the chunked data transfer with pipelining for large message if server supported */
message.enable.chunking = true;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending Email with attachments and inline images from flash filesystem");
message.addRecipient(F("user1"), RECIPIENT_EMAIL);
/** Two alternative content versions are sending in this example e.g. plain text and html */
String htmlMsg = "<span style=\"color:#ff0000;\">This message contains 1 inline image and 1 attachment file.</span><br/><br/><img src=\"orange.png\" width=\"100\" height=\"100\">";
message.html.content = htmlMsg;
/** The HTML text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("utf-8");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
message.text.content = F("This message contains 1 inline image and 1 attachment file.\r\nThe inline image will not show in the plain text message.");
message.text.charSet = F("utf-8");
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <user1@gmail.com>"));
/* The attachment data item */
SMTP_Attachment att[2];
int attIndex = 0;
/** Set the inline image info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
att[attIndex].descr.filename = F("orange.png");
att[attIndex].descr.mime = F("image/png");
att[attIndex].file.path = F("/orange.png");
/** 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
*/
att[attIndex].file.storage_type = esp_mail_file_storage_type_flash;
/* Need to be base64 transfer encoding for inline image */
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/** The orange.png file is already base64 encoded file.
* Then set the content encoding to match the transfer encoding
* which no encoding was taken place prior to sending.
*/
att[attIndex].descr.content_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att[attIndex]);
/** Set the attachment info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
attIndex++;
att[attIndex].descr.filename = F("bin1.dat");
att[attIndex].descr.mime = F("application/octet-stream"); // binary data
att[attIndex].descr.description = F("This is binary data");
att[attIndex].file.path = F("/bin1.dat");
att[attIndex].file.storage_type = esp_mail_file_storage_type_flash;
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add attachment to the message */
message.addAttachment(att[attIndex]);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending the Email and close the session */
if (!MailClient.sendMail(&smtp, &message, true))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,318 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email with attachment stored in PSRAM (ESP32 only).
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>
// To use only SMTP functions, you can exclude the IMAP from compilation, see ESP_Mail_FS.h.
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
"-----END CERTIFICATE-----\n";
void setup()
{
Serial.begin(115200);
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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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);
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email with PSRAM attachment");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
String textMsg = "This is simple plain text message with PSRAM attachment";
message.text.content = textMsg;
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
// If this is a reply message
// message.in_reply_to = "<parent message id>";
// message.references = "<parent references> <parent message id>";
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
// message.response.reply_to = "someone@somemail.com";
// message.response.return_path = "someone@somemail.com";
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
// For Root CA certificate verification (ESP8266 and ESP32 only)
// config.certificate.cert_data = rootCACert;
// or
// config.certificate.cert_file = "/path/to/der/file";
// config.certificate.cert_file_storage_type = esp_mail_file_storage_type_flash; // esp_mail_file_storage_type_sd
// config.certificate.verify = true;
// The WiFiNINA firmware the Root CA certification can be added via the option in Firmware update tool in Arduino IDE
/* The attachment data item */
SMTP_Attachment att[1];
int attIndex = 0;
#if defined(ESP32)
int dlen = 3 * 1024 * 1024 + 512 * 1024;
uint8_t *data = (uint8_t *)ps_malloc(dlen);
if (psramFound())
{
memset(data, 0xff, dlen);
att[attIndex].descr.filename = F("data.dat");
att[attIndex].descr.mime = F("application/octet-stream");
att[attIndex].descr.description = F("This is binary data");
att[attIndex].blob.data = data;
att[attIndex].blob.size = dlen;
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att[attIndex]);
}
#endif
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,325 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
/**
* This example shows how to send Email with inline image from ESP32 camera module.
*
* The ESP32 board used in this example is ESP32 PSRAM Timer Camera X (OV3660).
*/
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#endif
#include <ESP_Mail_Client.h>
#include "esp_camera.h"
// ===================
// Select camera model
// ===================
//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
#define CAMERA_MODEL_ESP_EYE // Has PSRAM
//#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
//#define CAMERA_MODEL_AI_THINKER // Has PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
//#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
// ** Espressif Internal Boards **
//#define CAMERA_MODEL_ESP32_CAM_BOARD
//#define CAMERA_MODEL_ESP32S2_CAM_BOARD
//#define CAMERA_MODEL_ESP32S3_CAM_LCD
//#define CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3 // Has PSRAM
//#define CAMERA_MODEL_DFRobot_Romeo_ESP32S3 // Has PSRAM
#include "camera_pins.h"
// The camera_pins.h was taken from
//https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Camera/CameraWebServer
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
void setup()
{
Serial.begin(115200);
Serial.println();
camera_config_t camCfg;
camCfg.ledc_channel = LEDC_CHANNEL_0;
camCfg.ledc_timer = LEDC_TIMER_0;
camCfg.pin_d0 = Y2_GPIO_NUM;
camCfg.pin_d1 = Y3_GPIO_NUM;
camCfg.pin_d2 = Y4_GPIO_NUM;
camCfg.pin_d3 = Y5_GPIO_NUM;
camCfg.pin_d4 = Y6_GPIO_NUM;
camCfg.pin_d5 = Y7_GPIO_NUM;
camCfg.pin_d6 = Y8_GPIO_NUM;
camCfg.pin_d7 = Y9_GPIO_NUM;
camCfg.pin_xclk = XCLK_GPIO_NUM;
camCfg.pin_pclk = PCLK_GPIO_NUM;
camCfg.pin_vsync = VSYNC_GPIO_NUM;
camCfg.pin_href = HREF_GPIO_NUM;
camCfg.pin_sscb_sda = SIOD_GPIO_NUM;
camCfg.pin_sscb_scl = SIOC_GPIO_NUM;
camCfg.pin_pwdn = PWDN_GPIO_NUM;
camCfg.pin_reset = RESET_GPIO_NUM;
camCfg.xclk_freq_hz = 20000000;
camCfg.pixel_format = PIXFORMAT_JPEG;
camCfg.frame_size = FRAMESIZE_QXGA;
camCfg.jpeg_quality = 10;
camCfg.fb_count = 2;
// camera init
esp_err_t err = esp_camera_init(&camCfg);
if (err != ESP_OK)
{
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
Serial.print("Connecting to AP");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(200);
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println();
/* Set the network reconnection option */
MailClient.networkReconnect(true);
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Enable the chunked data transfer with pipelining for large message if server supported */
message.enable.chunking = true;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending camera image");
message.addRecipient(F("user1"), RECIPIENT_EMAIL);
message.html.content = F("<span style=\"color:#ff0000;\">The camera image.</span><br/><br/><img src=\"cid:image-001\" alt=\"esp32 cam image\" width=\"2048\" height=\"1536\">");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded) <- not supported for message from blob and file
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
/** The HTML text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("utf-8");
camera_fb_t *fb = esp_camera_fb_get();
SMTP_Attachment att;
/** Set the inline image info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
att.descr.filename = F("camera.jpg");
att.descr.mime = F("image/jpg");
att.blob.data = fb->buf;
att.blob.size = fb->len;
att.descr.content_id = F("image-001"); // The content id (cid) of camera.jpg image in the src tag
/* Need to be base64 transfer encoding for inline image */
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add inline image to the message */
message.addInlineImage(att);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending the Email and close the session */
if (!MailClient.sendMail(&smtp, &message, true))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,317 @@
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 37
#define Y7_GPIO_NUM 38
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 35
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 13
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#define LED_GPIO_NUM 22
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_V2_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 22
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#define LED_GPIO_NUM 2
#elif defined(CAMERA_MODEL_M5STACK_ESP32CAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_M5STACK_UNITCAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// 4 for flash led or 33 for normal led
#define LED_GPIO_NUM 4
#elif defined(CAMERA_MODEL_TTGO_T_JOURNAL)
#define PWDN_GPIO_NUM 0
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 17
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_XIAO_ESP32S3)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 10
#define SIOD_GPIO_NUM 40
#define SIOC_GPIO_NUM 39
#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 12
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 16
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 17
#define Y2_GPIO_NUM 15
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 47
#define PCLK_GPIO_NUM 13
#elif defined(CAMERA_MODEL_ESP32_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM 33
#define XCLK_GPIO_NUM 4
#define SIOD_GPIO_NUM 18
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 36
#define Y8_GPIO_NUM 19
#define Y7_GPIO_NUM 21
#define Y6_GPIO_NUM 39
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 13
#else
#define Y5_GPIO_NUM 35
#endif
#define Y4_GPIO_NUM 14
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 35
#else
#define Y3_GPIO_NUM 13
#endif
#define Y2_GPIO_NUM 34
#define VSYNC_GPIO_NUM 5
#define HREF_GPIO_NUM 27
#define PCLK_GPIO_NUM 25
#elif defined(CAMERA_MODEL_ESP32S3_CAM_LCD)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 40
#define SIOD_GPIO_NUM 17
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 39
#define Y8_GPIO_NUM 41
#define Y7_GPIO_NUM 42
#define Y6_GPIO_NUM 12
#define Y5_GPIO_NUM 3
#define Y4_GPIO_NUM 14
#define Y3_GPIO_NUM 47
#define Y2_GPIO_NUM 13
#define VSYNC_GPIO_NUM 21
#define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 11
#elif defined(CAMERA_MODEL_ESP32S2_CAM_BOARD)
// The 18 pin header on the board has Y5 and Y3 swapped
#define USE_BOARD_HEADER 0
#define PWDN_GPIO_NUM 1
#define RESET_GPIO_NUM 2
#define XCLK_GPIO_NUM 42
#define SIOD_GPIO_NUM 41
#define SIOC_GPIO_NUM 18
#define Y9_GPIO_NUM 16
#define Y8_GPIO_NUM 39
#define Y7_GPIO_NUM 40
#define Y6_GPIO_NUM 15
#if USE_BOARD_HEADER
#define Y5_GPIO_NUM 12
#else
#define Y5_GPIO_NUM 13
#endif
#define Y4_GPIO_NUM 5
#if USE_BOARD_HEADER
#define Y3_GPIO_NUM 13
#else
#define Y3_GPIO_NUM 12
#endif
#define Y2_GPIO_NUM 14
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 4
#define PCLK_GPIO_NUM 3
#elif defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5
#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13
#elif defined(CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3) || defined(CAMERA_MODEL_DFRobot_Romeo_ESP32S3)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 45
#define SIOD_GPIO_NUM 1
#define SIOC_GPIO_NUM 2
#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 46
#define Y7_GPIO_NUM 8
#define Y6_GPIO_NUM 7
#define Y5_GPIO_NUM 4
#define Y4_GPIO_NUM 41
#define Y3_GPIO_NUM 40
#define Y2_GPIO_NUM 39
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 42
#define PCLK_GPIO_NUM 5
#else
#error "Camera model not selected"
#endif

View File

@ -0,0 +1,303 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email which the html and text message will be embedded as attachment or inline content.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
// To use only SMTP functions, you can exclude the IMAP from compilation, see ESP_Mail_FS.h.
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending message as embedded files");
message.addRecipient(F("Admin"), RECIPIENT_EMAIL);
message.html.content = F("<span style=\"color:#0055ff;\">This is html message</span>");
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("utf-8");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
/* Enable to send this message body as file */
message.html.embed.enable = true;
/* The name of embedded file */
message.html.embed.filename = F("test.html");
/** The embedded type
* esp_mail_smtp_embed_message_type_attachment or 0
* esp_mail_smtp_embed_message_type_inline or 1
*/
message.html.embed.type = esp_mail_smtp_embed_message_type_attachment;
message.text.content = F("This is simple plain text message");
message.text.charSet = F("utf-8");
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
message.text.embed.enable = true;
message.text.embed.filename = F("test.txt");
message.text.embed.type = esp_mail_smtp_embed_message_type_inline;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,293 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email in enriched text version.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending enriched text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
message.text.content = F("This is <bold><italic>enriched </italic></bold> <smaller>as defined in RFC 1896</smaller>\r\n\r\nIsn't it <bigger><bigger>cool?</bigger></bigger>");
message.text.content_type = F("text/enriched");
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,301 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send html message.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* The full message sending logs can now save to file */
/* Since v3.0.4, the sent logs stored in smtp.sendingResult will store only the latest message logs */
// config.sentLogs.filename = "/path/to/log/file";
// config.sentLogs.storage_type = esp_mail_file_storage_type_flash;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending html Email");
message.addRecipient(F("Admin"), RECIPIENT_EMAIL);
String htmlMsg = "<p>This is the <span style=\"color:#ff0000;\">html text</span> message.</p><p>The message was sent via ESP device.</p>";
message.html.content = htmlMsg;
/** The html text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
/* Set the TCP response read timeout in seconds */
// smtp.setTCPTimeout(10);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,334 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*
*/
/**
* This example shows how to send Email with media e.g. audio and images as parallen attachments,
* and play or display them simultaneously on the Email client (depends on the Mail client supports).
*/
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
/* This is for attachment data */
#include "data.h"
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Enable the chunked data transfer with pipelining for large message if server supported */
message.enable.chunking = true;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending Email with parallel attachments");
message.addRecipient(F("user1"), RECIPIENT_EMAIL);
message.html.content = F("<span style=\"color:#ff0000;\">This message contains image and audio file which will play on the Mail client in parallel or simultaneously (depends on the client supports).");
/** The HTML text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.html.charSet = F("utf-8");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
message.text.content = F("This message contains image and audio file which will play on the Mail client in parallel or simultaneously (depends on the client supports).");
message.text.charSet = F("us-ascii");
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <user1@gmail.com>"));
/* The attachment data item */
SMTP_Attachment att;
/** Set the attachment info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
att.descr.filename = F("haun.png");
att.descr.mime = F("image/png");
att.blob.data = shaun_png;
att.blob.size = sizeof(shaun_png);
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
message.addParallelAttachment(att);
/** Set the attachment info e.g.
* file name, MIME type, file path, file storage type,
* transfer encoding and content encoding
*/
message.resetAttachItem(att); // Clear the attach item data to reuse
att.descr.filename = F("mu_law.wav");
att.descr.mime = F("audio/basic");
att.blob.data = mu_law_wave;
att.blob.size = sizeof(mu_law_wave);
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
message.addParallelAttachment(att);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
/* Start sending the Email and close the session */
if (!MailClient.sendMail(&smtp, &message, true))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,360 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send Email message with attachment
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
/* This is for attachment data */
#include "image.h"
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending Email with rfc822 attachment");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
message.text.content = F("This is simple plain text message with rfc822 attachment");
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
SMTP_Message rfc822;
rfc822.messageID = F("1234@local.machine.example");
rfc822.from.name = F("rob");
rfc822.from.email = F("rob@example.com");
rfc822.sender.name = F("steve");
rfc822.sender.email = F("steve@example.com");
// This date field will set by default if the device time was already set or set date field manually
rfc822.date = MailClient.Time.getDateTimeString();
rfc822.subject = F("Test rfc822 message");
rfc822.comments = F("This is comment");
rfc822.addRecipient(F("joe"), F("joe@example.com"));
rfc822.response.reply_to = F("rob@example.com");
rfc822.text.charSet = F("utf-8");
rfc822.text.content = F("This is rfc822 text message");
rfc822.text.transfer_encoding = Content_Transfer_Encoding::enc_qp;
rfc822.html.charSet = F("utf-8");
rfc822.html.content = F("This is rfc822 html message");
rfc822.html.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* The attachment data item */
SMTP_Attachment att[2];
int attIndex = 0;
/** Set the attachment info e.g.
* file name, MIME type, BLOB data, BLOB data size,
* and transfer encoding
*/
att[attIndex].descr.filename = F("firebase_logo.png");
att[attIndex].descr.mime = F("image/png");
att[attIndex].blob.data = firebase_png;
att[attIndex].blob.size = sizeof(firebase_png);
att[attIndex].descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
/* Add the attachment to the rfc822 message */
#if defined(ESP32) || defined(ESP8266)
rfc822.addAttachment(att[attIndex]); // Required more stack and may fail on SAMD
#endif
/* Prepare other attachment data */
uint8_t *a = new uint8_t[512];
int j = 0;
for (int i = 0; i < 512; i++)
{
a[i] = j;
j++;
if (j > 255)
j = 0;
}
/** Set the attachment info e.g.
* file name, MIME type, BLOB data, BLOB data size.
* The default transfer encoding is base64.
*/
attIndex++;
att[attIndex].descr.filename = F("test.dat");
att[attIndex].descr.mime = F("application/octet-stream");
att[attIndex].blob.data = a;
att[attIndex].blob.size = 512;
/* Add this attachment to the message */
message.addAttachment(att[attIndex]);
/* Add rfc822 message in the message */
message.addMessage(rfc822);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (!smtp.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,242 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example show how to login once for sending multiple messages.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
Session_Config config;
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
#include "HeapStat.h"
HeapStat heapInfo;
unsigned long sentMillis = 0;
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
smtp.debug(1);
smtp.callback(smtpCallback);
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
}
void loop()
{
if (millis() - sentMillis > 3 * 60 * 1000 || sentMillis == 0)
{
sentMillis = millis();
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Send Email with session reusage");
message.addRecipient(F("user"), RECIPIENT_EMAIL);
message.html.content = F("<p>This is the HTML message.</p>");
message.text.content = F("This is the text message");
Serial.println();
Serial.println("Sending Email...");
if (!smtp.isLoggedIn())
{
/* Set the TCP response read timeout in seconds */
// smtp.setTCPTimeout(10);
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
goto exit;
}
if (!smtp.isLoggedIn())
{
Serial.println("\nError, Not yet logged in.");
goto exit;
}
else
{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
}
if (!MailClient.sendMail(&smtp, &message, false))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
exit:
heapInfo.collect();
heapInfo.print();
}
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,197 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send text message without callback and debug.
/**
* To use library in silent mode (no debug printing and callback), please define this macro in src/ESP_Mail_FS.h.
* #define SILENT_MODE
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define SMTP_HOST "<host>"
#define SMTP_PORT esp_mail_smtp_port_587
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
void printSmtpData(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
Session_Config config;
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
SMTP_Message message;
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
String textMsg = "This is simple plain text message";
message.text.content = textMsg;
message.text.charSet = F("us-ascii");
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (!smtp.isLoggedIn())
{
Serial.println("Not yet logged in.");
}
else
{
if (smtp.isAuthenticated())
Serial.println("Successfully logged in.");
else
Serial.println("Connected with no Auth.");
}
if (MailClient.sendMail(&smtp, &message))
{
printSmtpData(smtp.status());
}
else
{
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
}
smtp.sendingResult.clear();
}
void loop()
{
}
void printSmtpData(SMTP_Status status)
{
if (status.success())
{
Serial.println("\n----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,396 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to send text message.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587 // port 465 is not available for Outlook.com
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
// const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
// "-----END CERTIFICATE-----\n";
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/** If non-secure port is prefered (not allow SSL and TLS connection), use
* config.secure.mode = esp_mail_secure_mode_nonsecure;
*
* If SSL and TLS are always required, use
* config.secure.mode = esp_mail_secure_mode_ssl_tls;
*
* To disable SSL permanently (use less program space), define ESP_MAIL_DISABLE_SSL in ESP_Mail_FS.h
* or Custom_ESP_Mail_FS.h
*/
// config.secure.mode = esp_mail_secure_mode_nonsecure;
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* The full message sending logs can now save to file */
/* Since v3.0.4, the sent logs stored in smtp.sendingResult will store only the latest message logs */
// config.sentLogs.filename = "/path/to/log/file";
// config.sentLogs.storage_type = esp_mail_file_storage_type_flash;
/** In ESP32, timezone environment will not keep after wake up boot from sleep.
* The local time will equal to GMT time.
*
* To sync or set time with NTP server with the valid local time after wake up boot,
* set both gmt and day light offsets to 0 and assign the timezone environment string e.g.
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 0;
config.time.day_light_offset = 0;
config.time.timezone_env_string = "JST-9"; // for Tokyo
* The library will get (sync) the time from NTP server without GMT time offset adjustment
* and set the timezone environment variable later.
*
* This timezone environment string will be stored to flash or SD file named "/tze.txt"
* which set via config.time.timezone_file.
*
* See the timezone environment string list from
* https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
*
*/
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
/** If author and sender are not identical
message.sender.name = F("Sender");
message.sender.email = "sender@mail.com";
message.author.name = F("ESP Mail");
message.author.email = AUTHOR_EMAIL; // should be the same email as config.login.email
*/
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
String textMsg = "This is simple plain text message";
message.text.content = textMsg;
/** If the message to send is a large string, to reduce the memory used from internal copying while sending,
* you can assign string to message.text.blob by cast your string to uint8_t array like this
*
* String myBigString = "..... ......";
* message.text.blob.data = (uint8_t *)myBigString.c_str();
* message.text.blob.size = myBigString.length();
*
* or assign string to message.text.nonCopyContent, like this
*
* message.text.nonCopyContent = myBigString.c_str();
*
* Only base64 encoding is supported for content transfer encoding in this case.
*/
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
// If this is a reply message
// message.in_reply_to = "<parent message id>";
// message.references = "<parent references> <parent message id>";
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
// message.response.reply_to = "someone@somemail.com";
// message.response.return_path = "someone@somemail.com";
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
// For Root CA certificate verification (ESP8266 and ESP32 only)
// config.certificate.cert_data = rootCACert;
// or
// config.certificate.cert_file = "/path/to/der/file";
// config.certificate.cert_file_storage_type = esp_mail_file_storage_type_flash; // esp_mail_file_storage_type_sd
// config.certificate.verify = true;
// The WiFiNINA firmware the Root CA certification can be added via the option in Firmware update tool in Arduino IDE
/* Connect to server with the session config */
// Library will be trying to sync the time with NTP server if time is never sync or set.
// This is 10 seconds blocking process.
// If time reading was timed out, the error "NTP server time reading timed out" will show via debug and callback function.
// You can manually sync time by yourself with NTP library or calling configTime in ESP32 and ESP8266.
// Time can be set manually with provided timestamp to function smtp.setSystemTime.
/* Set the TCP response read timeout in seconds */
// smtp.setTCPTimeout(10);
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
/** Or connect without log in and log in later
if (!smtp.connect(&config, false))
return;
if (!smtp.loginWithPassword(AUTHOR_EMAIL, AUTHOR_PASSWORD))
return;
*/
if (!smtp.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,308 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example shows how to send text message with text wrapping.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, the app password will be used for log in
* Check out https://github.com/mobizt/ESP-Mail-Client#gmail-smtp-and-imap-required-app-passwords-to-sign-in
*
* 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
#if defined(ARDUINO_ARCH_SAMD)
while (!Serial)
;
#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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
/** Assign your host name or you public IPv4 or IPv6 only
* as this is the part of EHLO/HELO command to identify the client system
* to prevent connection rejection.
* If host name or public IP is not available, ignore this or
* use loopback address "127.0.0.1".
*
* Assign any text to this option may cause the connection rejection.
*/
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 3;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
/** The option to add soft line break to to the message for
* the long text message > 78 characters (rfc 3676)
* Some Servers may not compliant with this standard.
*/
message.text.flowed = true;
/** if the option message.text.flowed is true,
* the following plain text message will be wrapped.
*/
message.text.content = F("The text below is the long quoted text which breaks into several lines.\r\n\r\n>> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\r\n\r\nThis is the normal short text.\r\n\r\nAnother long text, abcdefg hijklmnop qrstuv wxyz abcdefg hijklmnop qrstuv wxyz abcdefg hijklmnop qrstuv wxyz.");
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (!smtp.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,253 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how to set the library and/or device time manually.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#include "RTC.h"
#endif
#include <ESP_Mail_Client.h>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
#define SMTP_HOST "<host>"
#define SMTP_PORT esp_mail_smtp_port_587
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
#define RECIPIENT_EMAIL "<recipient email here>"
SMTPSession smtp;
void smtpCallback(SMTP_Status status);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif
void setup()
{
Serial.begin(115200);
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");
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
unsigned long ms = millis();
#endif
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();
Serial.print("Waiting for NTP server time reading");
#if defined(ESP8266) || defined(ESP32) && !defined(ARDUINO_NANO_RP2040_CONNECT)
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
while (time(nullptr) < ESP_MAIL_CLIENT_VALID_TS)
{
delay(100);
}
#elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
configTime(10000, 0, "pool.ntp.org", "time.nist.gov");
while (time(nullptr) < ESP_MAIL_CLIENT_VALID_TS)
{
delay(100);
}
#elif __has_include(<WiFiNINA.h>) || __has_include(<WiFi101.h>)
time_t ts = 0;
do
{
ts = WiFi.getTime();
delay(100);
} while (ts < ESP_MAIL_CLIENT_VALID_TS);
float gmtOffset = 3.0; // GMT offset in hour
smtp.setSystemTime(ts, gmtOffset);
#elif __has_include(<WiFiS3.h>)
// see https://docs.arduino.cc/tutorials/uno-r4-wifi/rtc
RTC.begin();
// RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);
// RTC.setTime(startTime);
RTCTime currentTime;
// Get current time from RTC
RTC.getTime(currentTime);
float gmtOffset = 3.0; // GMT offset in hour
smtp.setSystemTime(currentTime.getUnixTime(), gmtOffset);
#endif
// To disable library internal NTP time reading, please comment or remove the following macro defined in src/ESP_Mail_FS.h
// #define ENABLE_NTP_TIME
MailClient.networkReconnect(true);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
MailClient.clearAP();
MailClient.addAP(WIFI_SSID, WIFI_PASSWORD);
#endif
smtp.debug(1);
smtp.callback(smtpCallback);
Session_Config config;
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
/**
* Once the system time (using smtp.setSystemTime) or device time was set before calling smtp.connect, the following config will
* not take effect when NTP time is enabled.
*
* config.time.ntp_server
* config.time.gmt_offset
* config.time.day_light_offset
*
* To reset the reference time and use config.time instead, call smtp.setSystemTime(0) whenever you want.
*/
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail");
message.sender.email = AUTHOR_EMAIL;
message.addRecipient(F("Someone"), RECIPIENT_EMAIL);
/* The time format of timestamp to inject into subject or content as using in strftime C++ function */
message.timestamp.tag = "#esp_mail_current_time";
/* The tag that will be replaced with current timestamp */
message.timestamp.format = "%B %d, %Y %H:%M:%S";
message.subject = F("Test sending plain text Email (#esp_mail_current_time)");
message.text.content = "This is simple plain text message\n\nSent #esp_mail_current_time";
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (!smtp.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
}
void loop()
{
}
void smtpCallback(SMTP_Status status)
{
Serial.println(status.info());
if (status.success())
{
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
SMTP_Result result = smtp.sendingResult.getItem(i);
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
smtp.sendingResult.clear();
}
}

View File

@ -0,0 +1,310 @@
/**
* Created by K. Suwatchai (Mobizt)
*
* Email: suwatchai@outlook.com
*
* Github: https://github.com/mobizt/ESP-Mail-Client
*
* Copyright (c) 2023 mobizt
*/
// This example showes how the device time was resume after device woke up from sleep.
/** Note for library update from v2.x.x to v3.x.x.
*
* Struct data names changed
*
* "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;
*/
#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.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>
#define WIFI_SSID "<ssid>"
#define WIFI_PASSWORD "<password>"
/** For Gmail, to send Email via port 465 (SSL), less secure app option
* should be enabled in the account settings. https://myaccount.google.com/lesssecureapps?pli=1
*
* Some Gmail user still not able to sign in using account password even above option was 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 smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "<host>"
/** The smtp port e.g.
* 25 or esp_mail_smtp_port_25
* 465 or esp_mail_smtp_port_465
* 587 or esp_mail_smtp_port_587
*/
#define SMTP_PORT esp_mail_smtp_port_587 // port 465 is not available for Outlook.com
/* The log in credentials */
#define AUTHOR_EMAIL "<email>"
#define AUTHOR_PASSWORD "<password>"
/* Recipient email address */
#define RECIPIENT_EMAIL "<recipient email here>"
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
"-----END CERTIFICATE-----\n";
void sendEmail()
{
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = F("127.0.0.1");
/*
Set the NTP config time
For times east of the Prime Meridian use 0-12
For times west of the Prime Meridian add 12 to the offset.
Ex. American/Denver GMT would be -6. 6 + 12 = 18
See https://en.wikipedia.org/wiki/Time_zone for a list of the GMT/UTC timezone offsets
*/
config.time.ntp_server = F("pool.ntp.org,time.nist.gov");
config.time.gmt_offset = 0;
config.time.day_light_offset = 0;
config.time.timezone_env_string = "JST-9"; // for Tokyo
// See the timezone environment string list from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP Mail"); // This witll be used with 'MAIL FROM' command and 'From' header field.
message.sender.email = AUTHOR_EMAIL; // This witll be used with 'From' header field.
message.subject = F("Test sending plain text Email");
message.addRecipient(F("Someone"), RECIPIENT_EMAIL); // This will be used with RCPT TO command and 'To' header field.
String textMsg = "This is simple plain text message";
message.text.content = textMsg;
/** If the message to send is a large string, to reduce the memory used from internal copying while sending,
* you can assign string to message.text.blob by cast your string to uint8_t array like this
*
* String myBigString = "..... ......";
* message.text.blob.data = (uint8_t *)myBigString.c_str();
* message.text.blob.size = myBigString.length();
*
* or assign string to message.text.nonCopyContent, like this
*
* message.text.nonCopyContent = myBigString.c_str();
*
* Only base64 encoding is supported for content transfer encoding in this case.
*/
/** The Plain text message character set e.g.
* us-ascii
* utf-8
* utf-7
* The default value is utf-8
*/
message.text.charSet = F("us-ascii");
/** The content transfer encoding e.g.
* enc_7bit or "7bit" (not encoded)
* enc_qp or "quoted-printable" (encoded)
* enc_base64 or "base64" (encoded)
* enc_binary or "binary" (not encoded)
* enc_8bit or "8bit" (not encoded)
* The default value is "7bit"
*/
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
// If this is a reply message
// message.in_reply_to = "<parent message id>";
// message.references = "<parent references> <parent message id>";
/** The message priority
* esp_mail_smtp_priority_high or 1
* esp_mail_smtp_priority_normal or 3
* esp_mail_smtp_priority_low or 5
* The default value is esp_mail_smtp_priority_low
*/
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
// message.response.reply_to = "someone@somemail.com";
// message.response.return_path = "someone@somemail.com";
/** The Delivery Status Notifications e.g.
* esp_mail_smtp_notify_never
* esp_mail_smtp_notify_success
* esp_mail_smtp_notify_failure
* esp_mail_smtp_notify_delay
* The default value is esp_mail_smtp_notify_never
*/
// message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Set the custom message header */
message.addHeader(F("Message-ID: <abcde.fghij@gmail.com>"));
// For Root CA certificate verification (ESP8266 and ESP32 only)
// config.certificate.cert_data = rootCACert;
// or
// config.certificate.cert_file = "/path/to/der/file";
// config.certificate.cert_file_storage_type = esp_mail_file_storage_type_flash; // esp_mail_file_storage_type_sd
// config.certificate.verify = true;
// The WiFiNINA firmware the Root CA certification can be added via the option in Firmware update tool in Arduino IDE
/* Connect to server with the session config */
// Library will be trying to sync the time with NTP server if time is never sync or set.
// This is 10 seconds blocking process.
// If time reading was timed out, the error "NTP server time reading timed out" will show via debug and callback function.
// You can manually sync time by yourself with NTP library or calling configTime in ESP32 and ESP8266.
// Time can be set manually with provided timestamp to function smtp.setSystemTime.
/* Connect to the server */
if (!smtp.connect(&config))
{
MailClient.printf("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
/* Start sending Email and close the session */
if (!MailClient.sendMail(&smtp, &message))
MailClient.printf("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
// to clear sending result log
// smtp.sendingResult.clear();
MailClient.printf("Free Heap: %d\n", MailClient.getFreeHeap());
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("Connecting to AP");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(200);
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println();
/** 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
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
sendEmail();
// Sleep for 60 seconds
Serial.println("Going to sleep for 60 seconds...");
#if defined(ESP32)
esp_sleep_enable_timer_wakeup(60 * 1000000);
esp_deep_sleep_start();
#endif
}
void loop()
{
}
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success())
{
// MailClient.printf used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. AVR, SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
MailClient.printf("Message sent success: %d\n", status.completedCount());
MailClient.printf("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
struct tm dt;
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
// In case, ESP32, ESP8266 and SAMD device, the timestamp get from result.timestamp should be valid if
// your device time was synched with NTP server.
// Other devices may show invalid timestamp as the device time was not set i.e. it will show Jan 1, 1970.
// You can call smtp.setSystemTime(xxx) to set device time manually. Where xxx is timestamp (seconds since Jan 1, 1970)
MailClient.printf("Message No: %d\n", i + 1);
MailClient.printf("Status: %s\n", result.completed ? "success" : "failed");
MailClient.printf("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());
MailClient.printf("Recipient: %s\n", result.recipients.c_str());
MailClient.printf("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}

View File

@ -1,127 +1,194 @@
######################################
# Syntax Coloring Map ESP Mail Client
######################################
#######################################
# Classes and Structured Type (KEYWORD1)
#######################################
MailClient KEYWORD1
IMAPSession KEYWORD1
SMTPSession KEYWORD1
SMTP_Message KEYWORD1
IMAP_Config KEYWORD1
FoldersCollection KEYWORD1
imapStatusCallback KEYWORD1
IMAP_MSG_List KEYWORD1
SelectedFolderInfo KEYWORD1
ESP_Mail_Session KEYWORD1
smtpStatusCallback KEYWORD1
SMTP_Attachment KEYWORD1
SMTP_Result KEYWORD1
IMAP_MSG_Item KEYWORD1
Content_Transfer_Encoding KEYWORD1
MessageList KEYWORD1
###############################################
# Methods and Functions (KEYWORD2)
###############################################
sendMail KEYWORD2
readMail KEYWORD2
setFlag KEYWORD2
addFlag KEYWORD2
removeFlag KEYWORD2
sdBegin KEYWORD2
sdMMCBegin KEYWORD2
connect KEYWORD2
closeSession KEYWORD2
debug KEYWORD2
getFolders KEYWORD2
selectFolder KEYWORD2
openFolder KEYWORD2
closeFolder KEYWORD2
callback KEYWORD2
headerOnly KEYWORD2
data KEYWORD2
selectedFolder KEYWORD2
errorReason KEYWORD2
empty KEYWORD2
resetAttachItem KEYWORD2
clear KEYWORD2
clearInlineimages KEYWORD2
clearAttachments KEYWORD2
clearRFC822Messages KEYWORD2
clearRecipients KEYWORD2
clearCc KEYWORD2
clearBcc KEYWORD2
clearHeader KEYWORD2
addAttachment KEYWORD2
addParallelAttachment KEYWORD2
addInlineImage KEYWORD2
addMessage KEYWORD2
addRecipient KEYWORD2
addCc KEYWORD2
addBcc KEYWORD2
addHeader KEYWORD2
info KEYWORD2
successs KEYWORD2
completedCount KEYWORD2
failedCount KEYWORD2
getItem KEYWORD2
size KEYWORD2
flagCount KEYWORD2
msgCount KEYWORD2
nextUID KEYWORD2
searchCount KEYWORD2
availableMessages KEYWORD2
flag KEYWORD2
setClock KEYWORD2
getUnixTime KEYWORD2
getTimestamp KEYWORD2
getYear KEYWORD2
getMonth KEYWORD2
getDay KEYWORD2
getDayOfWeek KEYWORD2
getDayOfWeekString KEYWORD2
getHour KEYWORD2
getMin KEYWORD2
getSecond KEYWORD2
getNumberOfDayThisYear KEYWORD2
getTotalDays KEYWORD2
dayofWeek KEYWORD2
getCurrentSecond KEYWORD2
getCurrentTimestamp KEYWORD2
getTimeFromSec KEYWORD2
getDateTimeString KEYWORD2
copyMessages KEYWORD2
deleteMessages KEYWORD2
createFolder KEYWORD2
deleteFolder KEYWORD2
#######################################
# Struct (KEYWORD3)
#######################################
esp_mail_email_info_t KEYWORD3
esp_mail_plain_body_t KEYWORD3
esp_mail_html_body_t KEYWORD3
esp_mail_smtp_msg_response_t KEYWORD3
esp_mail_smtp_enable_option_t KEYWORD3
esp_mail_email_info_t KEYWORD3
esp_mail_folder_info_item_t KEYWORD3
esp_mail_sesson_sever_config_t KEYWORD3
esp_mail_sesson_login_config_t KEYWORD3
esp_mail_sesson_secure_config_t KEYWORD3
esp_mail_sesson_cert_config_t KEYWORD3
esp_mail_imap_fetch_config_t KEYWORD3
esp_mail_imap_search_config_t KEYWORD3
esp_mail_imap_limit_config_t KEYWORD3
esp_mail_imap_enable_config_t KEYWORD3
esp_mail_imap_download_config_t KEYWORD3
esp_mail_imap_storage_config_t KEYWORD3
esp_mail_file_storage_type_none KEYWORD3
esp_mail_file_storage_type_flash KEYWORD3
esp_mail_file_storage_type_sd KEYWORD3
######################################
# Syntax Coloring Map ESP Mail Client
######################################
#######################################
# Classes and Structured Type (KEYWORD1)
#######################################
MailClient KEYWORD1
IMAPSession KEYWORD1
SMTPSession KEYWORD1
SMTP_Message KEYWORD1
IMAP_Config KEYWORD1
IMAP_Data KEYWORD2
FoldersCollection KEYWORD1
imapStatusCallback KEYWORD1
IMAP_MSG_List KEYWORD1
SelectedFolderInfo KEYWORD1
ESP_Mail_Session KEYWORD1
Session_Config KEYWORD1
smtpStatusCallback KEYWORD1
imapResponseCallback KEYWORD1
SMTP_Attachment KEYWORD1
SMTP_Result KEYWORD1
IMAP_MSG_Item KEYWORD1
Content_Transfer_Encoding KEYWORD1
MessageList KEYWORD1
###############################################
# Methods and Functions (KEYWORD2)
###############################################
sendMail KEYWORD2
appendMessage KEYWORD2
readMail KEYWORD2
setFlag KEYWORD2
addFlag KEYWORD2
removeFlag KEYWORD2
networkReconnect KEYWORD2
sdBegin KEYWORD2
sdMMCBegin KEYWORD2
getFreeHeap KEYWORD2
connect KEYWORD2
loginWithPassword KEYWORD2
loginWithAccessToken KEYWORD2
isAuthenticated KEYWORD2
isLoggedIn KEYWORD2
connected KEYWORD2
keepAlive KEYWORD2
isKeepAlive KEYWORD2
customConnect KEYWORD2
closeSession KEYWORD2
debug KEYWORD2
getFolders KEYWORD2
selectFolder KEYWORD2
openFolder KEYWORD2
closeFolder KEYWORD2
callback KEYWORD2
headerOnly KEYWORD2
data KEYWORD2
selectedFolder KEYWORD2
errorReason KEYWORD2
statusCode KEYWORD2
statusMessage KEYWORD2
errorCode KEYWORD2
empty KEYWORD2
resetAttachItem KEYWORD2
clear KEYWORD2
clearInlineimages KEYWORD2
clearAttachments KEYWORD2
clearRFC822Messages KEYWORD2
clearRecipients KEYWORD2
clearCc KEYWORD2
clearBcc KEYWORD2
clearHeader KEYWORD2
addAttachment KEYWORD2
addParallelAttachment KEYWORD2
addInlineImage KEYWORD2
addMessage KEYWORD2
addRecipient KEYWORD2
addCc KEYWORD2
addBcc KEYWORD2
addHeader KEYWORD2
info KEYWORD2
successs KEYWORD2
completedCount KEYWORD2
failedCount KEYWORD2
getItem KEYWORD2
size KEYWORD2
flagCount KEYWORD2
msgCount KEYWORD2
recentCount KEYWORD2
nextUID KEYWORD2
pollingStatus KEYWORD2
searchCount KEYWORD2
availableMessages KEYWORD2
flag KEYWORD2
setClock KEYWORD2
getUnixTime KEYWORD2
getTimestamp KEYWORD2
getYear KEYWORD2
getMonth KEYWORD2
getDay KEYWORD2
getDayOfWeek KEYWORD2
getDayOfWeekString KEYWORD2
getHour KEYWORD2
getMin KEYWORD2
getSecond KEYWORD2
getNumberOfDayThisYear KEYWORD2
getTotalDays KEYWORD2
dayofWeek KEYWORD2
getCurrentSecond KEYWORD2
getCurrentTimestamp KEYWORD2
getTimeFromSec KEYWORD2
getDateTimeString KEYWORD2
copyMessages KEYWORD2
moveMessages KEYWORD2
deleteMessages KEYWORD2
getQuota KEYWORD2
setQuota KEYWORD2
getQuotaRoot KEYWORD2
getACL KEYWORD2
setACL KEYWORD2
deleteACL KEYWORD2
myRights KEYWORD2
enable KEYWORD2
getNamespace KEYWORD2
createFolder KEYWORD2
renameFolder KEYWORD2
getSubscribesMailboxes KEYWORD2
subscribe KEYWORD2
unSubscribe KEYWORD2
deleteFolder KEYWORD2
listen KEYWORD2
stopListen KEYWORD2
folderChanged KEYWORD2
sendCustomCommand KEYWORD2
sendCustomData KEYWORD2
toBase64 KEYWORD2
getFlags KEYWORD2
getUID KEYWORD2
setTCPTimeout KEYWORD2
setClient KEYWORD2
setGSMClient KEYWORD2
connectionRequestCallback KEYWORD2
connectionUpgradeRequestCallback KEYWORD2
networkConnectionRequestCallback KEYWORD2
networkDisconnectionRequestCallback KEYWORD2
networkStatusRequestCallback KEYWORD2
setSystemTime KEYWORD2
mimeDataStreamCallback KEYWORD2
characterDecodingCallback KEYWORD2
clearAP KEYWORD2
addAP KEYWORD2
isFirmwareUpdated KEYWORD2
id KEYWORD2
serverID KEYWORD2
fileList KEYWORD2
status KEYWORD2
#######################################
# Struct (KEYWORD3)
#######################################
esp_mail_email_info_t KEYWORD3
esp_mail_plain_body_t KEYWORD3
esp_mail_html_body_t KEYWORD3
esp_mail_smtp_msg_response_t KEYWORD3
esp_mail_smtp_enable_option_t KEYWORD3
esp_mail_email_info_t KEYWORD3
esp_mail_folder_info_item_t KEYWORD3
esp_mail_sesson_sever_config_t KEYWORD3
esp_mail_sesson_login_config_t KEYWORD3
esp_mail_sesson_secure_config_t KEYWORD3
esp_mail_sesson_cert_config_t KEYWORD3
esp_mail_imap_fetch_config_t KEYWORD3
esp_mail_imap_search_config_t KEYWORD3
esp_mail_imap_limit_config_t KEYWORD3
esp_mail_imap_enable_config_t KEYWORD3
esp_mail_imap_download_config_t KEYWORD3
esp_mail_imap_storage_config_t KEYWORD3
esp_mail_imap_polling_status_t KEYWORD3
IMAP_Polling_Status KEYWORD3
IMAP_Identification KEYWORD3
esp_mail_file_storage_type_none KEYWORD3
esp_mail_file_storage_type_flash KEYWORD3
esp_mail_file_storage_type_sd KEYWORD3
######################################
# Constants (LITERAL1)
#######################################
ESP_MAIL_PRINTF LITERAL1

View File

@ -0,0 +1,16 @@
{
"name": "ESP Mail Client",
"version": "3.4.9",
"keywords": "communication, email, imap, smtp, esp32, esp8266, samd, arduino",
"description": "Arduino E-Mail Client Library to send, read and get incoming email notification for ESP32, ESP8266 and SAMD21 devices. The library also supported other Arduino Devices using Clients interfaces e.g. WiFiClient, EthernetClient, and GSMClient.",
"repository": {
"type": "git",
"url": "https://github.com/mobizt/ESP-Mail-Client.git"
},
"authors": [{
"name": "Mobizt",
"email": "suwatchai@outlook.com"
}],
"frameworks": "arduino",
"platforms": "espressif32, espressif8266, atmelsam, atmelavr, atmelmegaavr, ststm32, teensy, rp2040"
}

View File

@ -0,0 +1,17 @@
name=ESP Mail Client
version=3.4.9
author=Mobizt
maintainer=Mobizt <suwatchai@outlook.com>
sentence=Arduino E-Mail Client Library to send, read and get incoming email notification for ESP32, ESP8266 and SAMD21 devices.
paragraph=The library also supported other Arduino devices using Clients interfaces e.g. WiFiClient, EthernetClient, and GSMClient.
category=Communication
url=https://github.com/mobizt/ESP-Mail-Client
architectures=esp8266,esp32,sam,samd,stm32,STM32F1,STM32F4,teensy,avr,megaavr,mbed_nano,mbed_rp2040,rp2040

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
#pragma once
#ifndef ESP_MAIL_VERSION
#define ESP_MAIL_VERSION "3.4.9"
#define ESP_MAIL_VERSION_NUM 30409
/* The inconsistent file version checking to prevent mixed versions compilation. */
#define VALID_VERSION_CHECK(ver) (ver == ESP_MAIL_VERSION_NUM)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
/**
* Created August 6, 2023
*/
#pragma once
#ifndef ESP_MAIL_ERROR_H
#define ESP_MAIL_ERROR_H
#include "ESP_Mail_Client_Version.h"
#if !VALID_VERSION_CHECK(30409)
#error "Mixed versions compilation."
#endif
#define TCP_CLIENT_ERROR_CONNECTION_REFUSED -1
#define TCP_CLIENT_ERROR_SEND_DATA_FAILED -2
#define TCP_CLIENT_ERROR_NOT_INITIALIZED -3
#define TCP_CLIENT_ERROR_NOT_CONNECTED -4
#if defined(ENABLE_SMTP)
#define SMTP_STATUS_SERVER_CONNECT_FAILED -100
#define SMTP_STATUS_SMTP_GREETING_GET_RESPONSE_FAILED -101
#define SMTP_STATUS_SMTP_GREETING_SEND_ACK_FAILED -102
#define SMTP_STATUS_AUTHEN_NOT_SUPPORT -103
#define SMTP_STATUS_AUTHEN_FAILED -104
#define SMTP_STATUS_USER_LOGIN_FAILED -105
#define SMTP_STATUS_PASSWORD_LOGIN_FAILED -106
#define SMTP_STATUS_SEND_HEADER_SENDER_FAILED -107
#define SMTP_STATUS_SEND_HEADER_RECIPIENT_FAILED -108
#define SMTP_STATUS_SEND_BODY_FAILED -109
#define SMTP_STATUS_SERVER_OAUTH2_LOGIN_DISABLED -110
#define SMTP_STATUS_NO_VALID_RECIPIENTS_EXISTED -111
#define SMTP_STATUS_NO_VALID_SENDER_EXISTED -112
#define SMTP_STATUS_NO_SUPPORTED_AUTH -113
#define SMTP_STATUS_SEND_CUSTOM_COMMAND_FAILED -114
#define SMTP_STATUS_XOAUTH2_AUTH_FAILED -115
#define SMTP_STATUS_UNDEFINED -116
#endif
#if defined(ENABLE_IMAP)
#define IMAP_STATUS_SERVER_CONNECT_FAILED -200
#define IMAP_STATUS_IMAP_RESPONSE_FAILED -201
#define IMAP_STATUS_AUTHENTICATE_FAILED -202
#define IMAP_STATUS_BAD_COMMAND -203
#define IMAP_STATUS_STORE_FAILED -204
#define IMAP_STATUS_SERVER_OAUTH2_LOGIN_DISABLED -205
#define IMAP_STATUS_NO_MESSAGE -206
#define IMAP_STATUS_ERROR_DOWNLAD_TIMEOUT -207
#define IMAP_STATUS_CLOSE_MAILBOX_FAILED -208
#define IMAP_STATUS_OPEN_MAILBOX_FAILED -209
#define IMAP_STATUS_LIST_MAILBOXS_FAILED -210
#define IMAP_STATUS_CHECK_CAPABILITIES_FAILED -211
#define IMAP_STATUS_NO_SUPPORTED_AUTH -212
#define IMAP_STATUS_NO_MAILBOX_FOLDER_OPENED -213
#define IMAP_STATUS_FIRMWARE_UPDATE_INIT_FAILED -214
#define IMAP_STATUS_FIRMWARE_UPDATE_WRITE_FAILED -215
#define IMAP_STATUS_FIRMWARE_UPDATE_END_FAILED -216
#define IMAP_STATUS_CHANGEDSINC_MODSEQ_TEST_FAILED -217
#define IMAP_STATUS_MODSEQ_WAS_NOT_SUPPORTED -218
#endif
/**
* MB_FS.h
#define MB_FS_ERROR_FILE_IO_ERROR -300
#define MB_FS_ERROR_FILE_NOT_FOUND -301
#define MB_FS_ERROR_FLASH_STORAGE_IS_NOT_READY -302
#define MB_FS_ERROR_SD_STORAGE_IS_NOT_READY -303
#define MB_FS_ERROR_FILE_STILL_OPENED -304
*/
#if defined(ENABLE_SMTP) || defined(ENABLE_IMAP)
#define MAIL_CLIENT_ERROR_CONNECTION_CLOSED -400
#define MAIL_CLIENT_ERROR_READ_TIMEOUT -401
#define MAIL_CLIENT_ERROR_SSL_TLS_STRUCTURE_SETUP -402
#define MAIL_CLIENT_ERROR_OUT_OF_MEMORY -403
#define MAIL_CLIENT_ERROR_NTP_TIME_SYNC_TIMED_OUT -404
#define MAIL_CLIENT_ERROR_SESSION_CONFIG_WAS_NOT_ASSIGNED -405
#define MAIL_CLIENT_ERROR_TIME_WAS_NOT_SET -406
#define MAIL_CLIENT_ERROR_NOT_YET_LOGIN -407
#define MAIL_CLIENT_ERROR_BUFFER_OVERFLOW -408
#endif
#endif

View File

@ -0,0 +1,170 @@
#pragma once
#ifndef ESP_MAIL_CONFIG_H
#define ESP_MAIL_CONFIG_H
#include "ESP_Mail_Client_Version.h"
#if !VALID_VERSION_CHECK(30409)
#error "Mixed versions compilation."
#endif
#include <Arduino.h>
#include "extras/MB_MCU.h"
/** 📌 Predefined Build Options
* Use following build flag to disable all predefined options.
* -D DISABLE_ALL_OPTIONS
*/
/**📍 For enabling the device or library time setup from NTP server
* Use following build flag to disable.
* -D DISABLE_NTP_TIME
*/
#define ENABLE_NTP_TIME
/**📍 For enabling the error string from error reason
* Use following build flag to disable.
* -D DISABLE_ERROR_STRING
*/
#define ENABLE_ERROR_STRING
/**📍 For IMAP class compilation
* Use following build flag to disable.
* -D DISABLE_IMAP
*/
#define ENABLE_IMAP
/**📍 For SMTP class compilation
* Use following build flag to disable.
* -D DISABLE_SMTP
*/
#define ENABLE_SMTP
/**📍 For enabling PSRAM support
* Use following build flag to disable.
* -D DISABLE_PSRAM
*/
#define ESP_MAIL_USE_PSRAM
/**📌 For enabling flash filesystem support
*
* 📍 For SPIFFS
* #define ESP_MAIL_DEFAULT_FLASH_FS SPIFFS
*
*
* 📍 For LittleFS Filesystem
* #include <LittleFS.h>
* #define ESP_MAIL_DEFAULT_FLASH_FS LittleFS
*
*
* 📍 For SPIFFS Filesystem
* #if defined(ESP32)
* #include <SPIFFS.h>
* #endif
* #define ESP_MAIL_DEFAULT_FLASH_FS SPIFFS
*
*
* 📍 For FAT Filesystem
* #include <FFat.h>
* #define ESP_MAIL_DEFAULT_FLASH_FS FFat //For ESP32 FAT
*
* 🚫 Use following build flags to disable.
* -D DISABLE_FLASH or -DDISABLE_FLASH in PlatformIO
*/
#if defined(ESP32) || defined(ESP8266) || defined(MB_ARDUINO_PICO)
#if defined(ESP8266) || defined(MB_ARDUINO_PICO)
#include <LittleFS.h>
#define ESP_MAIL_DEFAULT_FLASH_FS LittleFS
#elif defined(ESP_ARDUINO_VERSION) /* ESP32 core >= v2.0.x */ /* ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) */
#include <LittleFS.h>
#define ESP_MAIL_DEFAULT_FLASH_FS LittleFS
#else
#include <SPIFFS.h>
#define ESP_MAIL_DEFAULT_FLASH_FS SPIFFS
#endif
#endif
// For ESP32, format SPIFFS or FFat if mounting failed
#define ESP_MAIL_FORMAT_FLASH_IF_MOUNT_FAILED 1
/**📌 For enabling SD filesystem support
*
* 📍 For SD
* #include <SD.h>
* #define ESP_MAIL_DEFAULT_SD_FS SD
* #define ESP_MAIL_CARD_TYPE_SD 1
*
* 📍 For SD MMC (ESP32)
* #include <SD_MMC.h>
* #define ESP_MAIL_DEFAULT_SD_FS SD_MMC //For ESP32 SDMMC
* #define ESP_MAIL_CARD_TYPE_SD_MMC 1
*
* 📍 For SdFat on ESP32 and other devices except for ESP8266
* #include <SdFat.h> //https://github.com/greiman/SdFat
* static SdFat sd_fat_fs; //should declare as static here
* #define ESP_MAIL_DEFAULT_SD_FS sd_fat_fs
* #define ESP_MAIL_CARD_TYPE_SD 1
* #define ESP_MAIL_SD_FS_FILE SdFile
*
*
* Use following build flags to disable.
* -D DISABLE_SD or -DDISABLE_SD in PlatformIO
*/
#if defined(ESP32) || defined(ESP8266)
#include <SD.h>
#define ESP_MAIL_DEFAULT_SD_FS SD
#define ESP_MAIL_CARD_TYPE_SD 1
#elif defined(MB_ARDUINO_PICO)
// Use SDFS (ESP8266SdFat) instead of SD
#include <SDFS.h>
#define ESP_MAIL_DEFAULT_SD_FS SDFS
#define ESP_MAIL_CARD_TYPE_SD 1
#endif
/** 🔖 Optional Build Options
*
* 🏷 For silent operation (no debug printing and callback)
* #define SILENT_MODE
*
* 🏷 For ENC28J60 Ethernet module support in ESP8266
* #define ENABLE_ESP8266_ENC28J60_ETH
*
* 🏷 For W5500 Ethernet module support in ESP8266
* #define ENABLE_ESP8266_W5500_ETH
*
* 🏷 For W5100 Ethernet module support in ESP8266
* #define ENABLE_ESP8266_W5100_ETH
*
* 🏷 For disabling on-board WiFI functionality in case external Client usage
* #define ESP_MAIL_DISABLE_ONBOARD_WIFI
*
* 🏷 For disabling native (sdk) Ethernet functionality in case external Client usage
* #define ESP_MAIL_DISABLE_NATIVE_ETHERNET
*
* 🏷 For disabling SSL connection (also disabling TLS using STARTTLS) in MAP and SMTP application
* #define ESP_MAIL_DISABLE_SSL
*
* 🏷 For debug port assignment if SILENT_MODE option was not set
* #define ESP_MAIL_DEBUG_PORT Serial
*/
#define ENABLE_ESP8266_ENC28J60_ETH
#if __has_include("Custom_ESP_Mail_FS.h")
#include "Custom_ESP_Mail_FS.h"
#endif
#include "extras/Build_Options.h"
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
/** Memory usage info for debugging purpose
#include "HeapStat.h"
HeapStat heapInfo;
void setup()
{
Serial.begin(115200);
}
void loop()
{
// Other codes here
// Collect memory info
heapInfo.collect();
// Print memory info
heapInfo.print();
}
*/
#ifndef HEAP_STAT_H
#define HEAP_STAT_H
#if defined(ESP8266) || defined(ESP32)
#ifndef MB_ARDUINO_ESP
#define MB_ARDUINO_ESP
#endif
#endif
#if defined(ARDUINO_ARCH_RP2040)
#if defined(ARDUINO_NANO_RP2040_CONNECT)
#ifndef MB_ARDUINO_NANO_RP2040_CONNECT
#define MB_ARDUINO_NANO_RP2040_CONNECT
#endif
#else
#ifndef MB_ARDUINO_PICO
#define MB_ARDUINO_PICO
#endif
#endif
#endif
#include "ESP_Mail_Client.h"
class HeapStat
{
private:
int current_heap = 0;
int first_round_heap = 0;
int min_heap = 0;
int max_heap = 0;
int diff_heap_from_first_round = 0;
int diff_heap_from_current_round = 0;
int _count = 0;
int getFreeHeap()
{
#if defined(MB_ARDUINO_ESP)
return ESP.getFreeHeap();
#elif defined(MB_ARDUINO_PICO)
return rp2040.getFreeHeap();
#else
return 0;
#endif
}
public:
HeapStat() {}
~HeapStat() {}
void reset()
{
current_heap = 0;
first_round_heap = 0;
min_heap = 0;
max_heap = 0;
diff_heap_from_first_round = 0;
diff_heap_from_current_round = 0;
_count = 0;
}
void collect()
{
_count++;
if (max_heap < getFreeHeap())
max_heap = getFreeHeap();
if (min_heap == 0 || min_heap > getFreeHeap())
min_heap = getFreeHeap();
if (first_round_heap == 0)
first_round_heap = getFreeHeap();
if (current_heap > 0)
{
diff_heap_from_first_round = getFreeHeap() - first_round_heap;
diff_heap_from_current_round = getFreeHeap() - current_heap;
}
current_heap = getFreeHeap();
}
int current()
{
return current_heap;
}
int min()
{
return min_heap;
}
int max()
{
return max_heap;
}
int diff1()
{
return diff_heap_from_first_round;
}
int diffN()
{
return diff_heap_from_current_round;
}
int count()
{
return _count;
}
void print()
{
MailClient.printf("#### Heap Info\n#### Current: %d, Min: %d, Max: %d, Diff_1: %d, Diff_%d: %d\n", current(), min(), max(), diff1(), count(), diffN());
}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
#ifndef CUSTOM_ESP_SSLCLIENT_FS_H
#define CUSTOM_ESP_SSLCLIENT_FS_H
#include "../ESP_Mail_FS.h"
#if defined(ESP_MAIL_DISABLE_SSL)
#undef USE_LIB_SSL_ENGINE
#undef USE_EMBED_SSL_ENGINE
#endif
#if defined(ESP_MAIL_USE_PSRAM)
#if !defined(ESP_SSLCLIENT_USE_PSRAM)
#define ESP_SSLCLIENT_USE_PSRAM
#endif
#else
#undef ESP_SSLCLIENT_USE_PSRAM
#endif
#undef ESP_SSLCLIENT_ENABLE_DEBUG
#undef ESP_SSLCLIENT_ENABLE_SSL_ERROR_STRING
#endif

View File

@ -0,0 +1,79 @@
/**
*
* The ESP SSL Client Class, ESP_SSLClient.h v2.1.6
*
* Created August 27, 2023
*
* The MIT License (MIT)
* Copyright (c) 2023 K. Suwatchai (Mobizt)
*
*
* Permission is hereby granted, free of charge, to any person returning a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ESP_SSLCLIENT_H
#define ESP_SSLCLIENT_H
#include "ESP_SSLClient_FS.h"
#ifndef SSLCLIENT_CONNECTION_UPGRADABLE
#define SSLCLIENT_CONNECTION_UPGRADABLE
#endif
#include "ESP_SSLClient_Const.h"
#if defined(USE_EMBED_SSL_ENGINE) || defined(USE_LIB_SSL_ENGINE)
#include "client/BSSL_TCP_Client.h"
class ESP_SSLClient : public BSSL_TCP_Client
{
public:
ESP_SSLClient(){};
~ESP_SSLClient(){};
};
class ESP_SSLClient2 : public BSSL_TCP_Client
{
public:
ESP_SSLClient2(Client &client, bool enableSSL = true) : _base_client(client)
{
setClient(&_base_client, enableSSL);
};
~ESP_SSLClient2(){};
private:
Client &_base_client;
};
#else
class ESP_SSLClient
{
public:
ESP_SSLClient(){};
~ESP_SSLClient(){};
};
class ESP_SSLClient2
{
public:
ESP_SSLClient2(Client &client, bool enableSSL = true) : _base_client(client){};
~ESP_SSLClient2(){};
private:
Client &_base_client;
};
#endif
#endif

View File

@ -0,0 +1,138 @@
#ifndef ESP_SSLCLIENT_CONST_H
#define ESP_SSLCLIENT_CONST_H
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wvla"
#include "ESP_SSLClient_FS.h"
#include <Arduino.h>
#include <Client.h>
#if defined(__AVR__)
#undef USE_LIB_SSL_ENGINE
#undef USE_EMBED_SSL_ENGINE
#error "Not support AVR architecture"
#endif
#define ESP_SSLCLIENT_VALID_TIMESTAMP 1690979919
#ifndef SSLCLIENT_CONNECTION_UPGRADABLE
#define SSLCLIENT_CONNECTION_UPGRADABLE
#endif
#ifdef ESP_SSLCLIENT_ENABLE_DEBUG
#if !defined(ESP_SSLCLIENT_DEBUG_PORT)
#define ESP_SSLCLIENT_DEBUG_PORT Serial
#endif
#define ESP_SSLCLIENT_DEBUG_PRINT ESP_SSLCLIENT_DEBUG_PORT.print
#else
#define ESP_SSLCLIENT_DEBUG_PRINT(...)
#endif
#if !defined(FPSTR)
#define FPSTR
#endif
#if defined(USE_EMBED_SSL_ENGINE) || defined(USE_LIB_SSL_ENGINE)
enum esp_ssl_client_debug_level
{
esp_ssl_debug_none = 0,
esp_ssl_debug_error = 1,
esp_ssl_debug_warn = 2,
esp_ssl_debug_info = 3,
esp_ssl_debug_dump = 4
};
enum esp_ssl_client_error_types
{
esp_ssl_ok,
esp_ssl_connection_fail,
esp_ssl_write_error,
esp_ssl_read_error,
esp_ssl_out_of_memory,
esp_ssl_internal_error
};
#if defined(ESP_SSLCLIENT_ENABLE_DEBUG)
static void esp_ssl_debug_print_prefix(const char *func_name, int level)
{
ESP_SSLCLIENT_DEBUG_PRINT(PSTR("> "));
// print the debug level
switch (level)
{
case esp_ssl_debug_info:
ESP_SSLCLIENT_DEBUG_PRINT(PSTR("INFO."));
break;
case esp_ssl_debug_warn:
ESP_SSLCLIENT_DEBUG_PRINT(PSTR("WARN."));
break;
case esp_ssl_debug_error:
ESP_SSLCLIENT_DEBUG_PRINT(PSTR("ERROR."));
break;
default:
break;
}
// print the function name
ESP_SSLCLIENT_DEBUG_PRINT(PSTR(""));
ESP_SSLCLIENT_DEBUG_PRINT(func_name);
ESP_SSLCLIENT_DEBUG_PRINT(PSTR(": "));
}
static void esp_ssl_debug_print(PGM_P msg, int debug_level, int level, const char *func_name)
{
if (debug_level >= level)
{
esp_ssl_debug_print_prefix(func_name, level);
ESP_SSLCLIENT_DEBUG_PRINT(msg);
ESP_SSLCLIENT_DEBUG_PRINT("\r\n");
}
}
#endif
static uint8_t htoi(unsigned char c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'F')
return 10 + c - 'A';
else if (c >= 'a' && c <= 'f')
return 10 + c - 'a';
else
return 255;
}
// Helper function which aborts a TLS handshake by sending TLS
// ClientAbort and ClientClose messages.
static bool send_abort(Client *probe, bool supportsLen)
{
// If we're still connected, send the appropriate notice that
// we're aborting the handshake per RFCs.
static const uint8_t clientAbort_P[] PROGMEM = {
0x15 /*alert*/, 0x03, 0x03 /*TLS 1.2*/, 0x00, 0x02,
1, 90 /* warning: user_cancelled */
};
static const uint8_t clientClose_P[] PROGMEM = {
0x15 /*alert*/, 0x03, 0x03 /*TLS 1.2*/, 0x00, 0x02,
1, 0 /* warning: close_notify */
};
if (probe->connected())
{
uint8_t msg[sizeof(clientAbort_P)];
memcpy_P(msg, clientAbort_P, sizeof(clientAbort_P));
probe->write(msg, sizeof(clientAbort_P));
memcpy_P(msg, clientClose_P, sizeof(clientClose_P));
probe->write(msg, sizeof(clientClose_P));
}
return supportsLen;
}
const uint16_t _secure_ports[26] = {443 /* HTTPS */, 465 /* SMTP */, 563 /* NNTP */, 636 /* LDAPS */, 695 /* IEEE-MMS-SSL */, 832 /* NETCONF */, 853 /* DNS */, 989 /* FTPS */, 990 /* FTPS */, 992 /* Telnet */, 993 /* IMAP */, 995 /* POP3 */, 4116 /* Smartcard */, 4843 /* OPC */, 5061 /* SIP */, 5085 /* LLIP */, 5349 /* NAT */, 5671 /* AMQP */, 5986 /* WinRM-HTTPS */, 6513 /* NETCONF */, 6514 /* Syslog */, 6515 /* Elipse RPC */, 6619 /* OFTP */, 8243 /* Apache Synapse */, 8403 /* GxFWD */, 8883 /* MQTT */};
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More