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
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
1127
lib/libesp32/ESP-Mail-Client/README.md
Normal file
258
lib/libesp32/ESP-Mail-Client/examples/IMAP/ACL/ACL.ino
Normal 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()
|
||||
{
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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.
|
||||
*/
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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(ð_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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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", "a_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()
|
||||
{
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
@ -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" : "");
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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()
|
||||
{
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 318 KiB After Width: | Height: | Size: 318 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
@ -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 = ð
|
||||
#elif defined(ENABLE_ESP8266_W5100_ETH)
|
||||
config.spi_ethernet_module.w5100 = ð
|
||||
#elif defined(ENABLE_ESP8266_W5500_ETH)
|
||||
config.spi_ethernet_module.w5500 = ð
|
||||
#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();
|
||||
}
|
||||
}
|
||||
@ -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(ð_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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
253
lib/libesp32/ESP-Mail-Client/examples/SMTP/Set_Time/Set_Time.ino
Normal 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();
|
||||
}
|
||||
}
|
||||
310
lib/libesp32/ESP-Mail-Client/examples/SMTP/Sleep/Sleep.ino
Normal 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();
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
16
lib/libesp32/ESP-Mail-Client/library.json
Normal 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"
|
||||
}
|
||||
17
lib/libesp32/ESP-Mail-Client/library.properties
Normal 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
|
||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
BIN
lib/libesp32/ESP-Mail-Client/media/images/ESP32-PSRAM.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
lib/libesp32/ESP-Mail-Client/media/images/ESP8266_VM.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
BIN
lib/libesp32/ESP-Mail-Client/media/images/esptool.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
1933
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_Client.cpp
Normal file
2862
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_Client.h
Normal file
12
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_Client_Version.h
Normal 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
|
||||
3492
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_Const.h
Normal file
86
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_Error.h
Normal 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
|
||||
170
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_FS.h
Normal 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
|
||||
6783
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_IMAP.h
Normal file
3631
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_SMTP.h
Normal file
1093
lib/libesp32/ESP-Mail-Client/src/ESP_Mail_TCPClient.h
Normal file
146
lib/libesp32/ESP-Mail-Client/src/HeapStat.h
Normal 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
|
||||
3416
lib/libesp32/ESP-Mail-Client/src/README.md
Normal 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
|
||||
79
lib/libesp32/ESP-Mail-Client/src/SSLClient/ESP_SSLClient.h
Normal 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
|
||||
138
lib/libesp32/ESP-Mail-Client/src/SSLClient/ESP_SSLClient_Const.h
Normal 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
|
||||