diff --git a/lib/lib_div/lib_mail/README.md b/lib/lib_div/lib_mail/README.md index 87ba8e72d..6025aec0e 100755 --- a/lib/lib_div/lib_mail/README.md +++ b/lib/lib_div/lib_mail/README.md @@ -1,4 +1,4 @@ -# Mail Client Arduino Library for ESP32 and ESP8266 v 1.0.13 +# Mail Client Arduino Library for ESP32 and ESP8266 v 1.2.0 [![Join the chat at https://gitter.im/mobizt/ESP_Mail_Client](https://badges.gitter.im/mobizt/ESP_Mail_Client.svg)](https://gitter.im/mobizt/ESP_Mail_Client?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -10,7 +10,7 @@ The library was tested and work well with ESP32s and ESP8266s based modules. This library was developed to replace the deprecated ESP32 Mail Client library with more options and features, better reliability and also conforms to the RFC standards. -![ESP32 Mail](/media/images/esp-mail-client.svg) +![ESP Mail](/media/images/esp-mail-client.svg) Copyright (c) 2021 K. Suwatchai (Mobizt). @@ -19,14 +19,14 @@ Copyright (c) 2021 K. Suwatchai (Mobizt). * Support Espressif ESP32 and ESP8266 MCUs based devices. * Support TCP session reusage. * Support PLAIN, LOGIN and XOAUTH2 authentication mechanisms. -* Secured connection with SSL and TLS. +* Support secured (with SSL and TLS) and non-secure ports. * Support mailbox selection for Email reading and searching. * Support the content encodings e.g. quoted-printable and base64. * Support the content decodings e.g. base64, UTF-8, UTF-7, quoted-printable, ISO-8859-1 (latin1) and ISO-8859-11 (Thai). * Support many types of embedded contents e.g. inline images, attachments, parallel media attachments and RFC822 message. * Support full debuging. -* Support SPIFFS and SD card for file storages. -* Support Ethernet (ESP32). +* Support flash memory and SD card for file storages which can be changed in [**ESP_Mail_FS.h**](/src/ESP_Mail_FS.h). +* Support Ethernet (ESP32 using LAN8720, TLK110 and IP101 Ethernet boards). ESP8266 Ethernet is not yet supported. * Customizable operating configurations (see the examples for the usages) ## Tested Devices @@ -65,6 +65,108 @@ Go to menu **Files** -> **Examples** -> **ESP-Mail-Client-master** and choose on + + + +## IDE Configuaration for ESP8266 MMU - Adjust the Ratio of ICACHE to IRAM + +### Arduino IDE + +When you update the ESP8266 Arduino Core SDK to v3.0.0, the memory can be configurable from Arduino IDE board settings. + +By default MMU **option 1** was selected, the free Heap can be low and may not suitable for the SSL client usage in this library. + +To increase the Heap, choose the MMU **option 3**, 16KB cache + 48KB IRAM and 2nd Heap (shared). + +![Arduino IDE config](/media/images/ArduinoIDE.png) + + +More about MMU settings. +https://arduino-esp8266.readthedocs.io/en/latest/mmu.html + +### PlatformIO IDE + +When Core SDK v3.0.0 becomes available in PlatformIO, + +By default the balanced ratio (32KB cache + 32KB IRAM) configuration is used. + +To increase the heap, **PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED** build flag should be assigned in platformio.ini. + +At the time of writing, to update SDK to v3.0.0 you can follow these steps. + +1. In platformio.ini, edit the config as the following + +```ini +[env:d1_mini] +platform = https://github.com/platformio/platform-espressif8266.git +build_flags = -D PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED +board = d1_mini +framework = arduino +monitor_speed = 115200 +``` + +2. Delete this folder **C:\Users\UserName\\.platformio\platforms\espressif8266@src-?????????????** +3. Delete .pio and .vscode folders in your project. +4. Clean and Compile the project. + + + +The supportedd MMU build flags in PlatformIO. + +- **PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48** + + 16KB cache + 48KB IRAM (IRAM) + +- **PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED** + + 16KB cache + 48KB IRAM and 2nd Heap (shared) + +- **PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM32_SECHEAP_NOTSHARED** + + 16KB cache + 32KB IRAM + 16KB 2nd Heap (not shared) + +- **PIO_FRAMEWORK_ARDUINO_MMU_EXTERNAL_128K** + + 128K External 23LC1024 + +- **PIO_FRAMEWORK_ARDUINO_MMU_EXTERNAL_1024K** + + 1M External 64 MBit PSRAM + +- **PIO_FRAMEWORK_ARDUINO_MMU_CUSTOM** + + Disables default configuration and expects user-specified flags + + +### Test code for MMU + +```cpp + +#include +#include + +void setup() +{ + Serial.begin(74880); + HeapSelectIram ephemeral; + Serial.printf("IRAM free: %6d bytes\r\n", ESP.getFreeHeap()); + { + HeapSelectDram ephemeral; + Serial.printf("DRAM free: %6d bytes\r\n", ESP.getFreeHeap()); + } +} + +void loop() { + // put your main code here, to run repeatedly: +} + +``` + + + + + + ## Usage @@ -77,6 +179,31 @@ The following examples showed the minimum usage which many options are not confi The examples in the examples folder provide the full options usages. +## Notes + +The string in the function's parameters or properties of structured data is the pointer to constant char or char array. + +You need to assign the string literal or char array or pointer to constant char to it. + +#### Ex. + +```cpp +message.sender.name = "My Mail"; +message.sender.email = "sender or your Email address"; +``` + +Or using String class + +```cpp +String name = "John"; +String email = "john@mail.com"; + +message.sender.name = name.c_str(); +message.sender.email = email.c_str(); +``` + + + ### Send the Email diff --git a/lib/lib_div/lib_mail/examples/Copy_Messages/Copy_Messsages.ino b/lib/lib_div/lib_mail/examples/Copy_Messages/Copy_Messsages.ino index 769443230..81022a136 100755 --- a/lib/lib_div/lib_mail/examples/Copy_Messages/Copy_Messsages.ino +++ b/lib/lib_div/lib_mail/examples/Copy_Messages/Copy_Messsages.ino @@ -5,7 +5,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -128,3 +128,20 @@ 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); + Serial.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : ""); + } + } +} diff --git a/lib/lib_div/lib_mail/examples/Delete_Messages/Delete_Messsages.ino b/lib/lib_div/lib_mail/examples/Delete_Messages/Delete_Messsages.ino index ae65b188d..93a629a43 100755 --- a/lib/lib_div/lib_mail/examples/Delete_Messages/Delete_Messsages.ino +++ b/lib/lib_div/lib_mail/examples/Delete_Messages/Delete_Messsages.ino @@ -5,7 +5,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -123,3 +123,20 @@ 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); + Serial.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : ""); + } + } +} diff --git a/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/ESP32_Ethernet_Send_Text.ino b/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/ESP32_Ethernet_Send_Text.ino new file mode 100644 index 000000000..3dc3192de --- /dev/null +++ b/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/ESP32_Ethernet_Send_Text.ino @@ -0,0 +1,307 @@ + + +/** + * This example will send the Email in plain text version using ESP32 and LAN8720 Ethernet module. + * + * Created by K. Suwatchai (Mobizt) + * + * Email: suwatchai@outlook.com + * + * Github: https://github.com/mobizt/ESP-Mail-Client + * + * Copyright (c) 2021 mobizt + * +*/ + +/** + * 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 + * +*/ + +//In case of 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 +#include + +#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; + + +/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com + * 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 + * and use the app password as password with your yahoo mail account to login. + * The google app password signin is also available https://support.google.com/mail/answer/185833?hl=en +*/ +#define SMTP_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 sign in credentials */ +#define AUTHOR_EMAIL "################" +#define AUTHOR_PASSWORD "################" + +/* The SMTP Session object used for Email sending */ +SMTPSession smtp; + +/* Callback function to get the Email sending status */ +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 + 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; + } +} + +void sendMail() +{ + + /** Enable the debug via Serial port + * none debug or 0 + * basic debug or 1 + */ + smtp.debug(1); + + /* Set the callback function to get the sending results */ + smtp.callback(smtpCallback); + + /* Declare the session config data */ + ESP_Mail_Session session; + + /** ######################################################## + * Some properties of SMTPSession data and parameters pass to + * SMTP_Message class accept the pointer to constant char + * i.e. const char*. + * + * You may assign a string literal to that properties or function + * like below example. + * + * session.login.user_domain = "mydomain.net"; + * session.login.user_domain = String("mydomain.net").c_str(); + * + * or + * + * String doman = "mydomain.net"; + * session.login.user_domain = domain.c_str(); + * + * And + * + * String name = "Jack " + String("dawson"); + * String email = "jack_dawson" + String(123) + "@mail.com"; + * + * message.addRecipient(name.c_str(), email.c_str()); + * + * message.addHeader(String("Message-ID: ").c_str()); + * + * or + * + * String header = "Message-ID: "; + * message.addHeader(header.c_str()); + * + * ########################################################### + */ + + /* Set the session config */ + session.server.host_name = SMTP_HOST; + session.server.port = SMTP_PORT; + session.login.email = AUTHOR_EMAIL; + session.login.password = AUTHOR_PASSWORD; + session.login.user_domain = "mydomain.net"; + + /* Declare the message class */ + SMTP_Message message; + + /* Set the message headers */ + message.sender.name = "ESP Mail"; + message.sender.email = AUTHOR_EMAIL; + message.subject = "Test sending plain text Email"; + message.addRecipient("Someone", "####@#####_dot_com"); + + String textMsg = "This is simple plain text message"; + message.text.content = textMsg.c_str(); + + /** The Plain text message character set e.g. + * us-ascii + * utf-8 + * utf-7 + * The default value is utf-8 + */ + message.text.charSet = "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("Message-ID: "); + + /* Connect to server with the session config */ + if (!smtp.connect(&session)) + return; + + /* Start sending Email and close the session */ + if (!MailClient.sendMail(&smtp, &message)) + Serial.println("Error sending Email, " + smtp.errorReason()); +} + +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(); + } +} + +/* 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()) + { + Serial.println("----------------"); + Serial.printf("Message sent success: %d\n", status.completedCount()); + Serial.printf("Message sent failled: %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); + localtime_r(&result.timesstamp, &dt); + + Serial.printf("Message No: %d\n", i + 1); + Serial.printf("Status: %s\n", result.completed ? "success" : "failed"); + Serial.printf("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec); + Serial.printf("Recipient: %s\n", result.recipients); + Serial.printf("Subject: %s\n", result.subject); + } + Serial.println("----------------\n"); + } +} diff --git a/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/modified_LAN8720_board_images/lan8720_modified_board.png b/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/modified_LAN8720_board_images/lan8720_modified_board.png new file mode 100644 index 000000000..44d0d7907 Binary files /dev/null and b/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/modified_LAN8720_board_images/lan8720_modified_board.png differ diff --git a/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/modified_LAN8720_board_images/lan8720_modified_schematic.png b/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/modified_LAN8720_board_images/lan8720_modified_schematic.png new file mode 100644 index 000000000..9dc3d1176 Binary files /dev/null and b/lib/lib_div/lib_mail/examples/ESP32_Ethernet_Send_Text/modified_LAN8720_board_images/lan8720_modified_schematic.png differ diff --git a/lib/lib_div/lib_mail/examples/Read_Email_Access_Token/Read_Email_Access_Token.ino b/lib/lib_div/lib_mail/examples/Read_Email_Access_Token/Read_Email_Access_Token.ino index ae9d7cc39..6e9bd1465 100755 --- a/lib/lib_div/lib_mail/examples/Read_Email_Access_Token/Read_Email_Access_Token.ino +++ b/lib/lib_div/lib_mail/examples/Read_Email_Access_Token/Read_Email_Access_Token.ino @@ -7,7 +7,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/examples/Read_Single_Email/Read_Single_Email.ino b/lib/lib_div/lib_mail/examples/Read_Single_Email/Read_Single_Email.ino index c03babfe8..20d039097 100755 --- a/lib/lib_div/lib_mail/examples/Read_Single_Email/Read_Single_Email.ino +++ b/lib/lib_div/lib_mail/examples/Read_Single_Email/Read_Single_Email.ino @@ -6,7 +6,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -110,6 +110,21 @@ void setup() /* Declare the session config data */ ESP_Mail_Session session; + /** ######################################################## + * Some properties of IMAP_Config and ESP_Mail_Session data + * accept the pointer to constant char i.e. const char*. + * + * You may assign a string literal to that properties like + * below example. + * + * config.storage.saved_path = String("/email_data").c_str(); + * + * String folder = "INBOX"; + * imap.selectFolder(folder.c_str()); + * + * ########################################################### + */ + /* Set the session config */ session.server.host_name = IMAP_HOST; session.server.port = IMAP_PORT; diff --git a/lib/lib_div/lib_mail/examples/Read_Single_Email_Loop/Read_Single_Email_Loop.ino b/lib/lib_div/lib_mail/examples/Read_Single_Email_Loop/Read_Single_Email_Loop.ino index c3452e7bc..af374fdbe 100755 --- a/lib/lib_div/lib_mail/examples/Read_Single_Email_Loop/Read_Single_Email_Loop.ino +++ b/lib/lib_div/lib_mail/examples/Read_Single_Email_Loop/Read_Single_Email_Loop.ino @@ -8,7 +8,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/examples/Search_Emails/Search_Emails.ino b/lib/lib_div/lib_mail/examples/Search_Emails/Search_Emails.ino index 5840441bd..f644ffe94 100755 --- a/lib/lib_div/lib_mail/examples/Search_Emails/Search_Emails.ino +++ b/lib/lib_div/lib_mail/examples/Search_Emails/Search_Emails.ino @@ -7,7 +7,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -111,6 +111,21 @@ void setup() * Which pin 15 is the CS pin of SD card adapter */ + /** ######################################################## + * Some properties of IMAP_Config and ESP_Mail_Session data + * accept the pointer to constant char i.e. const char*. + * + * You may assign a string literal to that properties like + * below example. + * + * config.search.criteria = String("UID SEARCH ALL").c_str(); + * + * String folder = "INBOX"; + * imap.selectFolder(folder.c_str()); + * + * ########################################################### + */ + /* Set the session config */ session.server.host_name = IMAP_HOST; session.server.port = IMAP_PORT; @@ -227,7 +242,7 @@ void setup() printSelectedMailboxInfo(imap); /* Config to search all messages in the opened mailboax (Search mode) */ - config.search.criteria = "UID SEARCH ALL"; + config.search.criteria = "UID SEARCH ALL"; // or "UID SEARCH NEW" for recent received messages /* No message UID provide for fetching */ config.fetch.uid = ""; diff --git a/lib/lib_div/lib_mail/examples/Send_Access_Token/Send_Access_Token.ino b/lib/lib_div/lib_mail/examples/Send_Access_Token/Send_Access_Token.ino index 5a2cbe41b..4fdc48102 100755 --- a/lib/lib_div/lib_mail/examples/Send_Access_Token/Send_Access_Token.ino +++ b/lib/lib_div/lib_mail/examples/Send_Access_Token/Send_Access_Token.ino @@ -9,7 +9,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -46,6 +46,9 @@ * To test this using GMail, get the OAuth2.0 access token from this web site * https://developers.google.com/oauthplayground/ * + * You can use the ESP Signer library to generate OAuth2.0 access token + * The library is available here https://github.com/mobizt/ESP-Signer + * * 1. Select the following scope (in Step 1) from Gmail API V1 * https://mail.google.com/ * https://mail.google.com/ diff --git a/lib/lib_div/lib_mail/examples/Send_Attachment_Blob/Send_Attachment_Blob.ino b/lib/lib_div/lib_mail/examples/Send_Attachment_Blob/Send_Attachment_Blob.ino index 139c8c42c..f6a3c7467 100755 --- a/lib/lib_div/lib_mail/examples/Send_Attachment_Blob/Send_Attachment_Blob.ino +++ b/lib/lib_div/lib_mail/examples/Send_Attachment_Blob/Send_Attachment_Blob.ino @@ -12,7 +12,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/examples/Send_Attachment_File/Send_Attachment_File.ino b/lib/lib_div/lib_mail/examples/Send_Attachment_File/Send_Attachment_File.ino index 1977ca6e0..8130262fa 100755 --- a/lib/lib_div/lib_mail/examples/Send_Attachment_File/Send_Attachment_File.ino +++ b/lib/lib_div/lib_mail/examples/Send_Attachment_File/Send_Attachment_File.ino @@ -12,12 +12,14 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ //To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1 +//The file systems for flash and sd memory can be changed in ESP_Mail_FS.h. + #include #if defined(ESP32) #include @@ -212,6 +214,39 @@ void setup() /* Declare the session config data */ ESP_Mail_Session session; + /** ######################################################## + * Some properties of SMTPSession data and parameters pass to + * SMTP_Message class accept the pointer to constant char + * i.e. const char*. + * + * You may assign a string literal to that properties or function + * like below example. + * + * session.login.user_domain = "mydomain.net"; + * session.login.user_domain = String("mydomain.net").c_str(); + * + * or + * + * String doman = "mydomain.net"; + * session.login.user_domain = domain.c_str(); + * + * And + * + * String name = "Jack " + String("dawson"); + * String email = "jack_dawson" + String(123) + "@mail.com"; + * + * message.addRecipient(name.c_str(), email.c_str()); + * + * message.addHeader(String("Message-ID: ").c_str()); + * + * or + * + * String header = "Message-ID: "; + * message.addHeader(header.c_str()); + * + * ########################################################### + */ + /* Set the session config */ session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; @@ -233,7 +268,8 @@ void setup() message.addRecipient("user1", "####@#####_dot_com"); /** Two alternative content versions are sending in this example e.g. plain text and html */ - message.html.content = "This message contains 2 inline images and 2 attachment files.

"; + String htmlMsg = "This message contains 2 inline images and 2 attachment files.

"; + message.html.content = htmlMsg.c_str(); /** The HTML text message character set e.g. * us-ascii diff --git a/lib/lib_div/lib_mail/examples/Send_Embedded_Message/Send_Embedded_Message.ino b/lib/lib_div/lib_mail/examples/Send_Embedded_Message/Send_Embedded_Message.ino index 99ba2f737..aa9c85554 100755 --- a/lib/lib_div/lib_mail/examples/Send_Embedded_Message/Send_Embedded_Message.ino +++ b/lib/lib_div/lib_mail/examples/Send_Embedded_Message/Send_Embedded_Message.ino @@ -11,7 +11,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/examples/Send_Enriched_Text/Send_Enriched_Text.ino b/lib/lib_div/lib_mail/examples/Send_Enriched_Text/Send_Enriched_Text.ino index bcdfcf6a4..caeee7b64 100755 --- a/lib/lib_div/lib_mail/examples/Send_Enriched_Text/Send_Enriched_Text.ino +++ b/lib/lib_div/lib_mail/examples/Send_Enriched_Text/Send_Enriched_Text.ino @@ -9,7 +9,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/examples/Send_Flash_Message_with_Inline_Image/Send_Flash_Message_with_Inline_Image.ino b/lib/lib_div/lib_mail/examples/Send_Flash_Message_with_Inline_Image/Send_Flash_Message_with_Inline_Image.ino new file mode 100644 index 000000000..1ba0a3ec5 --- /dev/null +++ b/lib/lib_div/lib_mail/examples/Send_Flash_Message_with_Inline_Image/Send_Flash_Message_with_Inline_Image.ino @@ -0,0 +1,287 @@ + + +/** + * This example will send the Email with inline images stored in flash memory. + * The message content stores as HTML data in flash memory + * + * The html and text version messages will be sent. + * + * Created by K. Suwatchai (Mobizt) + * + * Email: suwatchai@outlook.com + * + * Github: https://github.com/mobizt/ESP-Mail-Client + * + * Copyright (c) 2021 mobizt + * +*/ + +//To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1 + +//The file systems for flash and sd memory can be changed in ESP_Mail_FS.h. + +#include +#if defined(ESP32) +#include +#elif defined(ESP8266) +#include +#endif +#include + +#define WIFI_SSID "################" +#define WIFI_PASSWORD "################" + +/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com + * 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 + * and use the app password as password with your yahoo mail account to login. + * The google app password signin is also available https://support.google.com/mail/answer/185833?hl=en +*/ +#define SMTP_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 "################" +#define AUTHOR_PASSWORD "################" + +/* The SMTP Session object used for Email sending */ +SMTPSession smtp; + +/* Callback function to get the Email sending status */ +void smtpCallback(SMTP_Status status); + +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(); + + Serial.println("Mounting SPIFFS..."); + + const char *html = "This message contains 2 inline images.

\"orange \"green"; + const char *orangeImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RMQ0AMAgAsCFgftHLiQpsENJaaFT+fqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBGi/oCaOpTXoAAAAASUVORK5CYII="; + const char *greenImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RAQ0AMAgAoJviyWxtAtNYwzmoQGT/eqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBBaDPbQYiMoMAAAAASUVORK5CYII="; + +#if defined(ESP32) + if (SPIFFS.begin(true)) +#elif defined(ESP8266) + if (SPIFFS.begin()) +#endif + { + + //SPIFFS.format(); + + if (SPIFFS.exists("/orange.png")) + SPIFFS.remove("/orange.png"); + if (SPIFFS.exists("/green.png")) + SPIFFS.remove("/green.png"); + if (SPIFFS.exists("/msg.html")) + SPIFFS.remove("/msg.html"); + + Serial.println("Preparing SPIFFS attachments..."); + +#if defined(ESP32) + File file = SPIFFS.open("/orange.png", FILE_WRITE); +#elif defined(ESP8266) + File file = SPIFFS.open("/orange.png", "w"); +#endif + file.print(orangeImg); + file.close(); + +#if defined(ESP32) + file = SPIFFS.open("/green.png", FILE_WRITE); +#elif defined(ESP8266) + file = SPIFFS.open("/green.png", "w"); +#endif + file.print(greenImg); + file.close(); + +#if defined(ESP32) + file = SPIFFS.open("/msg.html", FILE_WRITE); +#elif defined(ESP8266) + file = SPIFFS.open("/msg.html", "w"); +#endif + file.print(html); + file.close(); + } + else + { + Serial.println("SPIFFS Monting Failed"); + } + + /** Enable the debug via Serial port + * none debug or 0 + * basic debug or 1 + */ + smtp.debug(1); + + /* Set the callback function to get the sending results */ + smtp.callback(smtpCallback); + + /* Declare the session config data */ + ESP_Mail_Session session; + + /* Set the session config */ + session.server.host_name = SMTP_HOST; + session.server.port = SMTP_PORT; + session.login.email = AUTHOR_EMAIL; + session.login.password = AUTHOR_PASSWORD; + session.login.user_domain = "mydomain.net"; + + /* 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 = "ESP Mail"; + message.sender.email = AUTHOR_EMAIL; + + message.subject = "Test sending Email with message content and inline images stored in flash memory"; + message.addRecipient("user1", "####@#####_dot_com"); + + /* Two alternative content versions are sending in this example e.g. plain text and html */ + + /* Assign blob data (in flash or ram) as HTML message */ + message.html.blob.data = (const uint8_t *)html; + message.html.blob.size = strlen(html); + + //Or get the content from file + //message.html.file.name = "/msg.html"; + //message.html.file.type = esp_mail_file_storage_type_flash; + + /** 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 = "utf-8"; + + message.text.content = "This message contains 2 inline images.\r\nThe inline images were not shown in the plain text message."; + message.text.charSet = "utf-8"; + message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64; + + /* Set the custom message header */ + message.addHeader("Message-ID: "); + + /* The attachment data item */ + 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 = "orange.png"; + att.descr.mime = "image/png"; + att.file.path = "/orange.png"; + att.descr.content_id = "image-001"; //The content id (cid) of orange image in the src tag + + /** 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.file.storage_type = esp_mail_file_storage_type_flash; + + /* Need to be base64 transfer encoding for inline image */ + att.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.descr.content_encoding = Content_Transfer_Encoding::enc_base64; + + /* Add inline image to the message */ + message.addInlineImage(att); + + /** Set the inline image 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 = "green.png"; + att.descr.mime = "image/png"; + att.file.path = "/green.png"; + att.descr.content_id = "image-002"; //The content id (cid) of green image in the src tag + att.file.storage_type = esp_mail_file_storage_type_flash; + att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64; + att.descr.content_encoding = Content_Transfer_Encoding::enc_base64; + message.addInlineImage(att); + + /* Connect to server with the session config */ + if (!smtp.connect(&session)) + return; + + /* Start sending the Email and close the session */ + if (!MailClient.sendMail(&smtp, &message, true)) + Serial.println("Error sending Email, " + smtp.errorReason()); +} + +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()) + { + Serial.println("----------------"); + Serial.printf("Message sent success: %d\n", status.completedCount()); + Serial.printf("Message sent failled: %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); + localtime_r(&result.timesstamp, &dt); + + Serial.printf("Message No: %d\n", i + 1); + Serial.printf("Status: %s\n", result.completed ? "success" : "failed"); + Serial.printf("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec); + Serial.printf("Recipient: %s\n", result.recipients); + Serial.printf("Subject: %s\n", result.subject); + } + Serial.println("----------------\n"); + } +} diff --git a/lib/lib_div/lib_mail/examples/Send_HTML/Send_HTML.ino b/lib/lib_div/lib_mail/examples/Send_HTML/Send_HTML.ino index 1f8794690..641009c1a 100755 --- a/lib/lib_div/lib_mail/examples/Send_HTML/Send_HTML.ino +++ b/lib/lib_div/lib_mail/examples/Send_HTML/Send_HTML.ino @@ -11,7 +11,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -25,7 +25,6 @@ #endif #include - #define WIFI_SSID "################" #define WIFI_PASSWORD "################" @@ -87,6 +86,39 @@ void setup() /* Declare the session config data */ ESP_Mail_Session session; + /** ######################################################## + * Some properties of SMTPSession data and parameters pass to + * SMTP_Message class accept the pointer to constant char + * i.e. const char*. + * + * You may assign a string literal to that properties or function + * like below example. + * + * session.login.user_domain = "mydomain.net"; + * session.login.user_domain = String("mydomain.net").c_str(); + * + * or + * + * String doman = "mydomain.net"; + * session.login.user_domain = domain.c_str(); + * + * And + * + * String name = "Jack " + String("dawson"); + * String email = "jack_dawson" + String(123) + "@mail.com"; + * + * message.addRecipient(name.c_str(), email.c_str()); + * + * message.addHeader(String("Message-ID: ").c_str()); + * + * or + * + * String header = "Message-ID: "; + * message.addHeader(header.c_str()); + * + * ########################################################### + */ + /* Set the session config */ session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; @@ -103,7 +135,8 @@ void setup() message.subject = "Test sending html Email"; message.addRecipient("Admin", "####@#####_dot_com"); - message.html.content = "

This is the html text message.

The message was sent via ESP device.

"; + String htmlMsg = "

This is the html text message.

The message was sent via ESP device.

"; + message.html.content = htmlMsg.c_str(); /** The html text message character set e.g. * us-ascii @@ -142,7 +175,6 @@ void setup() /* Set the custom message header */ message.addHeader("Message-ID: "); - /* Connect to server with the session config */ if (!smtp.connect(&session)) diff --git a/lib/lib_div/lib_mail/examples/Send_Parallel_Attachment/Send_Parallel_Attachment.ino b/lib/lib_div/lib_mail/examples/Send_Parallel_Attachment/Send_Parallel_Attachment.ino index 491e14152..27678b415 100755 --- a/lib/lib_div/lib_mail/examples/Send_Parallel_Attachment/Send_Parallel_Attachment.ino +++ b/lib/lib_div/lib_mail/examples/Send_Parallel_Attachment/Send_Parallel_Attachment.ino @@ -14,12 +14,14 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ //To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1 +//The file systems for flash and sd memory can be changed in ESP_Mail_FS.h. + #include #if defined(ESP32) #include diff --git a/lib/lib_div/lib_mail/examples/Send_RFC822_Attachment/Send_RFC822_Attachment.ino b/lib/lib_div/lib_mail/examples/Send_RFC822_Attachment/Send_RFC822_Attachment.ino index b2a67e77d..0f124253c 100755 --- a/lib/lib_div/lib_mail/examples/Send_RFC822_Attachment/Send_RFC822_Attachment.ino +++ b/lib/lib_div/lib_mail/examples/Send_RFC822_Attachment/Send_RFC822_Attachment.ino @@ -11,7 +11,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -205,7 +205,7 @@ void setup() message.addAttachment(att); /* Add rfc822 message in the message */ - message.addRMessage(rfc822); + message.addMessage(rfc822); /* Connect to server with the session config */ if (!smtp.connect(&session)) diff --git a/lib/lib_div/lib_mail/examples/Send_Reuse_Session/Send_Reuse_Session.ino b/lib/lib_div/lib_mail/examples/Send_Reuse_Session/Send_Reuse_Session.ino index df52cccab..b47496535 100755 --- a/lib/lib_div/lib_mail/examples/Send_Reuse_Session/Send_Reuse_Session.ino +++ b/lib/lib_div/lib_mail/examples/Send_Reuse_Session/Send_Reuse_Session.ino @@ -10,7 +10,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/examples/Send_Text/Send_Text.ino b/lib/lib_div/lib_mail/examples/Send_Text/Send_Text.ino index f824e498d..85aa42f03 100755 --- a/lib/lib_div/lib_mail/examples/Send_Text/Send_Text.ino +++ b/lib/lib_div/lib_mail/examples/Send_Text/Send_Text.ino @@ -9,7 +9,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -84,6 +84,39 @@ void setup() /* Declare the session config data */ ESP_Mail_Session session; + /** ######################################################## + * Some properties of SMTPSession data and parameters pass to + * SMTP_Message class accept the pointer to constant char + * i.e. const char*. + * + * You may assign a string literal to that properties or function + * like below example. + * + * session.login.user_domain = "mydomain.net"; + * session.login.user_domain = String("mydomain.net").c_str(); + * + * or + * + * String doman = "mydomain.net"; + * session.login.user_domain = domain.c_str(); + * + * And + * + * String name = "Jack " + String("dawson"); + * String email = "jack_dawson" + String(123) + "@mail.com"; + * + * message.addRecipient(name.c_str(), email.c_str()); + * + * message.addHeader(String("Message-ID: ").c_str()); + * + * or + * + * String header = "Message-ID: "; + * message.addHeader(header.c_str()); + * + * ########################################################### + */ + /* Set the session config */ session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; @@ -100,7 +133,8 @@ void setup() message.subject = "Test sending plain text Email"; message.addRecipient("Someone", "####@#####_dot_com"); - message.text.content = "This is simple plain text message"; + String textMsg = "This is simple plain text message"; + message.text.content = textMsg.c_str(); /** The Plain text message character set e.g. * us-ascii diff --git a/lib/lib_div/lib_mail/examples/Send_Text_Flowed/Send_Text_Flowed.ino b/lib/lib_div/lib_mail/examples/Send_Text_Flowed/Send_Text_Flowed.ino index 384bf7592..83eaa88a4 100755 --- a/lib/lib_div/lib_mail/examples/Send_Text_Flowed/Send_Text_Flowed.ino +++ b/lib/lib_div/lib_mail/examples/Send_Text_Flowed/Send_Text_Flowed.ino @@ -11,7 +11,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ @@ -86,6 +86,39 @@ void setup() /* Declare the session config data */ ESP_Mail_Session session; + /** ######################################################## + * Some properties of SMTPSession data and parameters pass to + * SMTP_Message class accept the pointer to constant char + * i.e. const char*. + * + * You may assign a string literal to that properties or function + * like below example. + * + * session.login.user_domain = "mydomain.net"; + * session.login.user_domain = String("mydomain.net").c_str(); + * + * or + * + * String doman = "mydomain.net"; + * session.login.user_domain = domain.c_str(); + * + * And + * + * String name = "Jack " + String("dawson"); + * String email = "jack_dawson" + String(123) + "@mail.com"; + * + * message.addRecipient(name.c_str(), email.c_str()); + * + * message.addHeader(String("Message-ID: ").c_str()); + * + * or + * + * String header = "Message-ID: "; + * message.addHeader(header.c_str()); + * + * ########################################################### + */ + /* Set the session config */ session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; @@ -93,7 +126,6 @@ void setup() session.login.password = AUTHOR_PASSWORD; session.login.user_domain = "mydomain.net"; - /* Declare the message class */ SMTP_Message message; diff --git a/lib/lib_div/lib_mail/examples/Set_Flags/Set_Flags.ino b/lib/lib_div/lib_mail/examples/Set_Flags/Set_Flags.ino index e256bd4bc..04ce2b3fe 100755 --- a/lib/lib_div/lib_mail/examples/Set_Flags/Set_Flags.ino +++ b/lib/lib_div/lib_mail/examples/Set_Flags/Set_Flags.ino @@ -5,7 +5,7 @@ * * Github: https://github.com/mobizt/ESP-Mail-Client * - * Copyright (c) 2020 mobizt + * Copyright (c) 2021 mobizt * */ diff --git a/lib/lib_div/lib_mail/keywords.txt b/lib/lib_div/lib_mail/keywords.txt index 61a64fdb7..eccf383ae 100755 --- a/lib/lib_div/lib_mail/keywords.txt +++ b/lib/lib_div/lib_mail/keywords.txt @@ -33,6 +33,7 @@ setFlag KEYWORD2 addFlag KEYWORD2 removeFlag KEYWORD2 sdBegin KEYWORD2 +sdMMCBegin KEYWORD2 connect KEYWORD2 closeSession KEYWORD2 debug KEYWORD2 @@ -100,27 +101,27 @@ deleteFolder KEYWORD2 ####################################### -# Struct (LITERAL1) +# Struct (KEYWORD3) ####################################### -esp_mail_email_info_t LITERAL1 -esp_mail_plain_body_t LITERAL1 -esp_mail_html_body_t LITERAL1 -esp_mail_smtp_msg_response_t LITERAL1 -esp_mail_smtp_enable_option_t LITERAL1 -esp_mail_email_info_t LITERAL1 -esp_mail_folder_info_item_t LITERAL1 -esp_mail_sesson_sever_config_t LITERAL1 -esp_mail_sesson_login_config_t LITERAL1 -esp_mail_sesson_secure_config_t LITERAL1 -esp_mail_sesson_cert_config_t LITERAL1 -esp_mail_imap_fetch_config_t LITERAL1 -esp_mail_imap_search_config_t LITERAL1 -esp_mail_imap_limit_config_t LITERAL1 -esp_mail_imap_enable_config_t LITERAL1 -esp_mail_imap_download_config_t LITERAL1 -esp_mail_imap_storage_config_t LITERAL1 +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 LITERAL1 -esp_mail_file_storage_type_flash LITERAL1 -esp_mail_file_storage_type_sd LITERAL1 \ No newline at end of file +esp_mail_file_storage_type_none KEYWORD3 +esp_mail_file_storage_type_flash KEYWORD3 +esp_mail_file_storage_type_sd KEYWORD3 \ No newline at end of file diff --git a/lib/lib_div/lib_mail/library.json b/lib/lib_div/lib_mail/library.json index e98d8e1ea..870d4f993 100755 --- a/lib/lib_div/lib_mail/library.json +++ b/lib/lib_div/lib_mail/library.json @@ -1,6 +1,6 @@ { "name": "ESP Mail Client", - "version": "1.0.13", + "version": "1.2.0", "keywords": "communication, email, imap, smtp, esp32, esp8266, arduino", "description": "Mail Client Arduino Library for Espressif ESP32 and ESP8266 devices. This library allows the ESP32 and ESP8266 devices to send and read Email with the many options and features e.g. the attachments, inline images, embeded rfc822 messages are supported for upload when sending and download when reading the Emails.", "repository": { diff --git a/lib/lib_div/lib_mail/library.properties b/lib/lib_div/lib_mail/library.properties index 2512fe923..572b4998a 100755 --- a/lib/lib_div/lib_mail/library.properties +++ b/lib/lib_div/lib_mail/library.properties @@ -1,9 +1,17 @@ name=ESP Mail Client -version=1.0.13 + +version=1.2.0 + author=Mobizt + maintainer=Mobizt + sentence=Mail Client Arduino Library for Espressif ESP32 and ESP8266 devices. + paragraph=This library allows the ESP32 and ESP8266 devices to send and read Email with the many options and features e.g. the attachments, inline images, embeded rfc822 messages are supported for upload when sending and download when reading the Emails. + category=Communication + url=https://github.com/mobizt/ESP-Mail-Client + architectures=esp32,esp8266 diff --git a/lib/lib_div/lib_mail/media/images/ArduinoIDE.png b/lib/lib_div/lib_mail/media/images/ArduinoIDE.png new file mode 100644 index 000000000..ed4d42897 Binary files /dev/null and b/lib/lib_div/lib_mail/media/images/ArduinoIDE.png differ diff --git a/lib/lib_div/lib_mail/src/ESP_Mail_Client.cpp b/lib/lib_div/lib_mail/src/ESP_Mail_Client.cpp index c042c3358..45678a10a 100755 --- a/lib/lib_div/lib_mail/src/ESP_Mail_Client.cpp +++ b/lib/lib_div/lib_mail/src/ESP_Mail_Client.cpp @@ -1,31 +1,30 @@ /** * Mail Client Arduino Library for Espressif's ESP32 and ESP8266 - * - * Version: 1.0.13 - * Released: January 11, 2021 + * + * Version: 1.2.0 + * Released: May 17, 2021 * * Updates: - * - Fix the IMAP search termination checking https://github.com/mobizt/ESP-Mail-Client/issues/15. - * - Fix the IMAP startTLS consequence commands - * - * - * This library allows Espressif's ESP32 and ESP8266 devices to send and read Email + * - Add support ESP8266 Core SDK v3.x.x. + * + * + * This library allows Espressif's ESP32 and ESP8266 devices to send and read Email * through the SMTP and IMAP servers. - * + * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (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 @@ -402,16 +401,15 @@ bool ESP_Mail_Client::readMail(IMAPSession *imap, bool closeSession) { _sdOk = sdTest(); if (_sdOk) - if (!SD.exists(imap->_config->storage.saved_path)) + if (!ESP_MAIL_SD_FS.exists(imap->_config->storage.saved_path)) createDirs(imap->_config->storage.saved_path); } - else if (!_flashOk && imap->_storageType == esp_mail_file_storage_type_flash) { + else if (!_flashOk && imap->_storageType == esp_mail_file_storage_type_flash) #if defined(ESP32) - // _flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + _flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // _flashOk = FLASH_FS.begin(); + _flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - } } if (cHeader(imap)->part_headers.size() > 0) @@ -598,18 +596,14 @@ bool ESP_Mail_Client::readMail(IMAPSession *imap, bool closeSession) if (imap->_storageType == esp_mail_file_storage_type_sd) { if (_sdOk) - SD.end(); + ESP_MAIL_SD_FS.end(); _sdOk = false; } else if (imap->_storageType == esp_mail_file_storage_type_flash) { - if (_flashOk) { -#if defined(ESP32) - // SPIFFS.end(); -#elif defined(ESP8266) - // FLASH_FS.end(); -#endif - } + if (_flashOk) + ESP_MAIL_FLASH_FS.end(); + _flashOk = false; } } @@ -738,7 +732,7 @@ bool ESP_Mail_Client::fetchMultipartBodyHeader(IMAPSession *imap, int msgIdx) do { - esp_mail_message_part_info_t *_cpart = &cHeader(imap)->part_headers[cHeader(imap)->message_data_count - 1]; + struct esp_mail_message_part_info_t *_cpart = &cHeader(imap)->part_headers[cHeader(imap)->message_data_count - 1]; bool rfc822_body_subtype = _cpart->message_sub_type == esp_mail_imap_message_sub_type_rfc822; std::string cmd; @@ -1388,24 +1382,32 @@ void ESP_Mail_Client::createDirs(std::string dirs) if (dirs[i] == '/') { if (dir.length() > 0) - SD.mkdir(dir.substr(0, dir.length() - 1).c_str()); + ESP_MAIL_SD_FS.mkdir(dir.substr(0, dir.length() - 1).c_str()); count = 0; } } if (count > 0) - SD.mkdir(dir.c_str()); + ESP_MAIL_SD_FS.mkdir(dir.c_str()); std::string().swap(dir); } bool ESP_Mail_Client::sdTest() { - +#if defined(CARD_TYPE_SD) if (_sdConfigSet) sdBegin(_sck, _miso, _mosi, _ss); else sdBegin(); +#endif - file = SD.open(esp_mail_str_204, FILE_WRITE); +#if defined(ESP32) +#if defined(CARD_TYPE_SD_MMC) + if (_sdConfigSet) + sdMMCBegin(sd_mmc_mountpoint, sd_mmc_mode1bit, sd_mmc_format_if_mount_failed); +#endif +#endif + + file = ESP_MAIL_SD_FS.open(esp_mail_str_204, FILE_WRITE); if (!file) return false; @@ -1413,7 +1415,7 @@ bool ESP_Mail_Client::sdTest() return false; file.close(); - file = SD.open(esp_mail_str_204); + file = ESP_MAIL_SD_FS.open(esp_mail_str_204); if (!file) return false; @@ -1424,7 +1426,7 @@ bool ESP_Mail_Client::sdTest() } file.close(); - SD.remove(esp_mail_str_204); + ESP_MAIL_SD_FS.remove(esp_mail_str_204); return true; } @@ -1783,7 +1785,7 @@ bool ESP_Mail_Client::setSendingResult(SMTPSession *smtp, SMTP_Message *msg, boo if (smtp->_sendCallback) { - esp_mail_smtp_send_status_t status; + struct esp_mail_smtp_send_status_t status; status.completed = result; status.timesstamp = time(nullptr); status.subject = msg->subject; @@ -1801,10 +1803,10 @@ bool ESP_Mail_Client::setSendingResult(SMTPSession *smtp, SMTP_Message *msg, boo bool ESP_Mail_Client::sendMail(SMTPSession *smtp, SMTP_Message *msg, bool closeSession) { - if (strlen(msg->html.content) > 0) + if (strlen(msg->html.content) > 0 || msg->html.blob.size > 0 || strlen(msg->html.file.name) > 0) msg->type |= esp_mail_msg_type_html; - if (strlen(msg->text.content) > 0) + if (strlen(msg->text.content) > 0 || msg->text.blob.size > 0 || strlen(msg->text.file.name) > 0) msg->type |= esp_mail_msg_type_plain; for (size_t i = 0; i < msg->_rfc822.size(); i++) @@ -2201,7 +2203,6 @@ bool ESP_Mail_Client::sendMSGData(SMTPSession *smtp, SMTP_Message *msg, bool clo } else { - appendP(s, esp_mail_str_1, true); s += mixed; appendP(s, esp_mail_str_35, false); @@ -2259,7 +2260,6 @@ bool ESP_Mail_Client::sendMSGData(SMTPSession *smtp, SMTP_Message *msg, bool clo if (!rfc822MSG) { - if (smtp->_sendCallback) { smtpCB(smtp, ""); @@ -2543,7 +2543,7 @@ void ESP_Mail_Client::checkBinaryData(SMTPSession *smtp, SMTP_Message *msg) bool ESP_Mail_Client::sendBlob(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att) { - if (strcmpP(att->descr.transfer_encoding, 0, esp_mail_str_31) && strcmp(att->descr.transfer_encoding, att->descr.content_encoding) != 0) + if (strcmp(att->descr.transfer_encoding, Content_Transfer_Encoding::enc_base64) == 0 && strcmp(att->descr.transfer_encoding, att->descr.content_encoding) != 0) { if (!sendBase64(smtp, msg, (const unsigned char *)att->blob.data, att->blob.size, att->_int.flash_blob, att->descr.filename, smtp->_sendCallback != NULL)) return false; @@ -2589,7 +2589,7 @@ bool ESP_Mail_Client::sendBlob(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attach bool ESP_Mail_Client::sendFile(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att, File &file) { - if (strcmpP(att->descr.transfer_encoding, 0, esp_mail_str_31) && strcmp(att->descr.transfer_encoding, att->descr.content_encoding) != 0) + if (strcmp(att->descr.transfer_encoding, Content_Transfer_Encoding::enc_base64) == 0 && strcmp(att->descr.transfer_encoding, att->descr.content_encoding) != 0) { if (!sendBase64Stream(smtp, msg, file, att->descr.filename, smtp->_sendCallback != NULL)) return false; @@ -2726,7 +2726,7 @@ bool ESP_Mail_Client::sendAttachments(SMTPSession *smtp, SMTP_Message *msg, cons esp_mail_debug(s.c_str()); buf.clear(); - getAttachHeader(buf, boundary, att); + getAttachHeader(buf, boundary, att, att->blob.size); if (!bdat(smtp, msg, buf.length(), false)) return false; @@ -2746,20 +2746,16 @@ bool ESP_Mail_Client::sendAttachments(SMTPSession *smtp, SMTP_Message *msg, cons else { - if (att->file.storage_type == esp_mail_file_storage_type_univ) { - - } else { - if (!_sdOk && att->file.storage_type == esp_mail_file_storage_type_sd) _sdOk = sdTest(); - if (!_flashOk && att->file.storage_type == esp_mail_file_storage_type_flash) { + if (!_flashOk && att->file.storage_type == esp_mail_file_storage_type_flash) #if defined(ESP32) - // _flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + _flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // _flashOk = FLASH_FS.begin(); + _flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - } + if ((!_sdOk && att->file.storage_type == esp_mail_file_storage_type_sd) || (!_flashOk && att->file.storage_type == esp_mail_file_storage_type_flash)) { @@ -2776,7 +2772,6 @@ bool ESP_Mail_Client::sendAttachments(SMTPSession *smtp, SMTP_Message *msg, cons continue; } - } if (openFileRead(smtp, msg, att, file, s, buf, boundary, false)) { @@ -2811,18 +2806,11 @@ bool ESP_Mail_Client::openFileRead(SMTPSession *smtp, SMTP_Message *msg, SMTP_At filepath += att->file.path; } - if (att->file.storage_type == esp_mail_file_storage_type_sd) { - file_existed = SD.exists(filepath.c_str()); - } - else if (att->file.storage_type == esp_mail_file_storage_type_flash) { -#if defined(ESP32) - //file_existed = SPIFFS.exists(filepath.c_str()); -#elif defined(ESP8266) - //file_existed = FLASH_FS.exists(filepath.c_str()); -#endif -} else if (att->file.storage_type == esp_mail_file_storage_type_univ) { - file_existed = ufsp->exists(filepath.c_str()); -} + if (att->file.storage_type == esp_mail_file_storage_type_sd) + file_existed = ESP_MAIL_SD_FS.exists(filepath.c_str()); + else if (att->file.storage_type == esp_mail_file_storage_type_flash) + file_existed = ESP_MAIL_FLASH_FS.exists(filepath.c_str()); + if (!file_existed) { @@ -2834,19 +2822,10 @@ bool ESP_Mail_Client::openFileRead(SMTPSession *smtp, SMTP_Message *msg, SMTP_At filepath += att->descr.filename; } - if (att->file.storage_type == esp_mail_file_storage_type_sd) { - file_existed = SD.exists(filepath.c_str()); - } - else if (att->file.storage_type == esp_mail_file_storage_type_flash) { -#if defined(ESP32) - //file_existed = SPIFFS.exists(filepath.c_str()); -#elif defined(ESP8266) - //file_existed = FLASH_FS.exists(filepath.c_str()); -#endif - } - else if (att->file.storage_type == esp_mail_file_storage_type_univ) { - file_existed = ufsp->exists(filepath.c_str()); - } + if (att->file.storage_type == esp_mail_file_storage_type_sd) + file_existed = ESP_MAIL_SD_FS.exists(filepath.c_str()); + else if (att->file.storage_type == esp_mail_file_storage_type_flash) + file_existed = ESP_MAIL_FLASH_FS.exists(filepath.c_str()); } if (!file_existed) @@ -2867,10 +2846,23 @@ bool ESP_Mail_Client::openFileRead(SMTPSession *smtp, SMTP_Message *msg, SMTP_At { buf.clear(); + + if (att->file.storage_type == esp_mail_file_storage_type_sd) + file = ESP_MAIL_SD_FS.open(filepath.c_str(), FILE_READ); + else if (att->file.storage_type == esp_mail_file_storage_type_flash) +#if defined(ESP32) + file = ESP_MAIL_FLASH_FS.open(filepath.c_str(), FILE_READ); +#elif defined(ESP8266) + file = ESP_MAIL_FLASH_FS.open(filepath.c_str(), "r"); +#endif + + if (!file) + return false; + if (inlined) - getInlineHeader(buf, boundary, att); + getInlineHeader(buf, boundary, att, file.size()); else - getAttachHeader(buf, boundary, att); + getAttachHeader(buf, boundary, att, file.size()); if (!bdat(smtp, msg, buf.length(), false)) return false; @@ -2878,19 +2870,53 @@ bool ESP_Mail_Client::openFileRead(SMTPSession *smtp, SMTP_Message *msg, SMTP_At if (smtpSend(smtp, buf.c_str(), false) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) return false; - if (att->file.storage_type == esp_mail_file_storage_type_sd) { - file = SD.open(filepath.c_str(), FILE_READ); + return true; + } + + return false; +} + +bool ESP_Mail_Client::openFileRead2(SMTPSession *smtp, SMTP_Message *msg, File &file, const char *path, esp_mail_file_storage_type storageType) +{ + bool file_existed = false; + std::string filepath; + + if (strlen(path) > 0) + { + if (path[0] != '/') + appendP(filepath, esp_mail_str_202, true); + filepath += path; + } + + if (storageType == esp_mail_file_storage_type_sd) + file_existed = ESP_MAIL_SD_FS.exists(filepath.c_str()); + else if (storageType == esp_mail_file_storage_type_flash) + file_existed = ESP_MAIL_FLASH_FS.exists(filepath.c_str()); + + if (!file_existed) + { + if (smtp->_sendCallback) + debugInfoP(esp_mail_str_158); + + if (smtp->_debug) + { + std::string e; + appendP(e, esp_mail_str_185, true); + appendP(e, esp_mail_str_158, false); + esp_mail_debug(e.c_str()); } - else if (att->file.storage_type == esp_mail_file_storage_type_flash) { + } + + if (file_existed) + { + if (storageType == esp_mail_file_storage_type_sd) + file = ESP_MAIL_SD_FS.open(filepath.c_str(), FILE_READ); + else if (storageType == esp_mail_file_storage_type_flash) #if defined(ESP32) - //file = SPIFFS.open(filepath.c_str(), FILE_READ); + file = ESP_MAIL_FLASH_FS.open(filepath.c_str(), FILE_READ); #elif defined(ESP8266) - //file = FLASH_FS.open(filepath.c_str(), "r"); + file = ESP_MAIL_FLASH_FS.open(filepath.c_str(), "r"); #endif - } - else if (att->file.storage_type == esp_mail_file_storage_type_univ) { - file = ufsp->open(filepath.c_str(), "r"); - } return true; } @@ -2941,7 +2967,6 @@ bool ESP_Mail_Client::sendInline(SMTPSession *smtp, SMTP_Message *msg, const std if (num > 0) { - for (uint8_t i = 0; i < msg->_att.size(); i++) { att = &msg->_att[i]; @@ -2974,7 +2999,7 @@ bool ESP_Mail_Client::sendInline(SMTPSession *smtp, SMTP_Message *msg, const std esp_mail_debug(s.c_str()); buf.clear(); - getInlineHeader(buf, related, att); + getInlineHeader(buf, related, att, att->blob.size); if (!bdat(smtp, msg, buf.length(), false)) return false; @@ -2993,18 +3018,16 @@ bool ESP_Mail_Client::sendInline(SMTPSession *smtp, SMTP_Message *msg, const std } else { - if (att->file.storage_type == esp_mail_file_storage_type_univ) { - } else { if (!_sdOk && att->file.storage_type == esp_mail_file_storage_type_sd) _sdOk = sdTest(); - if (!_flashOk && att->file.storage_type == esp_mail_file_storage_type_flash) { + if (!_flashOk && att->file.storage_type == esp_mail_file_storage_type_flash) #if defined(ESP32) - // _flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + _flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // _flashOk = FLASH_FS.begin(); + _flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - } + if ((!_sdOk && att->file.storage_type == esp_mail_file_storage_type_sd) || (!_flashOk && att->file.storage_type == esp_mail_file_storage_type_flash)) { @@ -3021,7 +3044,6 @@ bool ESP_Mail_Client::sendInline(SMTPSession *smtp, SMTP_Message *msg, const std continue; } - } if (openFileRead(smtp, msg, att, file, s, buf, related, true)) { @@ -3303,21 +3325,39 @@ bool ESP_Mail_Client::sdBegin(uint8_t sck, uint8_t miso, uint8_t mosi, uint8_t s _ss = ss; _sdConfigSet = true; #if defined(ESP32) +#if defined(CARD_TYPE_SD) SPI.begin(_sck, _miso, _mosi, _ss); - return SD.begin(_ss, SPI); -#elif defined(ESP8266) - return SD.begin(_ss); + return ESP_MAIL_SD_FS.begin(_ss, SPI); #endif +#elif defined(ESP8266) + return ESP_MAIL_SD_FS.begin(_ss); +#endif + return false; } bool ESP_Mail_Client::sdBegin(void) { _sdConfigSet = false; #if defined(ESP32) - return SD.begin(); + return ESP_MAIL_SD_FS.begin(); #elif defined(ESP8266) - return SD.begin(SD_CS_PIN); + return ESP_MAIL_SD_FS.begin(SD_CS_PIN); #endif + return false; +} + +bool ESP_Mail_Client::sdMMCBegin(const char *mountpoint, bool mode1bit, bool format_if_mount_failed) +{ +#if defined(ESP32) +#if defined(CARD_TYPE_SD_MMC) + _sdConfigSet = true; + sd_mmc_mountpoint = mountpoint; + sd_mmc_mode1bit = mode1bit; + sd_mmc_format_if_mount_failed = format_if_mount_failed; + return ESP_MAIL_SD_FS.begin(mountpoint, mode1bit, format_if_mount_failed); +#endif +#endif + return false; } bool ESP_Mail_Client::sendPartText(SMTPSession *smtp, SMTP_Message *msg, uint8_t type, const char *boundary) @@ -3476,7 +3516,34 @@ bool ESP_Mail_Client::sendPartText(SMTPSession *smtp, SMTP_Message *msg, uint8_t appendP(header, esp_mail_str_34, false); - encodingText(smtp, msg, type, header); + if ((msg->text.blob.size > 0 && (type == esp_mail_msg_type_plain || type == esp_mail_msg_type_enriched)) || (msg->html.blob.size > 0 && type == esp_mail_msg_type_html)) + { + if (!bdat(smtp, msg, header.length(), false)) + return false; + + if (smtpSend(smtp, header.c_str()) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) + return false; + + header.clear(); + + if (!sendBlobBody(smtp, msg, type)) + return false; + } + else if ((strlen(msg->text.file.name) > 0 && (type == esp_mail_msg_type_plain || type == esp_mail_msg_type_enriched)) || (strlen(msg->html.file.name) > 0 && type == esp_mail_msg_type_html)) + { + if (!bdat(smtp, msg, header.length(), false)) + return false; + + if (smtpSend(smtp, header.c_str()) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) + return false; + + header.clear(); + + if (!sendFileBody(smtp, msg, type)) + return false; + } + else + encodingText(smtp, msg, type, header); appendP(header, esp_mail_str_34, false); @@ -3500,6 +3567,256 @@ char *ESP_Mail_Client::getUID() return tmp; } +bool ESP_Mail_Client::sendBlobBody(SMTPSession *smtp, SMTP_Message *msg, uint8_t type) +{ + + if (msg->text.blob.size == 0 && msg->html.blob.size == 0) + return true; + + bool ret = true; + int bufLen = 512; + size_t pos = 0; + int pg = 0, _pg = 0; + + if (type == esp_mail_msg_type_plain || type == esp_mail_msg_type_enriched) + { + char *tmp = strP(esp_mail_str_325); + + if (strlen(msg->text.transfer_encoding) > 0) + { + if (strcmp(msg->text.transfer_encoding, Content_Transfer_Encoding::enc_base64) == 0) + { + ret = sendBase64(smtp, msg, (const unsigned char *)msg->text.blob.data, msg->text.blob.size, true, tmp, smtp->_sendCallback != NULL); + delS(tmp); + return ret; + } + } + + int len = msg->text.blob.size; + int available = len; + uint8_t *buf = new uint8_t[bufLen + 1]; + while (available) + { + if (available > bufLen) + available = bufLen; + + memcpy_P(buf, msg->text.blob.data + pos, available); + + if (!bdat(smtp, msg, available, false)) + break; + if (smtpSend(smtp, buf, available) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) + break; + pos += available; + len -= available; + available = len; + if (smtp->_sendCallback) + { + pg = (float)(100.0f * pos / msg->text.blob.size); + if (pg != _pg) + uploadReport(tmp, pg); + _pg = pg; + } + } + delete[] buf; + delS(tmp); + } + else if (type == esp_mail_message_type::esp_mail_msg_type_html) + { + char *tmp = strP(esp_mail_str_325); + + if (strlen(msg->html.transfer_encoding) > 0) + { + if (strcmp(msg->html.transfer_encoding, Content_Transfer_Encoding::enc_base64) == 0) + { + ret = sendBase64(smtp, msg, (const unsigned char *)msg->html.blob.data, msg->html.blob.size, true, tmp, smtp->_sendCallback != NULL); + delS(tmp); + return ret; + } + } + int len = msg->html.blob.size; + int available = len; + uint8_t *buf = new uint8_t[bufLen + 1]; + while (available) + { + + if (available > bufLen) + available = bufLen; + + memcpy_P(buf, msg->html.blob.data + pos, available); + + if (!bdat(smtp, msg, available, false)) + { + ret = false; + break; + } + + if (smtpSend(smtp, buf, available) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) + { + ret = false; + break; + } + pos += available; + len -= available; + available = len; + if (smtp->_sendCallback) + { + pg = (float)(100.0f * pos / msg->html.blob.size); + if (pg != _pg) + uploadReport(tmp, pg); + _pg = pg; + } + } + delete[] buf; + delS(tmp); + } + return ret; +} + +bool ESP_Mail_Client::sendFileBody(SMTPSession *smtp, SMTP_Message *msg, uint8_t type) +{ + + if (strlen(msg->text.file.name) == 0 && strlen(msg->html.file.name) == 0) + return true; + + bool ret = true; + size_t chunkSize = ESP_MAIL_CLIENT_STREAM_CHUNK_SIZE; + size_t writeLen = 0; + int pg = 0, _pg = 0; + + if (type == esp_mail_msg_type_plain || type == esp_mail_msg_type_enriched) + { + + if (!openFileRead2(smtp, msg, file, msg->text.file.name, msg->text.file.type)) + return false; + + char *tmp = strP(esp_mail_str_326); + + if (strlen(msg->text.transfer_encoding) > 0) + { + if (strcmp(msg->text.transfer_encoding, Content_Transfer_Encoding::enc_base64) == 0) + { + ret = sendBase64Stream(smtp, msg, file, tmp, smtp->_sendCallback != NULL); + delS(tmp); + return ret; + } + } + + if (file.size() > 0) + { + + if (file.size() < chunkSize) + chunkSize = file.size(); + uint8_t *buf = new uint8_t[chunkSize]; + while (writeLen < file.size() && file.available()) + { + if (writeLen > file.size() - chunkSize) + chunkSize = file.size() - writeLen; + size_t readLen = file.read(buf, chunkSize); + + if (readLen != chunkSize) + { + errorStatusCB(smtp, MAIL_CLIENT_ERROR_FILE_IO_ERROR); + break; + } + + if (!bdat(smtp, msg, chunkSize, false)) + { + ret = false; + break; + } + + if (smtpSend(smtp, buf, chunkSize) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) + { + ret = false; + break; + } + + if (smtp->_sendCallback) + { + pg = (float)(100.0f * writeLen / file.size()); + if (pg != _pg) + uploadReport(tmp, pg); + _pg = pg; + } + writeLen += chunkSize; + } + delete[] buf; + if (smtp->_sendCallback && _pg < 100) + uploadReport(tmp, 100); + + delS(tmp); + return ret && writeLen == file.size(); + } + } + else if (type == esp_mail_message_type::esp_mail_msg_type_html) + { + + if (!openFileRead2(smtp, msg, file, msg->html.file.name, msg->html.file.type)) + return false; + + char *tmp = strP(esp_mail_str_326); + + if (strlen(msg->html.transfer_encoding) > 0) + { + if (strcmp(msg->html.transfer_encoding, Content_Transfer_Encoding::enc_base64) == 0) + { + ret = sendBase64Stream(smtp, msg, file, tmp, smtp->_sendCallback != NULL); + delS(tmp); + return ret; + } + } + + if (file.size() > 0) + { + + if (file.size() < chunkSize) + chunkSize = file.size(); + uint8_t *buf = new uint8_t[chunkSize]; + while (writeLen < file.size() && file.available()) + { + if (writeLen > file.size() - chunkSize) + chunkSize = file.size() - writeLen; + size_t readLen = file.read(buf, chunkSize); + + if (readLen != chunkSize) + { + errorStatusCB(smtp, MAIL_CLIENT_ERROR_FILE_IO_ERROR); + break; + } + + if (!bdat(smtp, msg, chunkSize, false)) + { + ret = false; + break; + } + + if (smtpSend(smtp, buf, chunkSize) == ESP_MAIL_CLIENT_TRANSFER_DATA_FAILED) + { + ret = false; + break; + } + + if (smtp->_sendCallback) + { + pg = (float)(100.0f * writeLen / file.size()); + if (pg != _pg) + uploadReport(tmp, pg); + _pg = pg; + } + writeLen += chunkSize; + } + delete[] buf; + if (smtp->_sendCallback && _pg < 100) + uploadReport(tmp, 100); + + delS(tmp); + return ret && writeLen == file.size(); + } + } + + return false; +} + void ESP_Mail_Client::encodingText(SMTPSession *smtp, SMTP_Message *msg, uint8_t type, std::string &content) { if (type == esp_mail_msg_type_plain || type == esp_mail_msg_type_enriched) @@ -3549,7 +3866,10 @@ void ESP_Mail_Client::encodingText(SMTPSession *smtp, SMTP_Message *msg, uint8_t appendP(rep, esp_mail_str_136, true); appendP(rep, esp_mail_str_302, false); - rep += att->_int.cid; + if (strlen(att->descr.content_id) > 0) + rep += att->descr.content_id; + else + rep += att->_int.cid; appendP(rep, esp_mail_str_136, false); tmp = strReplace((char *)s.c_str(), (char *)fnd.c_str(), (char *)rep.c_str()); @@ -3596,14 +3916,14 @@ void ESP_Mail_Client::splitTk(std::string &str, std::vector &tk, co std::string().swap(s); } -/** Add the soft line break to the long text line (rfc 3676) +/** Add the soft line break to the long text line (rfc 3676) * and add Format=flowed parameter in the plain text content-type header. * We use the existing white space as a part of this soft line break * and set delSp="no" parameter to the header. - * + * * Some servers are not rfc 3676 compliant. * This causes the text lines are wrapped instead of joined. - * + * * Some mail clients trim the space before the line break * which makes the soft line break cannot be seen. */ @@ -3755,7 +4075,7 @@ bool ESP_Mail_Client::sendMSG(SMTPSession *smtp, SMTP_Message *msg, const std::s return true; } -void ESP_Mail_Client::getInlineHeader(std::string &header, const std::string &boundary, SMTP_Attachment *inlineAttach) +void ESP_Mail_Client::getInlineHeader(std::string &header, const std::string &boundary, SMTP_Attachment *inlineAttach, size_t size) { appendP(header, esp_mail_str_33, false); header += boundary; @@ -3789,15 +4109,21 @@ void ESP_Mail_Client::getInlineHeader(std::string &header, const std::string &bo appendP(header, esp_mail_str_299, false); header += filename; - appendP(header, esp_mail_str_36, false); + appendP(header, esp_mail_str_327, false); + char *tmp = intStr(size); + header += tmp; + delS(tmp); + appendP(header, esp_mail_str_34, false); appendP(header, esp_mail_str_300, false); header += filename; appendP(header, esp_mail_str_34, false); appendP(header, esp_mail_str_301, false); - - header += inlineAttach->_int.cid; + if (strlen(inlineAttach->descr.content_id) > 0) + header += inlineAttach->descr.content_id; + else + header += inlineAttach->_int.cid; appendP(header, esp_mail_str_15, false); @@ -3814,7 +4140,7 @@ void ESP_Mail_Client::getInlineHeader(std::string &header, const std::string &bo std::string().swap(filename); } -void ESP_Mail_Client::getAttachHeader(std::string &header, const std::string &boundary, SMTP_Attachment *attach) +void ESP_Mail_Client::getAttachHeader(std::string &header, const std::string &boundary, SMTP_Attachment *attach, size_t size) { appendP(header, esp_mail_str_33, false); header += boundary; @@ -3849,7 +4175,11 @@ void ESP_Mail_Client::getAttachHeader(std::string &header, const std::string &bo { appendP(header, esp_mail_str_30, false); header += filename; - appendP(header, esp_mail_str_36, false); + appendP(header, esp_mail_str_327, false); + char *tmp = intStr(size); + header += tmp; + delS(tmp); + appendP(header, esp_mail_str_34, false); } if (strlen(attach->descr.transfer_encoding) > 0) @@ -5069,10 +5399,22 @@ void ESP_Mail_Client::setSecure(ESP_Mail_HTTPClient &httpClient, ESP_Mail_Sessio #endif } +bool ESP_Mail_Client::ethLinkUp() +{ + bool ret = false; +#if defined(ESP32) + char *ip = strP(esp_mail_str_328); + if (strcmp(ETH.localIP().toString().c_str(), ip) != 0) + ret = ETH.linkUp(); + delS(ip); +#endif + return ret; +} + bool ESP_Mail_Client::reconnect(SMTPSession *smtp, unsigned long dataTime) { - bool status = WiFi.status() == WL_CONNECTED; + bool status = WiFi.status() == WL_CONNECTED || ethLinkUp(); if (dataTime > 0) { @@ -5101,7 +5443,7 @@ bool ESP_Mail_Client::reconnect(SMTPSession *smtp, unsigned long dataTime) _lastReconnectMillis = millis(); } - status = WiFi.status() == WL_CONNECTED; + status = WiFi.status() == WL_CONNECTED || ethLinkUp(); } return status; @@ -5110,7 +5452,7 @@ bool ESP_Mail_Client::reconnect(SMTPSession *smtp, unsigned long dataTime) bool ESP_Mail_Client::reconnect(IMAPSession *imap, unsigned long dataTime, bool downloadRequest) { - bool status = WiFi.status() == WL_CONNECTED; + bool status = WiFi.status() == WL_CONNECTED || ethLinkUp(); if (dataTime > 0) { @@ -5163,7 +5505,7 @@ bool ESP_Mail_Client::reconnect(IMAPSession *imap, unsigned long dataTime, bool _lastReconnectMillis = millis(); } - status = WiFi.status() == WL_CONNECTED; + status = WiFi.status() == WL_CONNECTED || ethLinkUp(); } return status; @@ -5400,22 +5742,27 @@ bool ESP_Mail_Client::handleIMAPResponse(IMAPSession *imap, int errCode, bool cl esp_mail_debug((const char *)response); } - //some IMAP servers advertise CAPABILITY in their responses - //try to read the next available response - memset(response, 0, chunkBufSize); - if (!imap->_secure) - readLen = _readLine(imap->httpClient._stream(), response, chunkBufSize, true, octetCount); + if (imap->_imap_cmd == esp_mail_imap_cmd_close) + completedResponse = true; else - readLen = readLine(imap->httpClient.stream(), response, chunkBufSize, true, octetCount); - if (readLen) { - completedResponse = false; - imapResp = imapResponseStatus(imap, response); - if (imapResp > esp_mail_imap_response_status::esp_mail_imap_resp_unknown) + //some IMAP servers advertise CAPABILITY in their responses + //try to read the next available response + memset(response, 0, chunkBufSize); + if (!imap->_secure) + readLen = _readLine(imap->httpClient._stream(), response, chunkBufSize, true, octetCount); + else + readLen = readLine(imap->httpClient.stream(), response, chunkBufSize, true, octetCount); + if (readLen) + { + completedResponse = false; + imapResp = imapResponseStatus(imap, response); + if (imapResp > esp_mail_imap_response_status::esp_mail_imap_resp_unknown) + completedResponse = true; + } + else completedResponse = true; } - else - completedResponse = true; } else { @@ -5626,7 +5973,7 @@ bool ESP_Mail_Client::handleIMAPResponse(IMAPSession *imap, int errCode, bool cl if (cHeader(imap)->part_headers.size() > 0) { - esp_mail_message_part_info_t *_part = &cHeader(imap)->part_headers[cHeader(imap)->part_headers.size() - 1]; + struct esp_mail_message_part_info_t *_part = &cHeader(imap)->part_headers[cHeader(imap)->part_headers.size() - 1]; bool rfc822_body_subtype = _part->message_sub_type == esp_mail_imap_message_sub_type_rfc822; if (rfc822_body_subtype) @@ -5695,27 +6042,27 @@ void ESP_Mail_Client::saveHeader(IMAPSession *imap) prepareFilePath(imap, headerFilePath, true); if (imap->_storageType == esp_mail_file_storage_type_sd && !_sdOk) _sdOk = sdTest(); - else if (imap->_storageType == esp_mail_file_storage_type_flash && !_flashOk) { + else if (imap->_storageType == esp_mail_file_storage_type_flash && !_flashOk) #if defined(ESP32) - // _flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + _flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // _flashOk = FLASH_FS.begin(); + _flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - } + if (_sdOk || _flashOk) { if (file) file.close(); if (imap->_storageType == esp_mail_file_storage_type_sd) - file = SD.open(headerFilePath.c_str(), FILE_WRITE); - else if (imap->_storageType == esp_mail_file_storage_type_flash) { + file = ESP_MAIL_SD_FS.open(headerFilePath.c_str(), FILE_WRITE); + else if (imap->_storageType == esp_mail_file_storage_type_flash) #if defined(ESP32) - // file = SPIFFS.open(headerFilePath.c_str(), FILE_WRITE); + file = ESP_MAIL_FLASH_FS.open(headerFilePath.c_str(), FILE_WRITE); #elif defined(ESP8266) - // file = FLASH_FS.open(headerFilePath.c_str(), "w"); + file = ESP_MAIL_FLASH_FS.open(headerFilePath.c_str(), "w"); #endif - } + if (file) { std::string s; @@ -5933,13 +6280,13 @@ bool ESP_Mail_Client::handleAttachment(IMAPSession *imap, char *buf, int bufLen, if (imap->_storageType == esp_mail_file_storage_type_sd && !_sdOk) _sdOk = sdTest(); - else if (imap->_storageType == esp_mail_file_storage_type_flash && !_flashOk) { + else if (imap->_storageType == esp_mail_file_storage_type_flash && !_flashOk) #if defined(ESP32) - // _flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + _flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // _flashOk = FLASH_FS.begin(); + _flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - } + if (_sdOk || _flashOk) { @@ -5954,7 +6301,7 @@ bool ESP_Mail_Client::handleAttachment(IMAPSession *imap, char *buf, int bufLen, delS(tmp); if (imap->_storageType == esp_mail_file_storage_type_sd) - if (!SD.exists(filePath.c_str())) + if (!ESP_MAIL_SD_FS.exists(filePath.c_str())) createDirs(filePath); appendP(filePath, esp_mail_str_202, false); @@ -5962,14 +6309,13 @@ bool ESP_Mail_Client::handleAttachment(IMAPSession *imap, char *buf, int bufLen, filePath += cPart(imap)->filename; if (imap->_storageType == esp_mail_file_storage_type_sd) - file = SD.open(filePath.c_str(), FILE_WRITE); - else if (imap->_storageType == esp_mail_file_storage_type_flash) { + file = ESP_MAIL_SD_FS.open(filePath.c_str(), FILE_WRITE); + else if (imap->_storageType == esp_mail_file_storage_type_flash) #if defined(ESP32) - // file = SPIFFS.open(filePath.c_str(), FILE_WRITE); + file = ESP_MAIL_FLASH_FS.open(filePath.c_str(), FILE_WRITE); #elif defined(ESP8266) - // file = FLASH_FS.open(filePath.c_str(), "w"); + file = ESP_MAIL_FLASH_FS.open(filePath.c_str(), "w"); #endif - } } } @@ -6363,14 +6709,13 @@ void ESP_Mail_Client::decodeText(IMAPSession *imap, char *buf, int bufLen, int & downloadRequest = true; if (imap->_storageType == esp_mail_file_storage_type_sd) - file = SD.open(filePath.c_str(), FILE_WRITE); - else if (imap->_storageType == esp_mail_file_storage_type_flash) { + file = ESP_MAIL_SD_FS.open(filePath.c_str(), FILE_WRITE); + else if (imap->_storageType == esp_mail_file_storage_type_flash) #if defined(ESP32) - // file = SPIFFS.open(filePath.c_str(), FILE_WRITE); + file = ESP_MAIL_FLASH_FS.open(filePath.c_str(), FILE_WRITE); #elif defined(ESP8266) - // file = FLASH_FS.open(filePath.c_str(), "w"); + file = ESP_MAIL_FLASH_FS.open(filePath.c_str(), "w"); #endif - } } } @@ -6394,7 +6739,7 @@ void ESP_Mail_Client::prepareFilePath(IMAPSession *imap, std::string &filePath, delS(tmp); if (imap->_storageType == esp_mail_file_storage_type_sd) - if (!SD.exists(fpath.c_str())) + if (!ESP_MAIL_SD_FS.exists(fpath.c_str())) createDirs(fpath); if (header) @@ -7183,31 +7528,12 @@ bool ESP_Mail_Client::sendBase64Stream(SMTPSession *smtp, SMTP_Message *msg, Fil } else { - if (len - fbufIndex == 1) + size_t readLen = file.read(fbuf, len - fbufIndex); + if (readLen != len - fbufIndex) { - fbuf[0] = file.read(); - if (fbuf[0] < 0) - { - errorStatusCB(smtp, MAIL_CLIENT_ERROR_FILE_IO_ERROR); - break; - } + errorStatusCB(smtp, MAIL_CLIENT_ERROR_FILE_IO_ERROR); + break; } - else if (len - fbufIndex == 2) - { - fbuf[0] = file.read(); - if (fbuf[0] < 0) - { - errorStatusCB(smtp, MAIL_CLIENT_ERROR_FILE_IO_ERROR); - break; - } - fbuf[1] = file.read(); - if (fbuf[1] < 0) - { - errorStatusCB(smtp, MAIL_CLIENT_ERROR_FILE_IO_ERROR); - break; - } - } - break; } } @@ -7269,9 +7595,9 @@ bool IMAPSession::closeSession() if (!_tcpConnected) return false; #if defined(ESP32) - /** + /** * The strange behavior in ESP8266 SSL client, BearSSLWiFiClientSecure - * The client disposed without memory released after the server close + * The client disposed without memory released after the server close * the connection due to LOGOUT command, which caused the memory leaks. */ if (!MailClient.imapLogout(this)) @@ -7282,7 +7608,6 @@ bool IMAPSession::closeSession() bool IMAPSession::connect(ESP_Mail_Session *sesssion, IMAP_Config *config) { - if (_tcpConnected) MailClient.closeTCP(this); @@ -7297,13 +7622,12 @@ bool IMAPSession::connect(ESP_Mail_Session *sesssion, IMAP_Config *config) { if (_sesson_cfg->certificate.cert_file_storage_type == esp_mail_file_storage_type::esp_mail_file_storage_type_sd && !MailClient._sdOk) MailClient._sdOk = MailClient.sdTest(); - if (_sesson_cfg->certificate.cert_file_storage_type == esp_mail_file_storage_type::esp_mail_file_storage_type_flash && !MailClient._flashOk) { + if (_sesson_cfg->certificate.cert_file_storage_type == esp_mail_file_storage_type::esp_mail_file_storage_type_flash && !MailClient._flashOk) #if defined(ESP32) - // MailClient._flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + MailClient._flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // MailClient._flashOk = FLASH_FS.begin(); + MailClient._flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - } } return MailClient.imapAuth(this); @@ -7446,16 +7770,16 @@ bool IMAPSession::headerOnly() return _headerOnly; } -esp_mail_imap_msg_list_t IMAPSession::data() +struct esp_mail_imap_msg_list_t IMAPSession::data() { - esp_mail_imap_msg_list_t ret; + struct esp_mail_imap_msg_list_t ret; for (size_t i = 0; i < _headers.size(); i++) { if (ESP.getFreeHeap() < ESP_MAIL_MIN_MEM) continue; - esp_mail_imap_msg_item_t itm; + struct esp_mail_imap_msg_item_t itm; itm.UID = _headers[i].message_uid.c_str(); itm.ID = _headers[i].message_id.c_str(); @@ -7491,7 +7815,7 @@ void IMAPSession::callback(imapStatusCallback imapCallback) _readCallback = std::move(imapCallback); } -void IMAPSession::getMessages(uint16_t messageIndex, esp_mail_imap_msg_item_t &msg) +void IMAPSession::getMessages(uint16_t messageIndex, struct esp_mail_imap_msg_item_t &msg) { msg.text.content = ""; msg.text.charSet = ""; @@ -7546,7 +7870,7 @@ void IMAPSession::getMessages(uint16_t messageIndex, esp_mail_imap_msg_item_t &m } } -void IMAPSession::getRFC822Messages(uint16_t messageIndex, esp_mail_imap_msg_item_t &msg) +void IMAPSession::getRFC822Messages(uint16_t messageIndex, struct esp_mail_imap_msg_item_t &msg) { if (messageIndex < _headers.size()) { @@ -7982,14 +8306,12 @@ bool SMTPSession::connect(ESP_Mail_Session *config) { if (_sesson_cfg->certificate.cert_file_storage_type == esp_mail_file_storage_type::esp_mail_file_storage_type_sd && !MailClient._sdOk) MailClient._sdOk = MailClient.sdTest(); - if (_sesson_cfg->certificate.cert_file_storage_type == esp_mail_file_storage_type::esp_mail_file_storage_type_flash && !MailClient._flashOk) { + if (_sesson_cfg->certificate.cert_file_storage_type == esp_mail_file_storage_type::esp_mail_file_storage_type_flash && !MailClient._flashOk) #if defined(ESP32) - // MailClient._flashOk = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); + MailClient._flashOk = ESP_MAIL_FLASH_FS.begin(FORMAT_FLASH); #elif defined(ESP8266) - // MailClient._flashOk = FLASH_FS.begin(); + MailClient._flashOk = ESP_MAIL_FLASH_FS.begin(); #endif - MailClient._flashOk = 1; - } } return MailClient.smtpAuth(this); } @@ -8013,16 +8335,6 @@ void SMTPSession::debug(int level) String SMTPSession::errorReason() { std::string ret; - if (_smtpStatus.text.length() > 0) - { - MailClient.appendP(ret, esp_mail_str_312, true); - char *code = MailClient.intStr(_smtpStatus.respCode); - ret += code; - MailClient.delS(code); - MailClient.appendP(ret, esp_mail_str_313, false); - ret += _smtpStatus.text; - return ret.c_str(); - } switch (_smtpStatus.statusCode) { @@ -8090,6 +8402,17 @@ String SMTPSession::errorReason() default: break; } + + if (_smtpStatus.text.length() > 0 && ret.length() == 0) + { + MailClient.appendP(ret, esp_mail_str_312, true); + char *code = MailClient.intStr(_smtpStatus.respCode); + ret += code; + MailClient.delS(code); + MailClient.appendP(ret, esp_mail_str_313, false); + ret += _smtpStatus.text; + return ret.c_str(); + } return ret.c_str(); } @@ -8113,9 +8436,9 @@ bool SMTPSession::closeSession() /* Sign out */ #if defined(ESP32) - /** + /** * The strange behavior in ESP8266 SSL client, BearSSLWiFiClientSecure - * The client disposed without memory released after the server close + * The client disposed without memory released after the server close * the connection due to QUIT command, which caused the memory leaks. */ MailClient.smtpSendP(this, esp_mail_str_7, true); @@ -8206,4 +8529,4 @@ void SMTP_Status::empty() ESP_Mail_Client MailClient = ESP_Mail_Client(); -#endif /* ESP_Mail_Client_CPP */ +#endif /* ESP_Mail_Client_CPP */ \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/ESP_Mail_Client.h b/lib/lib_div/lib_mail/src/ESP_Mail_Client.h index f26da0665..0eda23a80 100755 --- a/lib/lib_div/lib_mail/src/ESP_Mail_Client.h +++ b/lib/lib_div/lib_mail/src/ESP_Mail_Client.h @@ -1,64 +1,66 @@ +#ifndef ESP_Mail_Client_H +#define ESP_Mail_Client_H + +#define ESP_MAIL_VERSION "1.2.0" + /** * Mail Client Arduino Library for Espressif's ESP32 and ESP8266 * - * Version: 1.0.13 - * Released: January 11, 2021 + * Version: 1.2.0 + * Released: May 17, 2021 * * Updates: - * - Fix the IMAP search termination checking https://github.com/mobizt/ESP-Mail-Client/issues/15. - * - Fix the IMAP startTLS consequence commands + * - Add support ESP8266 Core SDK v3.x.x. * * - * This library allows Espressif's ESP32 and ESP8266 devices to send and read Email + * This library allows Espressif's ESP32 and ESP8266 devices to send and read + * Email * through the SMTP and IMAP servers. * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of + * 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, + * 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 + * 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 + * 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_Mail_Client_H -#define ESP_Mail_Client_H - -#define ESP_MAIL_VERSION "1.0.8" - #include #include "extras/RFC2047.h" #include "extras/ESPTimeHelper.h" #if defined(ESP32) +#define FORMAT_FLASH FORMAT_FLASH_IF_MOUNT_FAILED #include -#include -#include #include //#include #include #include "wcs/esp32/ESP_Mail_HTTPClient32.h" -#include "extras/ESPTimeHelper.h" #elif defined(ESP8266) #include -#include -#include #define FS_NO_GLOBALS #include -//#include #include "wcs/esp8266/ESP_Mail_HTTPClient.h" #endif @@ -68,7 +70,6 @@ #include #include -#define FORMAT_SPIFFS_IF_FAILED true #if defined(ESP8266) #define SD_CS_PIN 15 #endif @@ -125,8 +126,6 @@ #define ESP_MAIL_MIN_MEM 4000 #endif -extern FS *ufsp; - class IMAPSession; class SMTPSession; class SMTP_Status; @@ -135,69 +134,101 @@ class MessageData; enum esp_mail_smtp_status_code { - esp_mail_smtp_status_code_0, //default + esp_mail_smtp_status_code_0, // default /* Positive Completion */ esp_mail_smtp_status_code_211 = 221, // System status, or system help reply - esp_mail_smtp_status_code_214 = 214, //Help message(A response to the HELP command) + esp_mail_smtp_status_code_214 = + 214, // Help message(A response to the HELP command) esp_mail_smtp_status_code_220 = 220, // Service ready - esp_mail_smtp_status_code_221 = 221, // Service closing transmission channel [RFC 2034] - esp_mail_smtp_status_code_235 = 235, //2.7.0 Authentication succeeded[RFC 4954] - esp_mail_smtp_status_code_250 = 250, //Requested mail action okay, completed - esp_mail_smtp_status_code_251 = 251, //User not local; will forward - esp_mail_smtp_status_code_252 = 252, //Cannot verify the user, but it will try to deliver the message anyway + esp_mail_smtp_status_code_221 = + 221, // Service closing transmission channel [RFC 2034] + esp_mail_smtp_status_code_235 = + 235, // 2.7.0 Authentication succeeded[RFC 4954] + esp_mail_smtp_status_code_250 = 250, // Requested mail action okay, completed + esp_mail_smtp_status_code_251 = 251, // User not local; will forward + esp_mail_smtp_status_code_252 = 252, // Cannot verify the user, but it will + // try to deliver the message anyway /* Positive Intermediate */ - esp_mail_smtp_status_code_334 = 334, //(Server challenge - the text part contains the Base64 - encoded challenge)[RFC 4954] - esp_mail_smtp_status_code_354 = 354, //Start mail input + esp_mail_smtp_status_code_334 = 334, //(Server challenge - the text part + //contains the Base64 - encoded + //challenge)[RFC 4954] + esp_mail_smtp_status_code_354 = 354, // Start mail input /* Transient Negative Completion */ - /* "Transient Negative" means the error condition is temporary, and the action may be requested again.*/ - esp_mail_smtp_status_code_421 = 421, //Service is unavailable because the server is shutting down. - esp_mail_smtp_status_code_432 = 432, //4.7.12 A password transition is needed [RFC 4954] - esp_mail_smtp_status_code_450 = 450, //Requested mail action not taken: mailbox unavailable (e.g., mailbox busy or temporarily blocked for policy reasons) - esp_mail_smtp_status_code_451 = 451, //Requested action aborted : local error in processing - //e.g.IMAP server unavailable[RFC 4468] - esp_mail_smtp_status_code_452 = 452, //Requested action not taken : insufficient system storage - esp_mail_smtp_status_code_454 = 454, //4.7.0 Temporary authentication failure[RFC 4954] - esp_mail_smtp_status_code_455 = 455, //Server unable to accommodate parameters + /* "Transient Negative" means the error condition is temporary, and the action + may be requested again.*/ + esp_mail_smtp_status_code_421 = + 421, // Service is unavailable because the server is shutting down. + esp_mail_smtp_status_code_432 = + 432, // 4.7.12 A password transition is needed [RFC 4954] + esp_mail_smtp_status_code_450 = + 450, // Requested mail action not taken: mailbox unavailable (e.g., + // mailbox busy or temporarily blocked for policy reasons) + esp_mail_smtp_status_code_451 = + 451, // Requested action aborted : local error in processing + // e.g.IMAP server unavailable[RFC 4468] + esp_mail_smtp_status_code_452 = + 452, // Requested action not taken : insufficient system storage + esp_mail_smtp_status_code_454 = + 454, // 4.7.0 Temporary authentication failure[RFC 4954] + esp_mail_smtp_status_code_455 = + 455, // Server unable to accommodate parameters /* Permanent Negative Completion */ - esp_mail_smtp_status_code_500 = 500, //Syntax error, command unrecognized (This may include errors such as command line too long) - //e.g. Authentication Exchange line is too long [RFC 4954] - esp_mail_smtp_status_code_501 = 501, //Syntax error in parameters or arguments - //e.g. 5.5.2 Cannot Base64-decode Client responses [RFC 4954] - //5.7.0 Client initiated Authentication Exchange (only when the SASL mechanism specified that client does not begin the authentication exchange) [RFC 4954] - esp_mail_smtp_status_code_502 = 502, //Command not implemented - esp_mail_smtp_status_code_503 = 503, //Bad sequence of commands - esp_mail_smtp_status_code_504 = 504, //Command parameter is not implemented - //e.g. 5.5.4 Unrecognized authentication type [RFC 4954] - esp_mail_smtp_status_code_521 = 521, //Server does not accept mail [RFC 7504] - esp_mail_smtp_status_code_523 = 523, //Encryption Needed [RFC 5248] - esp_mail_smtp_status_code_530 = 530, //5.7.0 Authentication required [RFC 4954] - esp_mail_smtp_status_code_534 = 534, //5.7.9 Authentication mechanism is too weak [RFC 4954] - esp_mail_smtp_status_code_535 = 535, //5.7.8 Authentication credentials invalid [RFC 4954] - esp_mail_smtp_status_code_538 = 538, //5.7.11 Encryption required for requested authentication mechanism[RFC 4954] - esp_mail_smtp_status_code_550 = 550, //Requested action not taken: mailbox unavailable (e.g., mailbox not found, no access, or command rejected for policy reasons) - esp_mail_smtp_status_code_551 = 551, //User not local; please try - esp_mail_smtp_status_code_552 = 552, //Requested mail action aborted: exceeded storage allocation - esp_mail_smtp_status_code_553 = 553, //Requested action not taken: mailbox name not allowed - esp_mail_smtp_status_code_554 = 554, //Transaction has failed (Or, in the case of a connection-opening response, "No SMTP service here") - //e.g. 5.3.4 Message too big for system [RFC 4468] - esp_mail_smtp_status_code_556 = 556, //Domain does not accept mail[RFC 7504] + esp_mail_smtp_status_code_500 = 500, // Syntax error, command unrecognized + // (This may include errors such as + // command line too long) + // e.g. Authentication Exchange line is too long [RFC 4954] + esp_mail_smtp_status_code_501 = + 501, // Syntax error in parameters or arguments + // e.g. 5.5.2 Cannot Base64-decode Client responses [RFC 4954] + // 5.7.0 Client initiated Authentication Exchange (only when the SASL + // mechanism specified that client does not begin the authentication exchange) + // [RFC 4954] + esp_mail_smtp_status_code_502 = 502, // Command not implemented + esp_mail_smtp_status_code_503 = 503, // Bad sequence of commands + esp_mail_smtp_status_code_504 = 504, // Command parameter is not implemented + // e.g. 5.5.4 Unrecognized authentication type [RFC 4954] + esp_mail_smtp_status_code_521 = 521, // Server does not accept mail [RFC 7504] + esp_mail_smtp_status_code_523 = 523, // Encryption Needed [RFC 5248] + esp_mail_smtp_status_code_530 = + 530, // 5.7.0 Authentication required [RFC 4954] + esp_mail_smtp_status_code_534 = + 534, // 5.7.9 Authentication mechanism is too weak [RFC 4954] + esp_mail_smtp_status_code_535 = + 535, // 5.7.8 Authentication credentials invalid [RFC 4954] + esp_mail_smtp_status_code_538 = 538, // 5.7.11 Encryption required for + // requested authentication mechanism[RFC + // 4954] + esp_mail_smtp_status_code_550 = + 550, // Requested action not taken: mailbox unavailable (e.g., mailbox not + // found, no access, or command rejected for policy reasons) + esp_mail_smtp_status_code_551 = + 551, // User not local; please try + esp_mail_smtp_status_code_552 = + 552, // Requested mail action aborted: exceeded storage allocation + esp_mail_smtp_status_code_553 = + 553, // Requested action not taken: mailbox name not allowed + esp_mail_smtp_status_code_554 = 554, // Transaction has failed (Or, in the + // case of a connection-opening response, + // "No SMTP service here") + // e.g. 5.3.4 Message too big for system [RFC 4468] + esp_mail_smtp_status_code_556 = 556, // Domain does not accept mail[RFC 7504] }; enum esp_mail_smtp_port { - esp_mail_smtp_port_25 = 25, //PLAIN/TLS with STARTTLS - esp_mail_smtp_port_465 = 465, //SSL - esp_mail_smtp_port_587 = 587 //TLS with STARTTLS + esp_mail_smtp_port_25 = 25, // PLAIN/TLS with STARTTLS + esp_mail_smtp_port_465 = 465, // SSL + esp_mail_smtp_port_587 = 587 // TLS with STARTTLS }; enum esp_mail_imap_port { - esp_mail_imap_port_143 = 143, //PLAIN/TLS with STARTTLS - esp_mail_imap_port_993 = 993, //SSL + esp_mail_imap_port_143 = 143, // PLAIN/TLS with STARTTLS + esp_mail_imap_port_993 = 993, // SSL }; enum esp_mail_smtp_notify @@ -375,7 +406,8 @@ struct esp_mail_imap_descrete_media_type_t * "plain" * "enriched" (rfc 1896 revised from richtext in rfc 1341) * - * unrecognized subtypes and charset should be interpreted as application/octet-stream + * unrecognized subtypes and charset should be interpreted as + * application/octet-stream * * parameters: * "charset" (rfc 2045) default is us-ascii @@ -496,10 +528,12 @@ struct esp_mail_imap_multipart_sub_type_t /* parts intended to be viewed simultaneously */ static constexpr const char *parallel = "parallel"; - /* multipart entities in which each part has a default type of "message/rfc822" */ + /* multipart entities in which each part has a default type of + * "message/rfc822" */ static constexpr const char *digest = "digest"; - /* for compound objects consisting of several inter-related body parts (rfc 2387) */ + /* for compound objects consisting of several inter-related body parts (rfc + * 2387) */ static constexpr const char *related = "related"; /* rfc 3462 */ @@ -509,10 +543,12 @@ struct esp_mail_imap_multipart_sub_type_t /* message body sub types */ struct esp_mail_imap_message_sub_type_t { - /* body contains an encapsulated message, with the syntax of an RFC 822 message. */ + /* body contains an encapsulated message, with the syntax of an RFC 822 + * message. */ static constexpr const char *rfc822 = "rfc822"; - /* to allow large objects to be delivered as several separate pieces of mail */ + /* to allow large objects to be delivered as several separate pieces of mail + */ static constexpr const char *Partial = "Partial"; /* the actual body data are not included, but merely referenced */ @@ -561,7 +597,8 @@ struct esp_mail_content_transfer_encoding_t /* The 8-bit transfer encoding for extended-US-ASCII characters*/ static constexpr const char *enc_8bit = "8bit"; - /* The binary transfer encoding for extended-US-ASCII characters with no line length limit*/ + /* The binary transfer encoding for extended-US-ASCII characters with no line + * length limit*/ static constexpr const char *enc_binary = "binary"; }; @@ -591,18 +628,47 @@ struct esp_mail_smtp_embed_message_body_t * esp_mail_smtp_embed_message_type_attachment or 0 * esp_mail_smtp_embed_message_type_inline or 1 */ - esp_mail_smtp_embed_message_type type = esp_mail_smtp_embed_message_type_attachment; + esp_mail_smtp_embed_message_type type = + esp_mail_smtp_embed_message_type_attachment; +}; + +struct esp_mail_file_message_content_t +{ + /* The file path include its name */ + const char *name = ""; + + /** The type of file storages e.g. + * esp_mail_file_storage_type_none, + * esp_mail_file_storage_type_flash, and + * esp_mail_file_storage_type_sd + */ + esp_mail_file_storage_type type = esp_mail_file_storage_type_flash; +}; + +struct esp_mail_blob_message_content_t +{ + /* The array of content in flash memory */ + const uint8_t *data = nullptr; + + /* The array size in bytes */ + size_t size = 0; }; /* The PLAIN text body details of the message */ struct esp_mail_plain_body_t { /* The option to embed this message content as a file */ - esp_mail_smtp_embed_message_body_t embed; + struct esp_mail_smtp_embed_message_body_t embed; /* The PLAIN text content of the message */ const char *content = ""; + /* The blob that contins PLAIN text content of the message */ + struct esp_mail_blob_message_content_t blob; + + /* The file that contins PLAIN text content of the message */ + struct esp_mail_file_message_content_t file; + /* The charset of the PLAIN text content of the message */ const char *charSet = "UTF-8"; @@ -616,17 +682,23 @@ struct esp_mail_plain_body_t bool flowed = false; /* The internal usage data */ - esp_mail_internal_use_t _int; + struct esp_mail_internal_use_t _int; }; struct esp_mail_html_body_t { /* The option to embedded the content as a file */ - esp_mail_smtp_embed_message_body_t embed; + struct esp_mail_smtp_embed_message_body_t embed; /* The HTML content of the message */ const char *content = ""; + /* The blob that contins HTML content of the message */ + struct esp_mail_blob_message_content_t blob; + + /* The file that contins HTML content of the message */ + struct esp_mail_file_message_content_t file; + /* The charset of the HTML content of the message */ const char *charSet = "UTF-8"; @@ -637,7 +709,7 @@ struct esp_mail_html_body_t const char *transfer_encoding = "7bit"; /* The internal usage data */ - esp_mail_internal_use_t _int; + struct esp_mail_internal_use_t _int; }; struct esp_mail_link_internal_t @@ -705,11 +777,14 @@ struct esp_mail_attach_descr_t /* The MIME type of attachment */ const char *mime = ""; - /* The transfer encoding of attachnent e.g. base64 */ + /* The transfer encoding of attachment e.g. base64 */ const char *transfer_encoding = "base64"; - /* The cntent encoding of attachnent e.g. base64 */ + /* The content encoding of attachment e.g. base64 */ const char *content_encoding = ""; + + /* The content id of attachment file */ + const char *content_id = ""; }; struct esp_mail_attach_internal_t @@ -735,7 +810,7 @@ struct esp_mail_attachment_t struct esp_mail_attach_file_t file; /* reserved for internal usage */ - esp_mail_attach_internal_t _int; + struct esp_mail_attach_internal_t _int; }; struct esp_mail_smtp_recipient_t @@ -841,8 +916,10 @@ struct esp_mail_message_part_info_t esp_mail_message_type msg_type = esp_mail_msg_type_none; bool file_open_write = false; bool multipart = false; - esp_mail_imap_multipart_sub_type multipart_sub_type = esp_mail_imap_multipart_sub_type_none; - esp_mail_imap_message_sub_type message_sub_type = esp_mail_imap_message_sub_type_none; + esp_mail_imap_multipart_sub_type multipart_sub_type = + esp_mail_imap_multipart_sub_type_none; + esp_mail_imap_message_sub_type message_sub_type = + esp_mail_imap_message_sub_type_none; bool rfc822_part = false; int rfc822_msg_Idx = 0; struct esp_mail_imap_rfc822_msg_header_item_t rfc822_header; @@ -873,8 +950,10 @@ struct esp_mail_message_header_t int rfc822Idx = 0; std::string partNumStr = ""; - esp_mail_imap_multipart_sub_type multipart_sub_type = esp_mail_imap_multipart_sub_type_none; - esp_mail_imap_message_sub_type message_sub_type = esp_mail_imap_message_sub_type_none; + esp_mail_imap_multipart_sub_type multipart_sub_type = + esp_mail_imap_multipart_sub_type_none; + esp_mail_imap_message_sub_type message_sub_type = + esp_mail_imap_message_sub_type_none; std::string from_charset = ""; std::string to_charset = ""; std::string cc_charset = ""; @@ -882,7 +961,8 @@ struct esp_mail_message_header_t std::string msgID = ""; std::string error_msg = ""; bool error = false; - std::vector part_headers = std::vector(); + std::vector part_headers = + std::vector(); int attachment_count = 0; int total_download_size = 0; int downloaded_size = 0; @@ -1119,10 +1199,10 @@ struct esp_mail_imap_msg_item_t const char *subjectCharset = ""; /* The PLAIN text content of the message */ - esp_mail_plain_body_t text; + struct esp_mail_plain_body_t text; /* The HTML content of the message */ - esp_mail_html_body_t html; + struct esp_mail_html_body_t html; /* rfc822 related */ @@ -1151,16 +1231,19 @@ struct esp_mail_imap_msg_item_t const char *fetchError = ""; /* The info about the attachments in the message */ - std::vector attachments = std::vector(); + std::vector attachments = + std::vector(); /* The info about the rfc822 messages included in the message */ - std::vector rfc822 = std::vector(); + std::vector rfc822 = + std::vector(); }; struct esp_mail_imap_msg_list_t { /* The info of a message */ - std::vector msgItems = std::vector(); + std::vector msgItems = + std::vector(); }; struct esp_mail_smtp_msg_type_t @@ -1187,13 +1270,15 @@ typedef struct esp_mail_content_transfer_encoding_t Content_Transfer_Encoding; /* The result from sending the Email */ typedef struct esp_mail_smtp_send_status_t SMTP_Result; -/* The attachment item details for a message which returned from fetching the Email */ +/* The attachment item details for a message which returned from fetching the + * Email */ typedef struct esp_mail_attacment_info_t IMAP_Attach_Item; /* The attachment details for sending the Email */ typedef struct esp_mail_attachment_t SMTP_Attachment; -/* The info of the selected or open mailbox folder e.g. name, attributes and delimiter */ +/* The info of the selected or open mailbox folder e.g. name, attributes and + * delimiter */ typedef struct esp_mail_folder_info_item_t FolderInfo; /* The session configuations */ @@ -1202,13 +1287,16 @@ typedef struct esp_mail_session_config_t ESP_Mail_Session; /** The IMAP operation configuations */ typedef struct esp_mail_imap_read_config_t IMAP_Config; -/* The message item data of the IMAP_MSG_List which contains header, body and attachments info for eacch message*/ +/* The message item data of the IMAP_MSG_List which contains header, body and + * attachments info for eacch message*/ typedef struct esp_mail_imap_msg_item_t IMAP_MSG_Item; -/* The list that contains the message items from searching or fetching the Email */ +/* The list that contains the message items from searching or fetching the Email + */ typedef struct esp_mail_imap_msg_list_t IMAP_MSG_List; -static const char esp_mail_str_1[] PROGMEM = "Content-Type: multipart/mixed; boundary=\""; +static const char esp_mail_str_1[] PROGMEM = + "Content-Type: multipart/mixed; boundary=\""; static const char esp_mail_str_2[] PROGMEM = "$ CAPABILITY"; static const char esp_mail_str_3[] PROGMEM = "Mime-Version: 1.0\r\n"; static const char esp_mail_str_4[] PROGMEM = "AUTH LOGIN"; @@ -1235,9 +1323,11 @@ static const char esp_mail_str_24[] PROGMEM = "Subject: "; static const char esp_mail_str_25[] PROGMEM = "Content-Type: "; static const char esp_mail_str_26[] PROGMEM = "; Name=\""; static const char esp_mail_str_27[] PROGMEM = "$"; -static const char esp_mail_str_28[] PROGMEM = "Content-Type: multipart/parallel; boundary=\""; +static const char esp_mail_str_28[] PROGMEM = + "Content-Type: multipart/parallel; boundary=\""; static const char esp_mail_str_29[] PROGMEM = "7bit"; -static const char esp_mail_str_30[] PROGMEM = "Content-Disposition: attachment; filename=\""; +static const char esp_mail_str_30[] PROGMEM = + "Content-Disposition: attachment; filename=\""; static const char esp_mail_str_31[] PROGMEM = "base64"; static const char esp_mail_str_32[] PROGMEM = "application/octet-stream"; static const char esp_mail_str_33[] PROGMEM = "--"; @@ -1249,7 +1339,8 @@ static const char esp_mail_str_38[] PROGMEM = "unable to connect to server"; static const char esp_mail_str_39[] PROGMEM = "SMTP server greeting failed"; static const char esp_mail_str_40[] PROGMEM = ".dat"; static const char esp_mail_str_41[] PROGMEM = "$ AUTHENTICATE PLAIN "; -static const char esp_mail_str_42[] PROGMEM = "the provided SASL authentication mechanism is not support"; +static const char esp_mail_str_42[] PROGMEM = + "the provided SASL authentication mechanism is not support"; static const char esp_mail_str_43[] PROGMEM = "authentication failed"; static const char esp_mail_str_44[] PROGMEM = "mydomain.com"; static const char esp_mail_str_45[] PROGMEM = "AUTH PLAIN"; @@ -1258,15 +1349,19 @@ static const char esp_mail_str_47[] PROGMEM = "login password is not valid"; static const char esp_mail_str_48[] PROGMEM = "send header failed"; static const char esp_mail_str_49[] PROGMEM = "send body failed"; static const char esp_mail_str_50[] PROGMEM = "Connecting to IMAP server..."; -static const char esp_mail_str_51[] PROGMEM = ".HEADER.FIELDS (SUBJECT FROM SENDER RETURN-PATH TO REPLY-TO DATE CC Message-ID COMMENT KEYWORD content-type Content-transfer-encoding)]"; +static const char esp_mail_str_51[] PROGMEM = + ".HEADER.FIELDS (SUBJECT FROM SENDER RETURN-PATH TO REPLY-TO DATE CC " + "Message-ID COMMENT KEYWORD content-type Content-transfer-encoding)]"; static const char esp_mail_str_52[] PROGMEM = "failed"; static const char esp_mail_str_53[] PROGMEM = "Error, "; static const char esp_mail_str_54[] PROGMEM = "IMAP server connected"; static const char esp_mail_str_55[] PROGMEM = "> C: download attachment"; static const char esp_mail_str_56[] PROGMEM = "Logging in..."; static const char esp_mail_str_57[] PROGMEM = "Downloading messages..."; -static const char esp_mail_str_58[] PROGMEM = "Reading the list of mailboxes..."; -static const char esp_mail_str_59[] PROGMEM = "> C: download plain TEXT message"; +static const char esp_mail_str_58[] PROGMEM = + "Reading the list of mailboxes..."; +static const char esp_mail_str_59[] PROGMEM = + "> C: download plain TEXT message"; static const char esp_mail_str_60[] PROGMEM = "> C: download HTML message"; static const char esp_mail_str_61[] PROGMEM = "Selecting the "; static const char esp_mail_str_62[] PROGMEM = "fail to list the mailboxes"; @@ -1279,8 +1374,10 @@ static const char esp_mail_str_68[] PROGMEM = "Search limit:"; static const char esp_mail_str_69[] PROGMEM = "Found "; static const char esp_mail_str_70[] PROGMEM = " messages"; static const char esp_mail_str_71[] PROGMEM = "Show "; -static const char esp_mail_str_72[] PROGMEM = "No message found for search criteria"; -static const char esp_mail_str_73[] PROGMEM = "Search criteria does not set, fetch the recent message"; +static const char esp_mail_str_72[] PROGMEM = + "No message found for search criteria"; +static const char esp_mail_str_73[] PROGMEM = + "Search criteria does not set, fetch the recent message"; static const char esp_mail_str_74[] PROGMEM = "Fetching message "; static const char esp_mail_str_75[] PROGMEM = ", UID: "; static const char esp_mail_str_76[] PROGMEM = ", Number: "; @@ -1293,7 +1390,8 @@ static const char esp_mail_str_82[] PROGMEM = "rfc822"; static const char esp_mail_str_83[] PROGMEM = "reading"; static const char esp_mail_str_84[] PROGMEM = "Free Heap: "; static const char esp_mail_str_85[] PROGMEM = "Logging out..."; -static const char esp_mail_str_86[] PROGMEM = "> C: fetch body sub part header, "; +static const char esp_mail_str_86[] PROGMEM = + "> C: fetch body sub part header, "; static const char esp_mail_str_87[] PROGMEM = "Finished reading Email"; static const char esp_mail_str_88[] PROGMEM = "> C: finished reading Email"; static const char esp_mail_str_89[] PROGMEM = "SD card mount failed"; @@ -1305,7 +1403,8 @@ static const char esp_mail_str_94[] PROGMEM = ".html"; static const char esp_mail_str_95[] PROGMEM = ".txt"; static const char esp_mail_str_96[] PROGMEM = " folder..."; static const char esp_mail_str_97[] PROGMEM = ";"; -static const char esp_mail_str_98[] PROGMEM = "Content-Disposition: attachment\r\n"; +static const char esp_mail_str_98[] PROGMEM = + "Content-Disposition: attachment\r\n"; static const char esp_mail_str_99[] PROGMEM = "Date: "; static const char esp_mail_str_100[] PROGMEM = "Messsage UID: "; static const char esp_mail_str_101[] PROGMEM = "Messsage ID: "; @@ -1328,10 +1427,12 @@ static const char esp_mail_str_117[] PROGMEM = "Size: "; static const char esp_mail_str_118[] PROGMEM = "Type: "; static const char esp_mail_str_119[] PROGMEM = "Creation Date: "; static const char esp_mail_str_120[] PROGMEM = "Connecting to SMTP server..."; -static const char esp_mail_str_121[] PROGMEM = "SMTP server connected, wait for greeting..."; +static const char esp_mail_str_121[] PROGMEM = + "SMTP server connected, wait for greeting..."; static const char esp_mail_str_122[] PROGMEM = "Sending greeting response..."; static const char esp_mail_str_123[] PROGMEM = "message/rfc822"; -static const char esp_mail_str_124[] PROGMEM = "Saving message header to file..."; +static const char esp_mail_str_124[] PROGMEM = + "Saving message header to file..."; static const char esp_mail_str_125[] PROGMEM = "Sending message header..."; static const char esp_mail_str_126[] PROGMEM = "Sending message body..."; static const char esp_mail_str_127[] PROGMEM = "Sending attachments..."; @@ -1339,7 +1440,8 @@ static const char esp_mail_str_128[] PROGMEM = "Closing the session..."; static const char esp_mail_str_129[] PROGMEM = "Message sent successfully"; static const char esp_mail_str_130[] PROGMEM = "$ LOGIN "; static const char esp_mail_str_131[] PROGMEM = " "; -static const char esp_mail_str_132[] PROGMEM = "fail to set up the SSL/TLS structure"; +static const char esp_mail_str_132[] PROGMEM = + "fail to set up the SSL/TLS structure"; static const char esp_mail_str_133[] PROGMEM = "$ LIST \"\" *"; static const char esp_mail_str_134[] PROGMEM = "Comment: "; static const char esp_mail_str_135[] PROGMEM = "$ EXAMINE \""; @@ -1351,7 +1453,9 @@ static const char esp_mail_str_140[] PROGMEM = "UID"; static const char esp_mail_str_141[] PROGMEM = "SEARCH"; static const char esp_mail_str_142[] PROGMEM = "$ UID FETCH "; static const char esp_mail_str_143[] PROGMEM = "$ FETCH "; -static const char esp_mail_str_144[] PROGMEM = "HEADER.FIELDS (SUBJECT FROM TO DATE CC Message-ID Accept-Language content-type Content-transfer-encoding Content-Language)"; +static const char esp_mail_str_144[] PROGMEM = + "HEADER.FIELDS (SUBJECT FROM TO DATE CC Message-ID Accept-Language " + "content-type Content-transfer-encoding Content-Language)"; static const char esp_mail_str_145[] PROGMEM = "Keyword: "; static const char esp_mail_str_146[] PROGMEM = "$ LOGOUT"; static const char esp_mail_str_147[] PROGMEM = " BODY"; @@ -1365,7 +1469,8 @@ static const char esp_mail_str_154[] PROGMEM = "Remove FLAG"; static const char esp_mail_str_155[] PROGMEM = "Add FLAG"; static const char esp_mail_str_156[] PROGMEM = "]"; static const char esp_mail_str_157[] PROGMEM = "Set FLAG"; -static const char esp_mail_str_158[] PROGMEM = "file does not exist or can't access"; +static const char esp_mail_str_158[] PROGMEM = + "file does not exist or can't access"; static const char esp_mail_str_159[] PROGMEM = "msg.html"; static const char esp_mail_str_160[] PROGMEM = "upload "; static const char esp_mail_str_161[] PROGMEM = "/msg"; @@ -1411,8 +1516,10 @@ static const char esp_mail_str_201[] PROGMEM = "port > "; static const char esp_mail_str_202[] PROGMEM = "/"; static const char esp_mail_str_203[] PROGMEM = "/header.txt"; static const char esp_mail_str_204[] PROGMEM = "/esp.32"; -static const char esp_mail_str_205[] PROGMEM = "sender Email address is not valid"; -static const char esp_mail_str_206[] PROGMEM = "some of the recipient Email address is not valid"; +static const char esp_mail_str_205[] PROGMEM = + "sender Email address is not valid"; +static const char esp_mail_str_206[] PROGMEM = + "some of the recipient Email address is not valid"; static const char esp_mail_str_207[] PROGMEM = "> C: send Email"; static const char esp_mail_str_208[] PROGMEM = "Sending Email..."; static const char esp_mail_str_209[] PROGMEM = "Send command, STARTTLS"; @@ -1446,12 +1553,15 @@ static const char esp_mail_str_236[] PROGMEM = "> C: connect to SMTP server"; static const char esp_mail_str_237[] PROGMEM = "tis-620"; static const char esp_mail_str_238[] PROGMEM = "> C: smtp server connected"; static const char esp_mail_str_239[] PROGMEM = "> C: send smtp command, HELO"; -static const char esp_mail_str_240[] PROGMEM = "> C: send smtp command, AUTH LOGIN"; -static const char esp_mail_str_241[] PROGMEM = "> C: send smtp command, AUTH PLAIN"; +static const char esp_mail_str_240[] PROGMEM = + "> C: send smtp command, AUTH LOGIN"; +static const char esp_mail_str_241[] PROGMEM = + "> C: send smtp command, AUTH PLAIN"; static const char esp_mail_str_242[] PROGMEM = "> C: send message header"; static const char esp_mail_str_243[] PROGMEM = "> C: send message body"; static const char esp_mail_str_244[] PROGMEM = "> C: send attachments"; -static const char esp_mail_str_245[] PROGMEM = "> C: terminate the SMTP session"; +static const char esp_mail_str_245[] PROGMEM = + "> C: terminate the SMTP session"; static const char esp_mail_str_246[] PROGMEM = "> C: Message sent successfully"; static const char esp_mail_str_247[] PROGMEM = "$ SELECT \""; static const char esp_mail_str_248[] PROGMEM = "> C: open the mailbox folder"; @@ -1475,7 +1585,8 @@ static const char esp_mail_str_265[] PROGMEM = "FAILURE"; static const char esp_mail_str_266[] PROGMEM = "DELAY"; static const char esp_mail_str_267[] PROGMEM = "Sending next Email..."; static const char esp_mail_str_268[] PROGMEM = "> C: send next Email"; -static const char esp_mail_str_269[] PROGMEM = "header.fields (content-type Content-transfer-encoding)]"; +static const char esp_mail_str_269[] PROGMEM = + "header.fields (content-type Content-transfer-encoding)]"; static const char esp_mail_str_270[] PROGMEM = "format=\"flowed\""; static const char esp_mail_str_271[] PROGMEM = "> C: send inline data"; static const char esp_mail_str_272[] PROGMEM = "Content-transfer-encoding: "; @@ -1490,33 +1601,46 @@ static const char esp_mail_str_280[] PROGMEM = "> C: no content"; static const char esp_mail_str_281[] PROGMEM = "fail to open the mailbox"; static const char esp_mail_str_282[] PROGMEM = "file I/O error"; static const char esp_mail_str_283[] PROGMEM = "time.nist.gov"; -static const char esp_mail_str_284[] PROGMEM = "log in was disabled for this server"; +static const char esp_mail_str_284[] PROGMEM = + "log in was disabled for this server"; static const char esp_mail_str_285[] PROGMEM = "user="; static const char esp_mail_str_286[] PROGMEM = "\1auth=Bearer "; static const char esp_mail_str_287[] PROGMEM = "\1\1"; -static const char esp_mail_str_288[] PROGMEM = "> C: send smtp command, AUTH XOAUTH2"; +static const char esp_mail_str_288[] PROGMEM = + "> C: send smtp command, AUTH XOAUTH2"; static const char esp_mail_str_289[] PROGMEM = "AUTH XOAUTH2 "; -static const char esp_mail_str_290[] PROGMEM = "> C: send imap command, AUTHENTICATE PLAIN"; -static const char esp_mail_str_291[] PROGMEM = "> C: send imap command, AUTH XOAUTH2"; +static const char esp_mail_str_290[] PROGMEM = + "> C: send imap command, AUTHENTICATE PLAIN"; +static const char esp_mail_str_291[] PROGMEM = + "> C: send imap command, AUTH XOAUTH2"; static const char esp_mail_str_292[] PROGMEM = "$ AUTHENTICATE XOAUTH2 "; -static const char esp_mail_str_293[] PROGMEM = "OAuth2.0 log in was disabled for this server"; +static const char esp_mail_str_293[] PROGMEM = + "OAuth2.0 log in was disabled for this server"; static const char esp_mail_str_294[] PROGMEM = "{\"status\":"; static const char esp_mail_str_295[] PROGMEM = "0123456789ABCDEF"; static const char esp_mail_str_296[] PROGMEM = "pool.ntp.org"; -static const char esp_mail_str_297[] PROGMEM = "Content-Type: multipart/alternative; boundary=\""; -static const char esp_mail_str_298[] PROGMEM = "Content-Type: multipart/related; boundary=\""; -static const char esp_mail_str_299[] PROGMEM = "Content-Disposition: inline; filename=\""; +static const char esp_mail_str_297[] PROGMEM = + "Content-Type: multipart/alternative; boundary=\""; +static const char esp_mail_str_298[] PROGMEM = + "Content-Type: multipart/related; boundary=\""; +static const char esp_mail_str_299[] PROGMEM = + "Content-Disposition: inline; filename=\""; static const char esp_mail_str_300[] PROGMEM = "Content-Location: "; static const char esp_mail_str_301[] PROGMEM = "Content-ID: <"; static const char esp_mail_str_302[] PROGMEM = "cid:"; -static const char esp_mail_str_303[] PROGMEM = "Finishing the message sending..."; -static const char esp_mail_str_304[] PROGMEM = "> C: Finish the message sending"; +static const char esp_mail_str_303[] PROGMEM = + "Finishing the message sending..."; +static const char esp_mail_str_304[] PROGMEM = + "> C: Finish the message sending"; static const char esp_mail_str_305[] PROGMEM = "connection failed"; -static const char esp_mail_str_306[] PROGMEM = "some of the requested messages no longer exist"; +static const char esp_mail_str_306[] PROGMEM = + "some of the requested messages no longer exist"; static const char esp_mail_str_307[] PROGMEM = "Reading messages..."; -static const char esp_mail_str_308[] PROGMEM = "> C: reading plain TEXT message"; +static const char esp_mail_str_308[] PROGMEM = + "> C: reading plain TEXT message"; static const char esp_mail_str_309[] PROGMEM = "> C: reading HTML message"; -static const char esp_mail_str_310[] PROGMEM = "> C: performing the SSL handshaking"; +static const char esp_mail_str_310[] PROGMEM = + "> C: performing the SSL/TLS handshake"; static const char esp_mail_str_311[] PROGMEM = "STARTTLS\r\n"; static const char esp_mail_str_312[] PROGMEM = "code: "; static const char esp_mail_str_313[] PROGMEM = ", text: "; @@ -1531,6 +1655,10 @@ static const char esp_mail_str_321[] PROGMEM = "> C: delete folder"; static const char esp_mail_str_322[] PROGMEM = "$ CREATE "; static const char esp_mail_str_323[] PROGMEM = "$ DELETE "; static const char esp_mail_str_324[] PROGMEM = "HEADER.FIELDS"; +static const char esp_mail_str_325[] PROGMEM = "flash content message"; +static const char esp_mail_str_326[] PROGMEM = "file content message"; +static const char esp_mail_str_327[] PROGMEM = "\"; size="; +static const char esp_mail_str_328[] PROGMEM = "0.0.0.0"; static const char esp_mail_smtp_response_1[] PROGMEM = "AUTH "; static const char esp_mail_smtp_response_2[] PROGMEM = " LOGIN"; @@ -1545,11 +1673,11 @@ static const char esp_mail_smtp_response_10[] PROGMEM = "PIPELINING"; static const char esp_mail_smtp_response_11[] PROGMEM = " CRAM-MD5"; static const char esp_mail_smtp_response_12[] PROGMEM = " DIGEST-MD5"; static const char esp_mail_smtp_response_13[] PROGMEM = "DSN"; -//Tagged +// Tagged static const char esp_mail_imap_response_1[] PROGMEM = "$ OK "; static const char esp_mail_imap_response_2[] PROGMEM = "$ NO "; static const char esp_mail_imap_response_3[] PROGMEM = "$ BAD "; -//Untagged +// Untagged static const char esp_mail_imap_response_4[] PROGMEM = "* LIST "; static const char esp_mail_imap_response_5[] PROGMEM = "* FLAGS "; static const char esp_mail_imap_response_6[] PROGMEM = "* SEARCH "; @@ -1591,11 +1719,12 @@ static const char imap_7bit_val12[] PROGMEM = "–"; static const char imap_7bit_key13[] PROGMEM = "=E2=80=94"; static const char imap_7bit_val13[] PROGMEM = "—"; -static const unsigned char b64_index_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char boundary_table[] PROGMEM = "=_abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const unsigned char b64_index_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char boundary_table[] PROGMEM = + "=_abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -__attribute__((used)) static bool -compFunc(uint32_t i, uint32_t j) +__attribute__((used)) static bool compFunc(uint32_t i, uint32_t j) { return (i > j); } @@ -1612,10 +1741,7 @@ public: _list.push_back(uid); } - void clear() - { - _list.clear(); - } + void clear() { _list.clear(); } private: std::vector _list = std::vector(); @@ -1639,7 +1765,8 @@ public: /* Get the predict next message UID */ size_t nextUID() { return _nextUID; }; - /* Get the numbers of messages from search result based on the search criteria */ + /* Get the numbers of messages from search result based on the search criteria + */ size_t searchCount() { return _searchCount; }; /* Get the numbers of messages to be stored in the ressult */ @@ -1654,10 +1781,7 @@ public: } private: - void addFlag(const char *flag) - { - _flags.push_back(flag); - }; + void addFlag(const char *flag) { _flags.push_back(flag); }; void clear() { for (size_t i = 0; i < _flags.size(); i++) @@ -1671,7 +1795,8 @@ private: std::vector _flags = std::vector(); }; -/* The class that provides the list of FolderInfo e.g. name, attributes and delimiter */ +/* The class that provides the list of FolderInfo e.g. name, attributes and + * delimiter */ class FoldersCollection { public: @@ -1681,9 +1806,9 @@ public: ~FoldersCollection() { clear(); }; size_t size() { return _folders.size(); }; - esp_mail_folder_info_item_t info(size_t index) + struct esp_mail_folder_info_item_t info(size_t index) { - esp_mail_folder_info_item_t fd; + struct esp_mail_folder_info_item_t fd; if (index < _folders.size()) { fd.name = _folders[index].name.c_str(); @@ -1694,7 +1819,7 @@ public: } private: - void add(esp_mail_folder_info_t &fd) { _folders.push_back(fd); }; + void add(struct esp_mail_folder_info_t &fd) { _folders.push_back(fd); }; void clear() { for (size_t i = 0; i < _folders.size(); i++) @@ -1708,7 +1833,8 @@ private: } _folders.clear(); } - std::vector _folders = std::vector(); + std::vector _folders = + std::vector(); }; /* The class that provides the status of message feching and searching */ @@ -1744,6 +1870,7 @@ public: att.descr.transfer_encoding = ""; att.descr.content_encoding = ""; att.descr.mime = ""; + att.descr.content_id = ""; att._int.att_type = esp_mail_att_type_none; att._int.index = 0; att._int.msg_uid = 0; @@ -1820,7 +1947,7 @@ public: */ void clearInlineimages() { - for (size_t i = _att.size() - 1; i >= 0; i--) + for (int i = (int)_att.size() - 1; i >= 0; i--) { if (_att[i]._int.att_type == esp_mail_att_type_inline) _att.erase(_att.begin() + i); @@ -1830,13 +1957,13 @@ public: /* Clear all the attachments */ void clearAttachments() { - for (size_t i = _att.size() - 1; i >= 0; i--) + for (int i = (int)_att.size() - 1; i >= 0; i--) { if (_att[i]._int.att_type == esp_mail_att_type_attachment) _att.erase(_att.begin() + i); } - for (size_t i = _parallel.size() - 1; i >= 0; i--) + for (int i = (int)_parallel.size() - 1; i >= 0; i--) _parallel.erase(_parallel.begin() + i); }; @@ -1844,7 +1971,7 @@ public: */ void clearRFC822Messages() { - for (size_t i = _rfc822.size() - 1; i >= 0; i--) + for (int i = (int)_rfc822.size() - 1; i >= 0; i--) { _rfc822[i].clear(); _rfc822.erase(_rfc822.begin() + i); @@ -1912,10 +2039,7 @@ public: * * @param msg The RFC822_Message class object */ - void addMessage(SMTP_Message &msg) - { - _rfc822.push_back(msg); - } + void addMessage(SMTP_Message &msg) { _rfc822.push_back(msg); } /** Add the primary recipient mailbox to the message * @@ -1959,7 +2083,7 @@ public: void addHeader(const char *hdr) { _hdr.push_back(hdr); }; /* The message author config */ - esp_mail_email_info_t sender; + struct esp_mail_email_info_t sender; /* The topic of message */ const char *subject = ""; @@ -1968,22 +2092,23 @@ public: byte type = esp_mail_msg_type_none; /* The PLAIN text message */ - esp_mail_plain_body_t text; + struct esp_mail_plain_body_t text; /* The HTML text message */ - esp_mail_html_body_t html; + struct esp_mail_html_body_t html; /* The response config */ - esp_mail_smtp_msg_response_t response; + struct esp_mail_smtp_msg_response_t response; /* The priority of the message */ - esp_mail_smtp_priority priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal; + esp_mail_smtp_priority priority = + esp_mail_smtp_priority::esp_mail_smtp_priority_normal; /* The enable options */ - esp_mail_smtp_enable_option_t enable; + struct esp_mail_smtp_enable_option_t enable; /* The message from config */ - esp_mail_email_info_t from; + struct esp_mail_email_info_t from; /* The message identifier */ const char *messageID = ""; @@ -2002,9 +2127,12 @@ public: private: friend class ESP_Mail_Client; - std::vector _rcp = std::vector(); - std::vector _cc = std::vector(); - std::vector _bcc = std::vector(); + std::vector _rcp = + std::vector(); + std::vector _cc = + std::vector(); + std::vector _bcc = + std::vector(); std::vector _hdr = std::vector(); std::vector _att = std::vector(); std::vector _parallel = std::vector(); @@ -2041,8 +2169,10 @@ class ESP_Mail_Client public: /** Sending Email through the SMTP server * - * @param smtp The pointer to SMTP session object which holds the data and the TCP client. - * @param msg The pointer to SMTP_Message class which contains the header, body, and attachments. + * @param smtp The pointer to SMTP session object which holds the data and the + * TCP client. + * @param msg The pointer to SMTP_Message class which contains the header, + * body, and attachments. * @param closeSession The option to Close the SMTP session after sent. * @return The boolean value indicates the success of operation. */ @@ -2050,42 +2180,50 @@ public: /** Reading Email through IMAP server. * - * @param imap The pointer to IMAP sesssion object which holds the data and the TCP client. + * @param imap The pointer to IMAP sesssion object which holds the data and + the TCP client. - * @param closeSession The option to close the IMAP session after fetching or searching the Email. + * @param closeSession The option to close the IMAP session after fetching or + searching the Email. * @return The boolean value indicates the success of operation. */ bool readMail(IMAPSession *imap, bool closeSession = true); /** Set the argument to the Flags for the specified message. * - * @param imap The pointer to IMAP session object which holds the data and the TCP client. + * @param imap The pointer to IMAP session object which holds the data and the + * TCP client. * @param msgUID The UID of the message. * @param flags The flag list to set. * @param closeSession The option to close the IMAP session after set flag. * @return The boolean value indicates the success of operation. */ - bool setFlag(IMAPSession *imap, int msgUID, const char *flags, bool closeSession); + bool setFlag(IMAPSession *imap, int msgUID, const char *flags, + bool closeSession); /** Add the argument to the Flags for the specified message. * - * @param imap The pointer to IMAP session object which holds the data and the TCP client. + * @param imap The pointer to IMAP session object which holds the data and the + * TCP client. * @param msgUID The UID of the message. * @param flags The flag list to set. * @param closeSession The option to close the IMAP session after add flag. * @return The boolean value indicates the success of operation. */ - bool addFlag(IMAPSession *imap, int msgUID, const char *flags, bool closeSession); + bool addFlag(IMAPSession *imap, int msgUID, const char *flags, + bool closeSession); /** Remove the argument from the Flags for the specified message. * - * @param imap The pointer to IMAP session object which holds the data and the TCP client. + * @param imap The pointer to IMAP session object which holds the data and the + * TCP client. * @param msgUID The UID of the message that flags to be removed. * @param flags The flag list to remove. * @param closeSession The option to close the IMAP session after remove flag. * @return The boolean value indicates the success of operation. */ - bool removeFlag(IMAPSession *imap, int msgUID, const char *flags, bool closeSession); + bool removeFlag(IMAPSession *imap, int msgUID, const char *flags, + bool closeSession); /** Initialize the SD card with the SPI port. * @@ -2101,7 +2239,17 @@ public: * * @return The boolean value which indicates the success of operation. */ - bool sdBegin(void); + bool sdBegin(); + + /** Initialize the SD_MMC card (ESSP32 only). + * + * @param mountpoint The mounting point. + * @param mode1bit Allow 1 bit data line. + * @param format_if_mount_failed Format SD_MMC card if mount failed. + * @return The boolean value indicates the success of operation. + */ + bool sdMMCBegin(const char *mountpoint = "/sdcard", bool mode1bit = false, bool format_if_mount_failed = false); + ESPTimeHelper Time; @@ -2109,8 +2257,7 @@ private: friend class SMTPSession; friend class IMAPSession; #if defined(ESP8266) - void - setClock(float offset); + void setClock(float offset); #endif RFC2047_Decoder RFC2047Decoder; @@ -2120,6 +2267,9 @@ private: bool _flashOk = false; bool _sdConfigSet = false; uint8_t _sck, _miso, _mosi, _ss; + const char *sd_mmc_mountpoint = ""; + bool sd_mmc_mode1bit = false; + bool sd_mmc_format_if_mount_failed = false; #if defined(ESP8266) bool _clockReady = false; @@ -2130,17 +2280,22 @@ private: unsigned long _lastReconnectMillis = 0; uint16_t _reconnectTimeout = ESP_MAIL_WIFI_RECONNECT_TIMEOUT; - bool _sendMail(SMTPSession *smtp, SMTP_Message *msg, bool closeSession = true); + bool _sendMail(SMTPSession *smtp, SMTP_Message *msg, + bool closeSession = true); + bool ethLinkUp(); bool reconnect(SMTPSession *smtp, unsigned long dataTime = 0); - bool reconnect(IMAPSession *imap, unsigned long dataTime = 0, bool downloadRequestuest = false); + bool reconnect(IMAPSession *imap, unsigned long dataTime = 0, + bool downloadRequestuest = false); void closeTCP(SMTPSession *smtp); void closeTCP(IMAPSession *imap); void getMIME(const char *ext, std::string &mime); void mimeFromFile(const char *name, std::string &mime); #if defined(ESP32) - void setSecure(ESP_Mail_HTTPClient32 &httpClient, ESP_Mail_Session *session, std::shared_ptr caCert); + void setSecure(ESP_Mail_HTTPClient32 &httpClient, ESP_Mail_Session *session, + std::shared_ptr caCert); #elif defined(ESP8266) - void setSecure(ESP_Mail_HTTPClient &httpClient, ESP_Mail_Session *session, std::shared_ptr caCert); + void setSecure(ESP_Mail_HTTPClient &httpClient, ESP_Mail_Session *session, + std::shared_ptr caCert); #endif void delS(char *p); char *newS(size_t len); @@ -2156,7 +2311,8 @@ private: size_t smtpSend(SMTPSession *smtp, const char *data, bool newline = false); size_t smtpSend(SMTPSession *smtp, int data, bool newline = false); size_t smtpSend(SMTPSession *smtp, uint8_t *data, size_t size); - bool getMultipartFechCmd(IMAPSession *imap, int msgIdx, std::string &partText); + bool getMultipartFechCmd(IMAPSession *imap, int msgIdx, + std::string &partText); bool multipartMember(const std::string &part, const std::string &check); bool fetchMultipartBodyHeader(IMAPSession *imap, int msgIdx); bool connected(IMAPSession *imap); @@ -2170,53 +2326,88 @@ private: std::string getBoundary(size_t len); std::string getEncodedToken(IMAPSession *imap); bool imapLogout(IMAPSession *imap); - bool sendParallelAttachments(SMTPSession *smtp, SMTP_Message *msg, const std::string &boundary); - bool sendAttachments(SMTPSession *smtp, SMTP_Message *msg, const std::string &boundary, bool parallel = false); + bool sendParallelAttachments(SMTPSession *smtp, SMTP_Message *msg, + const std::string &boundary); + bool sendAttachments(SMTPSession *smtp, SMTP_Message *msg, + const std::string &boundary, bool parallel = false); - bool sendMSGData(SMTPSession *smtp, SMTP_Message *msg, bool closeSession, bool rfc822MSG); - bool sendRFC822Msg(SMTPSession *smtp, SMTP_Message *msg, const std::string &boundary, bool closeSession, bool rfc822MSG); - void getRFC822MsgEnvelope(SMTPSession *smtp, SMTP_Message *msg, std::string &buf); + bool sendMSGData(SMTPSession *smtp, SMTP_Message *msg, bool closeSession, + bool rfc822MSG); + bool sendRFC822Msg(SMTPSession *smtp, SMTP_Message *msg, + const std::string &boundary, bool closeSession, + bool rfc822MSG); + void getRFC822MsgEnvelope(SMTPSession *smtp, SMTP_Message *msg, + std::string &buf); bool bdat(SMTPSession *smtp, SMTP_Message *msg, int len, bool last); void checkBinaryData(SMTPSession *smtp, SMTP_Message *msg); bool sendBlob(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att); - bool sendFile(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att, File &file); - bool openFileRead(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att, File &file, std::string &s, std::string &buf, const std::string &boundary, bool inlined); - bool sendInline(SMTPSession *smtp, SMTP_Message *msg, const std::string &boundary, byte type); + bool sendFile(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att, + File &file); + bool openFileRead(SMTPSession *smtp, SMTP_Message *msg, SMTP_Attachment *att, + File &file, std::string &s, std::string &buf, + const std::string &boundary, bool inlined); + bool openFileRead2(SMTPSession *smtp, SMTP_Message *msg, File &file, + const char *path, esp_mail_file_storage_type storageType); + bool sendInline(SMTPSession *smtp, SMTP_Message *msg, + const std::string &boundary, byte type); void debugInfoP(PGM_P info); - size_t numAtt(SMTPSession *smtp, esp_mail_attach_type type, SMTP_Message *msg); + size_t numAtt(SMTPSession *smtp, esp_mail_attach_type type, + SMTP_Message *msg); bool validEmail(const char *s); bool checkEmail(SMTPSession *smtp, SMTP_Message *msg); - bool sendPartText(SMTPSession *smtp, SMTP_Message *msg, byte type, const char *boundary); + bool sendPartText(SMTPSession *smtp, SMTP_Message *msg, byte type, + const char *boundary); char *getUID(); - void encodingText(SMTPSession *smtp, SMTP_Message *msg, uint8_t type, std::string &content); - void splitTk(std::string &str, std::vector &tk, const char *delim); + bool sendBlobBody(SMTPSession *smtp, SMTP_Message *msg, uint8_t type); + bool sendFileBody(SMTPSession *smtp, SMTP_Message *msg, uint8_t type); + void encodingText(SMTPSession *smtp, SMTP_Message *msg, uint8_t type, + std::string &content); + void splitTk(std::string &str, std::vector &tk, + const char *delim); void formatFlowedText(std::string &content); void softBreak(std::string &content, const char *quoteMarks); - bool sendMSG(SMTPSession *smtp, SMTP_Message *msg, const std::string &boundary); - void getAttachHeader(std::string &header, const std::string &boundary, SMTP_Attachment *attach); - void getRFC822PartHeader(SMTPSession *smtp, std::string &header, const std::string &boundary); - void getInlineHeader(std::string &header, const std::string &boundary, SMTP_Attachment *inlineAttach); - unsigned char *decodeBase64(const unsigned char *src, size_t len, size_t *out_len); + bool sendMSG(SMTPSession *smtp, SMTP_Message *msg, + const std::string &boundary); + void getAttachHeader(std::string &header, const std::string &boundary, + SMTP_Attachment *attach, size_t size); + void getRFC822PartHeader(SMTPSession *smtp, std::string &header, + const std::string &boundary); + void getInlineHeader(std::string &header, const std::string &boundary, + SMTP_Attachment *inlineAttach, size_t size); + unsigned char *decodeBase64(const unsigned char *src, size_t len, + size_t *out_len); std::string encodeBase64Str(const unsigned char *src, size_t len); std::string encodeBase64Str(uint8_t *src, size_t len); void encodeQP(const char *buf, char *out); - bool sendBase64(SMTPSession *smtp, SMTP_Message *msg, const unsigned char *data, size_t len, bool flashMem, const char *filename, bool report); - bool sendBase64Stream(SMTPSession *smtp, SMTP_Message *msg, File file, const char *filename, bool report); + bool sendBase64(SMTPSession *smtp, SMTP_Message *msg, + const unsigned char *data, size_t len, bool flashMem, + const char *filename, bool report); + bool sendBase64Stream(SMTPSession *smtp, SMTP_Message *msg, File file, + const char *filename, bool report); void smtpCBP(SMTPSession *smtp, PGM_P info, bool success = false); void smtpCB(SMTPSession *smtp, const char *info, bool success = false); void imapCBP(IMAPSession *imap, PGM_P info, bool success); void imapCB(IMAPSession *imap, const char *info, bool success); - int readLine(WiFiClient *stream, char *buf, int bufLen, bool crlf, int &count); + int readLine(WiFiClient *stream, char *buf, int bufLen, bool crlf, + int &count); #if defined(ESP32) - int _readLine(ESP_Mail_WCS32 *stream, char *buf, int bufLen, bool crlf, int &count); + int _readLine(ESP_Mail_WCS32 *stream, char *buf, int bufLen, bool crlf, + int &count); #elif defined(ESP8266) - int _readLine(ESP_Mail::ESP_Mail_WCS *stream, char *buf, int bufLen, bool crlf, int &count); + int _readLine(ESP_Mail::ESP_Mail_WCS *stream, char *buf, int bufLen, + bool crlf, int &count); #endif - int getMSGNUM(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, bool &endSearch, int &nump, const char *key, const char *pc); - void handleHeader(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, struct esp_mail_message_header_t &header, int &headerState, int &octetCount); - void setHeader(IMAPSession *imap, char *buf, struct esp_mail_message_header_t &header, int state); - void handlePartHeader(IMAPSession *imap, char *buf, int &chunkIdx, struct esp_mail_message_part_info_t &part); - char *subStr(const char *buf, PGM_P beginH, PGM_P endH, int beginPos, int endPos = 0); + int getMSGNUM(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, + bool &endSearch, int &nump, const char *key, const char *pc); + void handleHeader(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, + struct esp_mail_message_header_t &header, int &headerState, + int &octetCount); + void setHeader(IMAPSession *imap, char *buf, + struct esp_mail_message_header_t &header, int state); + void handlePartHeader(IMAPSession *imap, char *buf, int &chunkIdx, + struct esp_mail_message_part_info_t &part); + char *subStr(const char *buf, PGM_P beginH, PGM_P endH, int beginPos, + int endPos = 0); struct esp_mail_message_part_info_t *cPart(IMAPSession *imap); struct esp_mail_message_header_t *cHeader(IMAPSession *imap); void strcat_c(char *str, char c); @@ -2224,14 +2415,17 @@ private: char *stristr(const char *str1, const char *str2); char *rstrstr(const char *haystack, const char *needle); int rstrpos(const char *haystack, const char *needle, int offset); - void getResponseStatus(const char *buf, esp_mail_smtp_status_code respCode, int beginPos, struct esp_mail_smtp_response_status_t &status); + void getResponseStatus(const char *buf, esp_mail_smtp_status_code respCode, + int beginPos, + struct esp_mail_smtp_response_status_t &status); void handleAuth(SMTPSession *smtp, char *buf); std::string getEncodedToken(SMTPSession *smtp); bool connected(SMTPSession *smtp); bool setSendingResult(SMTPSession *smtp, SMTP_Message *msg, bool result); bool smtpAuth(SMTPSession *smtp); int available(SMTPSession *smtp); - bool handleSMTPResponse(SMTPSession *smtp, esp_mail_smtp_status_code respCode, int errCode); + bool handleSMTPResponse(SMTPSession *smtp, esp_mail_smtp_status_code respCode, + int errCode); int available(IMAPSession *imap); bool handleIMAPResponse(IMAPSession *imap, int errCode, bool closeSession); void downloadReport(IMAPSession *imap, int progress); @@ -2240,14 +2434,22 @@ private: void uploadReport(const char *filename, int progress); int cMSG(IMAPSession *imap); int cIdx(IMAPSession *imap); - esp_mail_imap_response_status imapResponseStatus(IMAPSession *imap, char *response); + esp_mail_imap_response_status imapResponseStatus(IMAPSession *imap, + char *response); void saveHeader(IMAPSession *imap); esp_mail_char_decoding_scheme getEncodingFromCharset(const char *enc); void decodeHeader(std::string &headerField, std::string &headerEnc); - bool handleAttachment(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, File &file, std::string &filePath, bool &downloadRequest, int &octetCount, int &octetLength, int &oCount, int &reportState, int &downloadCount); - int decodeLatin1_UTF8(unsigned char *out, int *outlen, const unsigned char *in, int *inlen); + bool handleAttachment(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, + File &file, std::string &filePath, + bool &downloadRequest, int &octetCount, + int &octetLength, int &oCount, int &reportState, + int &downloadCount); + int decodeLatin1_UTF8(unsigned char *out, int *outlen, + const unsigned char *in, int *inlen); void decodeTIS620_UTF8(char *out, const char *in, size_t len); - void decodeText(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, File &file, std::string &filePath, bool &downloadRequest, int &octetLength, int &readDataLen, int &readCount); + void decodeText(IMAPSession *imap, char *buf, int bufLen, int &chunkIdx, + File &file, std::string &filePath, bool &downloadRequest, + int &octetLength, int &readDataLen, int &readCount); void prepareFilePath(IMAPSession *imap, std::string &filePath, bool header); int decodeChar(const char *s); void decodeQP(const char *buf, char *out); @@ -2259,7 +2461,8 @@ private: void handleCapability(IMAPSession *imap, char *buf, int &chunkIdx); void handleExamine(IMAPSession *imap, char *buf); bool handleIMAPError(IMAPSession *imap, int err, bool ret); - bool _setFlag(IMAPSession *imap, int msgUID, const char *flags, uint8_t action, bool closeSession); + bool _setFlag(IMAPSession *imap, int msgUID, const char *flags, + uint8_t action, bool closeSession); void createDirs(std::string dirs); bool sdTest(); }; @@ -2272,8 +2475,10 @@ public: /** Begin the IMAP server connection. * - * @param session The pointer to ESP_Mail_Session structured data that keeps the server and log in details. - * @param config The pointer to IMAP_Config structured data that keeps the operation options. + * @param session The pointer to ESP_Mail_Session structured data that keeps + * the server and log in details. + * @param config The pointer to IMAP_Config structured data that keeps the + * operation options. * @return The boolean value which indicates the success of operation. */ bool connect(ESP_Mail_Session *session, IMAP_Config *config); @@ -2294,9 +2499,11 @@ public: */ void debug(int level); - /** Get the list of all the mailbox folders since the TCP session was opened and user was authenticated. + /** Get the list of all the mailbox folders since the TCP session was opened + * and user was authenticated. * - * @param folders The FoldersCollection class that contains the collection of the + * @param folders The FoldersCollection class that contains the collection of + * the * FolderInfo structured data. * @return The boolean value which indicates the success of operation. */ @@ -2305,7 +2512,8 @@ public: /** Select or open the mailbox folder to search or fetch the message inside. * * @param folderName The known mailbox folder name. The default name is INBOX. - * @param readOnly The option to open the mailbox for read only. Set this option to false when you wish + * @param readOnly The option to open the mailbox for read only. Set this + * option to false when you wish * to modify the Flags using the setFlag, addFlag and removeFlag functions. * @return The boolean value which indicates the success of operation. */ @@ -2314,7 +2522,8 @@ public: /** Open the mailbox folder to read or search the mesages. * * @param folderName The name of known mailbox folder to be opened. - * @param readOnly The option to open the mailbox for reading only. Set this option to false when you wish + * @param readOnly The option to open the mailbox for reading only. Set this + * option to false when you wish * to modify the flags using the setFlag, addFlag and removeFlag functions. * @return The boolean value which indicates the success of operation. */ @@ -2343,40 +2552,48 @@ public: /** Copy the messages to the defined mailbox folder. * - * @param toCopy The pointer to the MessageListList class that contains the list of messages to copy. + * @param toCopy The pointer to the MessageListList class that contains the + * list of messages to copy. * @param dest The destination folder that the messages to copy to. * @return The boolean value which indicates the success of operation. */ - bool copyMessages(MessageList *toCopy, const char* dest); + bool copyMessages(MessageList *toCopy, const char *dest); /** Delete the messages in the opened mailbox folder. * - * @param toDelete The pointer to the MessageListList class that contains the list of messages to delete. + * @param toDelete The pointer to the MessageListList class that contains the + * list of messages to delete. * @param expunge The boolean option to expunge all messages. * @return The boolean value which indicates the success of operation. */ bool deleteMessages(MessageList *toDelete, bool expunge = false); - /** Assign the callback function that returns the operating status when fetching or reading the Email. + /** Assign the callback function that returns the operating status when + * fetching or reading the Email. * - * @param imapCallback The function that accepts the imapStatusCallback as parameter. + * @param imapCallback The function that accepts the imapStatusCallback as + * parameter. */ void callback(imapStatusCallback imapCallback); - /** Determine if no message body contained in the search result and only the message header is available. + /** Determine if no message body contained in the search result and only the + * message header is available. */ bool headerOnly(); /** Get the message list from search or fetch the Emails * - * @return The IMAP_MSG_List structured data which contains text and html contents, - * attachments, inline images, embedded rfc822 messages details for each message. + * @return The IMAP_MSG_List structured data which contains text and html + * contents, + * attachments, inline images, embedded rfc822 messages details for each + * message. */ IMAP_MSG_List data(); /** Get the details of the selected or opned mailbox folder * - * @return The SelectedFolderInfo class which contains the info about flags, total messages, next UID, + * @return The SelectedFolderInfo class which contains the info about flags, + * total messages, next UID, * search count and the available messages count. */ SelectedFolderInfo selectedFolder(); @@ -2398,25 +2615,31 @@ private: void clearMessageData(); void checkUID(); void checkPath(); - void getMessages(uint16_t messageIndex, esp_mail_imap_msg_item_t &msg); - void getRFC822Messages(uint16_t messageIndex, esp_mail_imap_msg_item_t &msg); + void getMessages(uint16_t messageIndex, struct esp_mail_imap_msg_item_t &msg); + void getRFC822Messages(uint16_t messageIndex, + struct esp_mail_imap_msg_item_t &msg); bool closeMailbox(); - bool openMailbox(const char *folder, esp_mail_imap_auth_mode mode, bool waitResponse); + bool openMailbox(const char *folder, esp_mail_imap_auth_mode mode, + bool waitResponse); bool getMailboxes(FoldersCollection &flders); bool checkCapability(); bool _tcpConnected = false; - esp_mail_imap_response_status_t _imapStatus; + struct esp_mail_imap_response_status_t _imapStatus; int _cMsgIdx = 0; int _cPartIdx = 0; int _totalRead = 0; - std::vector _headers = std::vector(); + std::vector _headers = + std::vector(); - esp_mail_imap_command _imap_cmd = esp_mail_imap_command::esp_mail_imap_cmd_login; - //std::string _partNumStr = ""; - std::vector _multipart_levels = std::vector(); + esp_mail_imap_command _imap_cmd = + esp_mail_imap_command::esp_mail_imap_cmd_login; + // std::string _partNumStr = ""; + std::vector _multipart_levels = + std::vector(); int _rfc822_part_count = 0; - esp_mail_file_storage_type _storageType = esp_mail_file_storage_type::esp_mail_file_storage_type_flash; + esp_mail_file_storage_type _storageType = + esp_mail_file_storage_type::esp_mail_file_storage_type_flash; bool _unseen = false; bool _readOnlyMode = true; struct esp_mail_auth_capability_t _auth_capability; @@ -2425,7 +2648,7 @@ private: bool _mailboxOpened = false; std::string _nextUID = ""; - esp_mail_imap_read_config_t *_config = nullptr; + struct esp_mail_imap_read_config_t *_config = nullptr; bool _headerOnly = true; bool _uidSearch = false; @@ -2454,10 +2677,11 @@ private: class SendingResult { private: - std::vector _result = std::vector(); - void add(esp_mail_smtp_send_status_t r) + std::vector _result = + std::vector(); + void add(struct esp_mail_smtp_send_status_t r) { - esp_mail_smtp_send_status_t _r = r; + struct esp_mail_smtp_send_status_t _r = r; _result.push_back(_r); } void clear() @@ -2479,7 +2703,7 @@ public: ~SendingResult() { clear(); }; SMTP_Result getItem(size_t index) { - esp_mail_smtp_send_status_t r; + struct esp_mail_smtp_send_status_t r; if (index < _result.size()) return _result[index]; return r; @@ -2495,7 +2719,8 @@ public: /** Begin the SMTP server connection. * - * @param session The pointer to ESP_Mail_Session structured data that keeps the server and log in details. + * @param session The pointer to ESP_Mail_Session structured data that keeps + * the server and log in details. * @return The boolean value indicates the success of operation. */ bool connect(ESP_Mail_Session *session); @@ -2523,7 +2748,8 @@ public: /** Set the Email sending status callback function. * - * @param smtpCallback The callback function that accept the smtpStatusCallback param. + * @param smtpCallback The callback function that accept the + * smtpStatusCallback param. */ void callback(smtpStatusCallback smtpCallback); @@ -2533,16 +2759,17 @@ public: private: bool _tcpConnected = false; - esp_mail_smtp_response_status_t _smtpStatus; + struct esp_mail_smtp_response_status_t _smtpStatus; int _sentSuccessCount = 0; int _sentFailedCount = 0; bool _chunkedEnable = false; int _chunkCount = 0; - esp_mail_smtp_command _smtp_cmd = esp_mail_smtp_command::esp_mail_smtp_cmd_greeting; + esp_mail_smtp_command _smtp_cmd = + esp_mail_smtp_command::esp_mail_smtp_cmd_greeting; struct esp_mail_auth_capability_t _auth_capability; struct esp_mail_smtp_capability_t _send_capability; - ESP_Mail_Session *_sesson_cfg; + ESP_Mail_Session *_sesson_cfg = NULL; bool _debug = false; int _debugLevel = 0; @@ -2550,7 +2777,7 @@ private: smtpStatusCallback _sendCallback = NULL; SMTP_Status _cbData; - esp_mail_smtp_msg_type_t _msgType; + struct esp_mail_smtp_msg_type_t _msgType; int _certType = -1; std::shared_ptr _caCert = nullptr; @@ -2568,7 +2795,8 @@ static void __attribute__((used)) esp_mail_debug(const char *msg) Serial.println(msg); } -static void __attribute__((used)) esp_mail_debug_line(const char *msg, bool newline) +static void __attribute__((used)) +esp_mail_debug_line(const char *msg, bool newline) { delay(0); if (newline) @@ -2579,4 +2807,4 @@ static void __attribute__((used)) esp_mail_debug_line(const char *msg, bool newl extern ESP_Mail_Client MailClient; -#endif //ESP_Mail_Client_H +#endif // ESP_Mail_Client_H diff --git a/lib/lib_div/lib_mail/src/ESP_Mail_FS.h b/lib/lib_div/lib_mail/src/ESP_Mail_FS.h new file mode 100644 index 000000000..7032c4ab8 --- /dev/null +++ b/lib/lib_div/lib_mail/src/ESP_Mail_FS.h @@ -0,0 +1,39 @@ +#ifndef ESP_Mail_CONFIG_H +#define ESP_Mail_CONFIG_H +#include + +/** + * To use other flash file systems + * + * LittleFS File system + * + * #include + * #define ESP_Mail_DEFAULT_FLASH_FS LittleFS //For ESP8266 LitteFS + * + * + * FFat File system + * + * #include + * #define ESP_Mail_DEFAULT_FLASH_FS FFat //For ESP32 FFat + * +*/ +#define ESP_Mail_DEFAULT_FLASH_FS SPIFFS + +/** + * To use SD card file systems with different hardware interface + * e.g. SDMMC hardware bus on the ESP32 + * https://github.com/espressif/arduino-esp32/tree/master/libraries/SD#faq + * + #include + #define ESP_Mail_DEFAULT_SD_FS SD_MMC //For ESP32 SDMMC + #define CARD_TYPE_SD_MMC 1 + * +*/ +#define ESP_Mail_DEFAULT_SD_FS SD +#define CARD_TYPE_SD 1 + +//For ESP32, format SPIFFS or FFat if mounting failed +#define FORMAT_FLASH_IF_MOUNT_FAILED 1 + + +#endif \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/README.md b/lib/lib_div/lib_mail/src/README.md index 874193eac..d83236eca 100755 --- a/lib/lib_div/lib_mail/src/README.md +++ b/lib/lib_div/lib_mail/src/README.md @@ -1,7 +1,7 @@ # ESP Mail Client Arduino Library for ESP32 and ESP8266 -The detail and usage of the available functions in the latest version (1.0.13) are showed below. +The detail and usage of the available functions in the latest version (1.2.0) are showed below. ## Global functions @@ -124,6 +124,25 @@ bool sdBegin(uint8_t sck, uint8_t miso, uint8_t mosi, uint8_t ss); +#### Initialize the SD_MMC card (ESP32 only). + +param **`mountpoint`** The mounting point. + +param **`mode1bit`** Allow 1 bit data line (SPI mode). + +param **`format_if_mount_failed`** Format SD_MMC card if mount failed. + +return **`Boolean`** type status indicates the success of the operation. + +```C++ +bool sdMMCBegin(const char *mountpoint = "/sdcard", bool mode1bit = false, bool format_if_mount_failed = false); +``` + + + + + + #### Initialize the SD card with the default SPI port. return **`boolean`** The boolean value which indicates the success of operation. @@ -703,6 +722,10 @@ This property has the sub properties ###### [const char*] content - The PLAIN text content of the message. +###### [esp_mail_blob_message_content_t] blob - The blob that contins PLAIN text content of the message. + +###### [esp_mail_file_message_content_t] file - The file that contins PLAIN text content of the message. + ###### [const char*] charSet - The character transcoding of the PLAIN text content of the message. ###### [const char*] content_type - The content type of message. @@ -722,6 +745,10 @@ This propery has the sub properties ###### [const char*] content - The HTML content of the message. +###### [esp_mail_blob_message_content_t] blob - The blob that contins HTML content of the message. + +###### [esp_mail_file_message_content_t] file - The file that contins HTML content of the message. + ###### [const char*] charSet - The character transcoding of the HTML content of the message. ###### [const char*] content_type - The content type of message. @@ -1334,6 +1361,61 @@ esp_mail_smtp_embed_message_type type; +## esp_mail_blob_message_content_t structured data + + +The following properties are available from the esp_mail_blob_message_content_t data type. + +This data type is used for storing the blob info of message body. + + + + +##### [Properties] The array of content in flash memory. + +```C++ +const uint8_t * data; +``` + + +##### [Properties] The array size in bytes. + +```C++ +size_t size; +``` + + + + + +## esp_mail_file_message_content_t structured data + + +The following properties are available from the esp_mail_file_message_content_t data type. + +This data type is used for storing the file info of message body. + + + + +##### [Properties] The file path include its name. + +```C++ +const char *name; +``` + + +##### [Properties] The type of file storages. + +```C++ +esp_mail_file_storage_type type; +``` + + + + + + ## IMAP_MSG_Item type data diff --git a/lib/lib_div/lib_mail/src/SDK_Version_Common.h b/lib/lib_div/lib_mail/src/SDK_Version_Common.h new file mode 100644 index 000000000..c0db7a62c --- /dev/null +++ b/lib/lib_div/lib_mail/src/SDK_Version_Common.h @@ -0,0 +1,20 @@ +#ifndef _SDK_VERSION_COMMON_H +#define _SDK_VERSION_COMMON_H + +#if defined(ESP8266) + +#include + +//__GNUC__ +//__GNUC_MINOR__ +//__GNUC_PATCHLEVEL__ + +#ifdef __GNUC__ +#if __GNUC__ > 4 || __GNUC__ == 10 +#define ESP8266_CORE_SDK_V3_X_X +#endif +#endif + +#endif + +#endif \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.cpp b/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.cpp index 5e2c01d50..227f8e59d 100755 --- a/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.cpp +++ b/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.cpp @@ -1,8 +1,8 @@ /* - * ESP32 Internet Time Helper Arduino Library v 1.0.1 + * ESP8266/ESP32 Internet Time Helper Arduino Library v 1.0.2 * * The MIT License (MIT) - * Copyright (c) 2019 K. Suwatchai (Mobizt) + * Copyright (c) 2021 K. Suwatchai (Mobizt) * * * Permission is hereby granted, free of charge, to any person returning a copy of @@ -31,12 +31,19 @@ ESPTimeHelper::ESPTimeHelper() { } + uint32_t ESPTimeHelper::getUnixTime() { uint32_t utime = (msec_time_diff + millis()) / 1000; return utime; } +int ESPTimeHelper::setTimestamp(time_t ts) +{ + struct timeval tm = {ts, 0};//sec, us + return settimeofday((const timeval *)&tm, 0); +} + time_t ESPTimeHelper::getTimestamp(int year, int mon, int date, int hour, int mins, int sec) { struct tm timeinfo; diff --git a/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.h b/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.h index 8ae9c336a..1e3111951 100755 --- a/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.h +++ b/lib/lib_div/lib_mail/src/extras/ESPTimeHelper.h @@ -1,8 +1,8 @@ /* - * ESP8266/ESP32 Internet Time Helper Arduino Library v 1.0.1 + * ESP8266/ESP32 Internet Time Helper Arduino Library v 1.0.2 * * The MIT License (MIT) - * Copyright (c) 2020 K. Suwatchai (Mobizt) + * Copyright (c) 2021 K. Suwatchai (Mobizt) * * * Permission is hereby granted, free of charge, to any person returning a copy of @@ -32,6 +32,7 @@ #include #elif defined(ESP8266) #include +#include "SDK_Version_Common.h" #endif class ESPTimeHelper @@ -49,6 +50,13 @@ public: */ bool setClock(float gmtOffset, float daylightOffset); + /** Set system time with provided timestamp + * + * @param ts timestamp in seconds from midnight Jan 1, 1970. + * @return error number, 0 for success. + */ + int setTimestamp(time_t ts); + /** Provide the Unix time * * @return uint32_t The value of current Unix time. diff --git a/lib/lib_div/lib_mail/src/extras/ESP_Mail_Client_FS.h b/lib/lib_div/lib_mail/src/extras/ESP_Mail_Client_FS.h deleted file mode 100755 index 3834201d7..000000000 --- a/lib/lib_div/lib_mail/src/extras/ESP_Mail_Client_FS.h +++ /dev/null @@ -1,8 +0,0 @@ - -/* - -To use LittleFS file system instead of SPIFFS, uncomment the following line - -*/ - -//#define USE_LITTLEFS diff --git a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.cpp b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.cpp index b463f0d85..86bfbcb69 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.cpp +++ b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.cpp @@ -1,17 +1,17 @@ /* - * Customized version of ESP32 HTTPClient Library. - * - * v 1.1.1 - * + * Customized version of ESP32 HTTPClient Library. + * + * v 1.1.5 + * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) - * + * * HTTPClient Arduino library for ESP32 * * Copyright (c) 2015 Markus Sattler. All rights reserved. * This file is part of the HTTPClient for Arduino. - * Port to ESP32 by Evandro Luis Copercini (2017), - * changed fingerprints to CA verification. + * Port to ESP32 by Evandro Luis Copercini (2017), + * changed fingerprints to CA verification. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,8 +38,6 @@ ESP_Mail_HTTPClient32::ESP_Mail_HTTPClient32() { - transportTraits = ESP_Mail_TransportTraitsPtr(new ESP_Mail_TLSTraits(nullptr)); - _wcs = transportTraits->create(); } ESP_Mail_HTTPClient32::~ESP_Mail_HTTPClient32() @@ -52,9 +50,6 @@ ESP_Mail_HTTPClient32::~ESP_Mail_HTTPClient32() } std::string().swap(_host); std::string().swap(_caCertFile); - _cacert.reset(new char); - _cacert = nullptr; - transportTraits.reset(nullptr); } bool ESP_Mail_HTTPClient32::begin(const char *host, uint16_t port) @@ -171,10 +166,10 @@ bool ESP_Mail_HTTPClient32::connect(bool secured) return true; } - if (!transportTraits) - return false; + if (_debugCallback) + _wcs->setDebugCB(&_debugCallback); + _wcs->setSTARTTLS(!secured); - transportTraits->verify(*_wcs, _host.c_str(), !secured, _debugCallback); if (!_wcs->connect(_host.c_str(), _port)) return false; return connected(); @@ -187,14 +182,15 @@ void ESP_Mail_HTTPClient32::setDebugCallback(DebugMsgCallback cb) void ESP_Mail_HTTPClient32::setCACert(const char *caCert) { + _wcs->setCACert(caCert); if (caCert) - { - transportTraits.reset(nullptr); - transportTraits = ESP_Mail_TransportTraitsPtr(new ESP_Mail_TLSTraits(caCert)); _certType = 1; - } else + { + setInsecure(); _certType = 0; + } + //_wcs->setNoDelay(true); } void ESP_Mail_HTTPClient32::setCertFile(const char *caCertFile, esp_mail_file_storage_type storageType) @@ -202,45 +198,34 @@ void ESP_Mail_HTTPClient32::setCertFile(const char *caCertFile, esp_mail_file_st if (strlen(caCertFile) > 0) { - bool t = false; - _certType = 2; - - if (storageType == esp_mail_file_storage_type::esp_mail_file_storage_type_flash) { - // t = SPIFFS.begin(true); - } - else if (storageType == esp_mail_file_storage_type::esp_mail_file_storage_type_sd) - t = SD.begin(); - if (!t) - return; - File f; - if (storageType == esp_mail_file_storage_type::esp_mail_file_storage_type_flash) + if (storageType == esp_mail_file_storage_type_flash) { - //if (SPIFFS.exists(caCertFile)) - // f = SPIFFS.open(caCertFile, FILE_READ); + ESP_MAIL_FLASH_FS.begin(); + if (ESP_MAIL_FLASH_FS.exists(caCertFile)) + f = ESP_MAIL_FLASH_FS.open(caCertFile, FILE_READ); } - else if (storageType == esp_mail_file_storage_type::esp_mail_file_storage_type_sd) + else if (storageType == esp_mail_file_storage_type_sd) { - if (SD.exists(caCertFile)) - f = SD.open(caCertFile, FILE_READ); + ESP_MAIL_SD_FS.begin(); + if (ESP_MAIL_SD_FS.exists(caCertFile)) + f = ESP_MAIL_SD_FS.open(caCertFile, FILE_READ); } if (f) { size_t len = f.size(); - _cacert.reset(new char); - _cacert = nullptr; - _cacert = std::unique_ptr(new char[len]); - - if (f.available()) - f.readBytes(_cacert.get(), len); - + _wcs->loadCACert(f, len); f.close(); - - transportTraits.reset(nullptr); - transportTraits = ESP_Mail_TransportTraitsPtr(new ESP_Mail_TLSTraits(_cacert.get())); } + _certType = 2; } + //_wcs->setNoDelay(true); +} + +void ESP_Mail_HTTPClient32::setInsecure() +{ + _wcs->setInsecure(); } #endif //ESP32 diff --git a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.h b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.h index 4631d71e8..e8c7d4c32 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.h +++ b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_HTTPClient32.h @@ -1,11 +1,11 @@ /* - * Customized version of ESP32 HTTPClient Library. - * - * v 1.1.1 - * + * Customized version of ESP32 HTTPClient Library. + * + * v 1.1.5 + * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) - * + * * HTTPClient Arduino library for ESP32 * * Copyright (c) 2015 Markus Sattler. All rights reserved. @@ -39,8 +39,14 @@ #include //#include #include +#include "ESP_Mail_FS.h" #include "ESP_Mail_WCS32.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#define ESP_MAIL_FLASH_FS ESP_Mail_DEFAULT_FLASH_FS +#define ESP_MAIL_SD_FS ESP_Mail_DEFAULT_SD_FS + #if __has_include() || __has_include() #error WiFi UART bridge was not supported. #endif @@ -54,56 +60,9 @@ enum esp_mail_file_storage_type { esp_mail_file_storage_type_none, esp_mail_file_storage_type_flash, - esp_mail_file_storage_type_sd, - esp_mail_file_storage_type_univ + esp_mail_file_storage_type_sd }; -class ESP_Mail_TransportTraits -{ -public: - virtual ~ESP_Mail_TransportTraits() {} - - virtual std::unique_ptr create() - { - return std::unique_ptr(new ESP_Mail_WCS32()); - } - - virtual bool - verify(ESP_Mail_WCS32 &client, const char *host, bool starttls, DebugMsgCallback cb) - { - return true; - } -}; - -class ESP_Mail_TLSTraits : public ESP_Mail_TransportTraits -{ -public: - ESP_Mail_TLSTraits(const char *CAcert, const char *clicert = nullptr, const char *clikey = nullptr) : _cacert(CAcert), _clicert(clicert), _clikey(clikey) {} - - std::unique_ptr create() override - { - return std::unique_ptr(new ESP_Mail_WCS32()); - } - - bool verify(ESP_Mail_WCS32 &client, const char *host, bool starttls, DebugMsgCallback cb) override - { - ESP_Mail_WCS32 &wcs = static_cast(client); - wcs.setCACert(_cacert); - wcs.setCertificate(_clicert); - wcs.setPrivateKey(_clikey); - wcs.setSTARTTLS(starttls); - wcs.setDebugCB(cb); - return true; - } - -protected: - const char *_cacert; - const char *_clicert; - const char *_clikey; -}; - -typedef std::unique_ptr ESP_Mail_TransportTraitsPtr; - class ESP_Mail_HTTPClient32 { public: @@ -115,7 +74,7 @@ public: * \param host - Host name without protocols. * \param port - Server's port. * \return True as default. - * If no certificate string provided, use (const char*)NULL to CAcert param + * If no certificate string provided, use (const char*)NULL to CAcert param */ bool begin(const char *host, uint16_t port); @@ -129,7 +88,7 @@ public: * Establish http connection if header provided and send it, send payload if provided. * \param header - The header string (constant chars array). * \param payload - The payload string (constant chars array), optional. - * \return http status code, Return zero if new http connection and header and/or payload sent + * \return http status code, Return zero if new http connection and header and/or payload sent * with no error or no header and payload provided. If obly payload provided, no new http connection was established. */ int send(const char *header, const char *payload); @@ -138,7 +97,7 @@ public: * Send extra header without making new http connection (if send has been called) * \param header - The header string (constant chars array). * \return True if header sending success. - * Need to call send with header first. + * Need to call send with header first. */ bool send(const char *header); @@ -148,6 +107,11 @@ public: */ WiFiClient *stream(void); + /** + * Set insecure mode + */ + void setInsecure(); + ESP_Mail_WCS32 *_stream(void); size_t _ns_print(const char *buf); size_t _ns_println(const char *buf); @@ -166,9 +130,7 @@ public: protected: DebugMsgCallback _debugCallback = NULL; - ESP_Mail_TransportTraitsPtr transportTraits; - std::unique_ptr _wcs; - std::unique_ptr _cacert; + std::unique_ptr _wcs = std::unique_ptr(new ESP_Mail_WCS32()); std::string _host = ""; uint16_t _port = 0; diff --git a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.cpp b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.cpp index 683a6a65c..72946d9e2 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.cpp +++ b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.cpp @@ -1,5 +1,5 @@ /* - *Customized WiFiClientSecure.cpp version 1.0.3 + *Customized WiFiClientSecure.cpp version 1.0.8 * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) @@ -61,10 +61,11 @@ ESP_Mail_WCS32::ESP_Mail_WCS32() { _connected = false; - sslclient = new esp_mail_ssl_ctx32; - ssl_init(sslclient); + sslclient = new esp_mail_ssl_client32::esp_mail_ssl_ctx32; + _ssl_client32.ssl_init(sslclient); sslclient->socket = -1; sslclient->handshake_timeout = 120000; + _use_insecure = false; _CA_cert = NULL; _cert = NULL; _private_key = NULL; @@ -78,8 +79,8 @@ ESP_Mail_WCS32::ESP_Mail_WCS32(int sock) _connected = false; _timeout = 0; - sslclient = new esp_mail_ssl_ctx32; - ssl_init(sslclient); + sslclient = new esp_mail_ssl_client32::esp_mail_ssl_ctx32; + _ssl_client32.ssl_init(sslclient); sslclient->socket = sock; sslclient->handshake_timeout = 120000; @@ -99,10 +100,12 @@ ESP_Mail_WCS32::ESP_Mail_WCS32(int sock) ESP_Mail_WCS32::ESP_Mail_WCS32(bool secured) { _connected = false; - sslclient = new esp_mail_ssl_ctx32; - ssl_init(sslclient); + + sslclient = new esp_mail_ssl_client32::esp_mail_ssl_ctx32; + _ssl_client32.ssl_init(sslclient); sslclient->socket = -1; sslclient->handshake_timeout = 120000; + _use_insecure = !secured; _secured = secured; _CA_cert = NULL; _cert = NULL; @@ -135,7 +138,7 @@ void ESP_Mail_WCS32::stop() _connected = false; _peek = -1; } - stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); + _ssl_client32.stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); } int ESP_Mail_WCS32::connect(IPAddress ip, uint16_t port) @@ -164,12 +167,12 @@ int ESP_Mail_WCS32::connect(const char *host, uint16_t port, int32_t timeout) return connect(host, port); } -int ESP_Mail_WCS32::connect(IPAddress ip, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) +int ESP_Mail_WCS32::connect(IPAddress ip, uint16_t port, const char *CA_cert, const char *cert, const char *private_key) { - return connect(ip.toString().c_str(), port, _CA_cert, _cert, _private_key); + return connect(ip.toString().c_str(), port, CA_cert, cert, private_key); } -int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key) +int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *CA_cert, const char *cert, const char *private_key) { _host = host; _port = port; @@ -180,7 +183,8 @@ int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *_CA_cer sslclient->handshake_timeout = _timeout; } - int ret = start_socket(sslclient, host, port, _timeout); + int ret = _ssl_client32.start_socket(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure); + _lastError = ret; if (ret < 0) { @@ -191,7 +195,7 @@ int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *_CA_cer if (_secured) { - ret = start_ssl_client(sslclient, host, port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL); + ret = _ssl_client32.start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure); _lastError = ret; if (ret < 0) { @@ -207,7 +211,7 @@ int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *_CA_cer int ESP_Mail_WCS32::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) { - return connect(ip.toString().c_str(), port, _pskIdent, _psKey); + return connect(ip.toString().c_str(), port, pskIdent, psKey); } int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) @@ -221,7 +225,8 @@ int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *pskIden { sslclient->handshake_timeout = _timeout; } - int ret = start_socket(sslclient, host, port, _timeout); + + int ret = _ssl_client32.start_socket(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure); _lastError = ret; if (ret < 0) { @@ -232,7 +237,7 @@ int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *pskIden if (_secured) { - ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey); + ret = _ssl_client32.start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure); _lastError = ret; if (ret < 0) { @@ -277,7 +282,7 @@ size_t ESP_Mail_WCS32::write(const uint8_t *buf, size_t size) { return 0; } - int res = send_ssl_data(sslclient, buf, size); + int res = _ssl_client32.send_ssl_data(sslclient, buf, size); if (res < 0) { stop(); @@ -312,7 +317,7 @@ int ESP_Mail_WCS32::read(uint8_t *buf, size_t size) peeked = 1; } - int res = get_ssl_receive(sslclient, buf, size); + int res = _ssl_client32.get_ssl_receive(sslclient, buf, size); if (res < 0) { stop(); @@ -328,7 +333,7 @@ int ESP_Mail_WCS32::available() { return peeked; } - int res = data_to_read(sslclient); + int res = _ssl_client32.data_to_read(sslclient); if (res < 0) { stop(); @@ -345,6 +350,16 @@ uint8_t ESP_Mail_WCS32::connected() return _connected; } +void ESP_Mail_WCS32::setInsecure() +{ + _CA_cert = NULL; + _cert = NULL; + _private_key = NULL; + _pskIdent = NULL; + _psKey = NULL; + _use_insecure = true; +} + void ESP_Mail_WCS32::setCACert(const char *rootCA) { _CA_cert = rootCA; @@ -371,17 +386,12 @@ bool ESP_Mail_WCS32::verify(const char *fp, const char *domain_name) if (!sslclient) return false; - return verify_ssl_fingerprint(sslclient, fp, domain_name); + return _ssl_client32.verify_ssl_fingerprint(sslclient, fp, domain_name); } char *ESP_Mail_WCS32::_streamLoad(Stream &stream, size_t size) { - static char *dest = nullptr; - if (dest) - { - free(dest); - } - dest = (char *)malloc(size); + char *dest = (char *)malloc(size + 1); if (!dest) { return nullptr; @@ -390,7 +400,9 @@ char *ESP_Mail_WCS32::_streamLoad(Stream &stream, size_t size) { free(dest); dest = nullptr; + return nullptr; } + dest[size] = '\0'; return dest; } @@ -436,9 +448,7 @@ int ESP_Mail_WCS32::lastError(char *buf, const size_t size) { return 0; } - char error_buf[100]; - mbedtls_strerror(_lastError, error_buf, 100); - snprintf(buf, size, "%s", error_buf); + mbedtls_strerror(_lastError, buf, size); return _lastError; } @@ -452,9 +462,9 @@ void ESP_Mail_WCS32::setSTARTTLS(bool enable) _secured = !enable; } -void ESP_Mail_WCS32::setDebugCB(DebugMsgCallback cb) +void ESP_Mail_WCS32::setDebugCB(DebugMsgCallback *cb) { - sslclient->_debugCallback = std::move(cb); + sslclient->_debugCallback = cb; } int ESP_Mail_WCS32::_ns_available() @@ -467,7 +477,7 @@ int ESP_Mail_WCS32::_ns_available() int bufLen = 1024; char *tmp = new char[bufLen]; memset(tmp, 0, bufLen); - int ret = _ns_lwip_read(sslclient, tmp, bufLen); + int ret = _ssl_client32._ns_lwip_read(sslclient, tmp, bufLen); if (ret > 0) _rxBuf += tmp; delete[] tmp; @@ -481,17 +491,18 @@ int ESP_Mail_WCS32::_ns_available() } return result; } + size_t ESP_Mail_WCS32::_ns_write(const char *buf, size_t size) { if (sslclient->socket < 0 || !size) return 0; - return _ns_lwip_write(sslclient, buf, size); + return _ssl_client32._ns_lwip_write(sslclient, buf, size); } size_t ESP_Mail_WCS32::_ns_read(char *buf, size_t size) { if (_rxBuf.length() == 0) - return _ns_lwip_read(sslclient, buf, size); + return _ssl_client32._ns_lwip_read(sslclient, buf, size); else { size_t sz = size; @@ -510,7 +521,7 @@ int ESP_Mail_WCS32::_ns_read() { char *buf = new char[2]; memset(buf, 0, 2); - int ret = _ns_lwip_read(sslclient, buf, 1); + int ret = _ssl_client32._ns_lwip_read(sslclient, buf, 1); if (ret > 0) c = buf[0]; delete[] buf; @@ -533,9 +544,9 @@ bool ESP_Mail_WCS32::_ns_connect_ssl() { int ret = 0; if (_withKey) - ret = start_ssl_client(sslclient, _host.c_str(), _port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL); + ret = _ssl_client32.start_ssl_client(sslclient, _host.c_str(), _port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL, _use_insecure); else if (_withCert) - ret = start_ssl_client(sslclient, _host.c_str(), _port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey); + ret = _ssl_client32.start_ssl_client(sslclient, _host.c_str(), _port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey, _use_insecure); _lastError = ret; if (ret < 0) @@ -550,4 +561,4 @@ bool ESP_Mail_WCS32::_ns_connect_ssl() #endif //ESP32 -#endif //WiFiClientSecureESP32_CPP \ No newline at end of file +#endif //ESP_Mail_WCS32_CPP \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.h b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.h index ce04846c7..35be7527d 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.h +++ b/lib/lib_div/lib_mail/src/wcs/esp32/ESP_Mail_WCS32.h @@ -1,6 +1,6 @@ /* - *Customized WiFiClientSecure.h version 1.0.3 + *Customized WiFiClientSecure.h version 1.0.8 * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) @@ -58,21 +58,22 @@ typedef void (*DebugMsgCallback)(const char *msg); class ESP_Mail_WCS32 : public WiFiClient { + friend class ESP_Mail_HTTPClient32; + protected: - esp_mail_ssl_ctx32 *sslclient; + esp_mail_ssl_client32::esp_mail_ssl_ctx32 *sslclient; int _lastError = 0; int _peek = -1; int _timeout = 0; + bool _use_insecure; const char *_CA_cert; const char *_cert; const char *_private_key; const char *_pskIdent; // identity for PSK cipher suites const char *_psKey; // key in hex for PSK cipher suites - DebugMsgCallback _debugCallback = NULL; public: - friend class ESP_Mail_HTTPClient32; ESP_Mail_WCS32 *next; ESP_Mail_WCS32(); ESP_Mail_WCS32(int socket); @@ -96,6 +97,7 @@ public: void stop(); uint8_t connected(); int lastError(char *buf, const size_t size); + void setInsecure(); // Don't validate the chain, just accept whatever is given. VERY INSECURE! void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex void setCACert(const char *rootCA); void setCertificate(const char *client_ca); @@ -105,8 +107,9 @@ public: bool loadPrivateKey(Stream &stream, size_t size); bool verify(const char *fingerprint, const char *domain_name); void setHandshakeTimeout(unsigned long handshake_timeout); + int setTimeout(uint32_t seconds) { return 0; } void setSTARTTLS(bool enable); - void setDebugCB(DebugMsgCallback cb); + void setDebugCB(DebugMsgCallback *cb); int _ns_available(); size_t _ns_write(const char *buf, size_t size); size_t _ns_read(char *buf, size_t size); @@ -139,6 +142,7 @@ public: } private: + esp_mail_ssl_client32 _ssl_client32; char *_streamLoad(Stream &stream, size_t size); bool _secured = true; bool _withCert = false; diff --git a/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.cpp b/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.cpp index 2fb192e78..c4d535ffb 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.cpp +++ b/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.cpp @@ -1,5 +1,5 @@ /* - *Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.5 + *Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.8 * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) @@ -36,7 +36,8 @@ #ifdef ESP32 -#include "Arduino.h" +#include + #include #include #include @@ -49,9 +50,13 @@ #include "esp_mail_ssl_client32.h" #include -const char *_esp_mail_pers32 = "esp32-tls"; +#ifndef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#error "Please configure IDF framework to include mbedTLS -> Enable pre-shared-key ciphersuites and activate at least one cipher" +#endif -static int handle_error(int err) +const char *_esp_mail_pers32 = "esp_mail_esp32-tls"; + +static int _handle_error(int err, const char *file, int line) { if (err == -30848) { @@ -60,22 +65,32 @@ static int handle_error(int err) #ifdef MBEDTLS_ERROR_C char error_buf[100]; mbedtls_strerror(err, error_buf, 100); - log_e("%s", error_buf); + log_e("[%s():%d]: (%d) %s", file, line, err, error_buf); +#else + log_e("[%s():%d]: code %d", file, line, err); #endif - log_e("MbedTLS message code: %d", err); return err; } -void ssl_init(esp_mail_ssl_ctx32 *ssl_client) +#define handle_error(e) _handle_error(e, __FUNCTION__, __LINE__) + +void esp_mail_ssl_client32::ssl_init(esp_mail_ssl_ctx32 *ssl_client) { mbedtls_ssl_init(&ssl_client->ssl_ctx); mbedtls_ssl_config_init(&ssl_client->ssl_conf); mbedtls_ctr_drbg_init(&ssl_client->drbg_ctx); - mbedtls_net_init(&ssl_client->server_fd); } -int start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout) +int esp_mail_ssl_client32::start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure) { + + if (rootCABuff == NULL && pskIdent == NULL && psKey == NULL && !insecure) + { + if (ssl_client->_debugCallback) + ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_27); + return -1; + } + int enable = 1; if (ssl_client->_debugCallback) @@ -116,12 +131,23 @@ int start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port { if (timeout <= 0) { - timeout = 30000; + timeout = 30000; // Milli seconds. } - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); - lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)); - lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)); + timeval so_timeout = {.tv_sec = timeout / 1000, .tv_usec = (timeout % 1000) * 1000}; + +#define ROE(x, msg) \ + { \ + if (((x) < 0)) \ + { \ + log_e("LWIP Socket config of " msg " failed."); \ + return -1; \ + } \ + } + ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &so_timeout, sizeof(so_timeout)), "SO_RCVTIMEO"); + ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &so_timeout, sizeof(so_timeout)), "SO_SNDTIMEO"); + + ROE(lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)), "TCP_NODELAY"); + ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)), "SO_KEEPALIVE"); } else { @@ -136,8 +162,9 @@ int start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port return ssl_client->socket; } -int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey) +int esp_mail_ssl_client32::start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure) { + char buf[512]; int ret, flags; @@ -147,21 +174,11 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t log_v("Seeding the random number generator"); mbedtls_entropy_init(&ssl_client->entropy_ctx); - ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func, - &ssl_client->entropy_ctx, (const unsigned char *)_esp_mail_pers32, strlen(_esp_mail_pers32)); + ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func, &ssl_client->entropy_ctx, (const unsigned char *)_esp_mail_pers32, strlen(_esp_mail_pers32)); if (ret < 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } - + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } @@ -176,22 +193,22 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } // MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and // MBEDTLS_SSL_VERIFY_NONE if not. - if (rootCABuff != NULL) + if (insecure) + { + if (ssl_client->_debugCallback) + ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_28); + + mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); + log_i("WARNING: Skipping SSL Verification. INSECURE!"); + } + else if (rootCABuff != NULL) { if (ssl_client->_debugCallback) ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_11); @@ -204,15 +221,9 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if (ret < 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); + // free the ca_cert in the case parse failed, otherwise, the old ca_cert still in the heap memory, that lead to "out of memory" crash. + mbedtls_x509_crt_free(&ssl_client->ca_cert); return handle_error(ret); } } @@ -229,6 +240,7 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t log_e("pre-shared key not valid hex or too long"); return -1; } + unsigned char psk[MBEDTLS_PSK_MAX_LEN]; size_t psk_len = strlen(psKey) / 2; for (int j = 0; j < strlen(psKey); j += 2) @@ -257,32 +269,24 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t // set mbedtls config if (ssl_client->_debugCallback) ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_14); + ret = mbedtls_ssl_conf_psk(&ssl_client->ssl_conf, psk, psk_len, (const unsigned char *)pskIdent, strlen(pskIdent)); if (ret != 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); + log_e("mbedtls_ssl_conf_psk returned %d", ret); return handle_error(ret); } } else { - - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); - log_i("WARNING: Use certificates for a more secure communication!"); + return -1; } - if (cli_cert != NULL && cli_key != NULL) + if (!insecure && cli_cert != NULL && cli_key != NULL) { mbedtls_x509_crt_init(&ssl_client->client_cert); @@ -297,15 +301,9 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if (ret < 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); + // free the client_cert in the case parse failed, otherwise, the old client_cert still in the heap memory, that lead to "out of memory" crash. + mbedtls_x509_crt_free(&ssl_client->client_cert); return handle_error(ret); } @@ -317,6 +315,8 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if (ret != 0) { + if (ssl_client->_debugCallback) + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } @@ -332,15 +332,7 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if ((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } @@ -349,16 +341,7 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } - + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } @@ -374,20 +357,12 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ssl_client->_debugCallback) - { - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } if ((millis() - handshake_start_time) > ssl_client->handshake_timeout) return -1; - vTaskDelay(10 / portTICK_PERIOD_MS); + vTaskDelay(2); //2 ticks } if (cli_cert != NULL && cli_key != NULL) @@ -395,7 +370,6 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t log_d("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx)); if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) { - log_d("Record expansion is %d", ret); } else @@ -411,18 +385,14 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { - bzero(buf, sizeof(buf)); + memset(buf, 0, sizeof(buf)); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); - if (ssl_client->_debugCallback) - ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_20); log_e("Failed to verify peer certificate! verification info: %s", buf); stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. return handle_error(ret); } else { - if (ssl_client->_debugCallback) - ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_21); log_v("Certificate verified."); } @@ -446,10 +416,11 @@ int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t return ssl_client->socket; } -void stop_ssl_socket(esp_mail_ssl_ctx32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key) +void esp_mail_ssl_client32::stop_ssl_socket(esp_mail_ssl_ctx32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key) { if (ssl_client->_debugCallback) ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_22); + log_v("Cleaning SSL connection."); if (ssl_client->socket >= 0) @@ -464,7 +435,7 @@ void stop_ssl_socket(esp_mail_ssl_ctx32 *ssl_client, const char *rootCABuff, con mbedtls_entropy_free(&ssl_client->entropy_ctx); } -int data_to_read(esp_mail_ssl_ctx32 *ssl_client) +int esp_mail_ssl_client32::data_to_read(esp_mail_ssl_ctx32 *ssl_client) { int ret, res; ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, NULL, 0); @@ -474,43 +445,33 @@ int data_to_read(esp_mail_ssl_ctx32 *ssl_client) if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) { if (ssl_client->_debugCallback) - { - char *buf = new char[512]; - char *error_buf = new char[100]; - memset(buf, 0, 512); - strcpy_P(buf, esp_ssl_client_str_1); - mbedtls_strerror(ret, error_buf, 100); - strcat(buf, error_buf); - ssl_client->_debugCallback(buf); - delete[] error_buf; - delete[] buf; - } + ssl_client_send_mbedtls_error_cb(ssl_client, ret); return handle_error(ret); } return res; } -int send_ssl_data(esp_mail_ssl_ctx32 *ssl_client, const uint8_t *data, uint16_t len) +int esp_mail_ssl_client32::send_ssl_data(esp_mail_ssl_ctx32 *ssl_client, const uint8_t *data, size_t len) { - - log_v("Writing HTTP request..."); //for low level debug + log_v("Writing HTTP request with %d bytes...", len); //for low level debug int ret = -1; while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) { + log_v("Handling error %d", ret); //for low level debug return handle_error(ret); } + //wait for space to become available + vTaskDelay(2); } - len = ret; - //log_v("%d bytes written", len); //for low level debug return ret; } -int get_ssl_receive(esp_mail_ssl_ctx32 *ssl_client, uint8_t *data, int length) +int esp_mail_ssl_client32::get_ssl_receive(esp_mail_ssl_ctx32 *ssl_client, uint8_t *data, int length) { //log_d( "Reading HTTP response..."); //for low level debug @@ -522,7 +483,7 @@ int get_ssl_receive(esp_mail_ssl_ctx32 *ssl_client, uint8_t *data, int length) return ret; } -static bool parseHexNibble(char pb, uint8_t *res) +bool esp_mail_ssl_client32::parseHexNibble(char pb, uint8_t *res) { if (pb >= '0' && pb <= '9') { @@ -543,7 +504,7 @@ static bool parseHexNibble(char pb, uint8_t *res) } // Compare a name from certificate and domain name, return true if they match -static bool matchName(const std::string &name, const std::string &domainName) +bool esp_mail_ssl_client32::matchName(const std::string &name, const std::string &domainName) { size_t wildcardPos = name.find('*'); if (wildcardPos == std::string::npos) @@ -574,7 +535,7 @@ static bool matchName(const std::string &name, const std::string &domainName) } // Verifies certificate provided by the peer to match specified SHA256 fingerprint -bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, const char *domain_name) +bool esp_mail_ssl_client32::verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, const char *domain_name) { // Convert hex string to byte array uint8_t fingerprint_local[32]; @@ -588,16 +549,12 @@ bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, cons } if (pos > len - 2) { - if (ssl_client->_debugCallback) - ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_23); log_d("pos:%d len:%d fingerprint too short", pos, len); return false; } uint8_t high, low; if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos + 1], &low)) { - if (ssl_client->_debugCallback) - ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_24); log_d("pos:%d len:%d invalid hex sequence: %c%c", pos, len, fp[pos], fp[pos + 1]); return false; } @@ -610,8 +567,6 @@ bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, cons if (!crt) { - if (ssl_client->_debugCallback) - ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_25); log_d("could not fetch peer certificate"); return false; } @@ -627,8 +582,6 @@ bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, cons // Check if fingerprints match if (memcmp(fingerprint_local, fingerprint_remote, 32)) { - if (ssl_client->_debugCallback) - ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_26); log_d("fingerprint doesn't match"); return false; } @@ -641,7 +594,7 @@ bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, cons } // Checks if peer certificate has specified domain in CN or SANs -bool verify_ssl_dn(esp_mail_ssl_ctx32 *ssl_client, const char *domain_name) +bool esp_mail_ssl_client32::verify_ssl_dn(esp_mail_ssl_ctx32 *ssl_client, const char *domain_name) { log_d("domain name: '%s'", (domain_name) ? domain_name : "(null)"); std::string domain_name_str(domain_name); @@ -688,12 +641,12 @@ bool verify_ssl_dn(esp_mail_ssl_ctx32 *ssl_client, const char *domain_name) return false; } -int _ns_lwip_write(esp_mail_ssl_ctx32 *ssl_client, const char *buf, int bufLen) +int esp_mail_ssl_client32::_ns_lwip_write(esp_mail_ssl_ctx32 *ssl_client, const char *buf, int bufLen) { return lwip_write(ssl_client->socket, buf, bufLen); } -int _ns_lwip_read(esp_mail_ssl_ctx32 *ssl_client, char *buf, int bufLen) +int esp_mail_ssl_client32::_ns_lwip_read(esp_mail_ssl_ctx32 *ssl_client, char *buf, int bufLen) { fd_set readset; fd_set writeset; @@ -719,17 +672,31 @@ int _ns_lwip_read(esp_mail_ssl_ctx32 *ssl_client, char *buf, int bufLen) return read(ssl_client->socket, buf, bufLen); } -void ssl_client_debug_pgm_send_cb(esp_mail_ssl_ctx32 *ssl_client, PGM_P info) +void esp_mail_ssl_client32::ssl_client_send_mbedtls_error_cb(esp_mail_ssl_ctx32 *ssl_client, int errNo) { - size_t dbgInfoLen = strlen_P(info) + 1; + char *buf = new char[512]; + char *error_buf = new char[100]; + memset(buf, 0, 512); + strcpy_P(buf, esp_ssl_client_str_1); + mbedtls_strerror(errNo, error_buf, 100); + strcat(buf, error_buf); + DebugMsgCallback cb = *ssl_client->_debugCallback; + cb(buf); + delete[] error_buf; + delete[] buf; +} + +void esp_mail_ssl_client32::ssl_client_debug_pgm_send_cb(esp_mail_ssl_ctx32 *ssl_client, PGM_P info) +{ + size_t dbgInfoLen = strlen_P(info) + 10; char *dbgInfo = new char[dbgInfoLen]; memset(dbgInfo, 0, dbgInfoLen); strcpy_P(dbgInfo, info); - - ssl_client->_debugCallback(dbgInfo); + DebugMsgCallback cb = *ssl_client->_debugCallback; + cb(dbgInfo); delete[] dbgInfo; } #endif //ESP32 -#endif //SSL_CLIENT32_CPP \ No newline at end of file +#endif //ESP_MAIL_SSL_CLIENT32_CPP \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.h b/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.h index 768d9697d..b0704d13f 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.h +++ b/lib/lib_div/lib_mail/src/wcs/esp32/esp_mail_ssl_client32.h @@ -1,5 +1,5 @@ /* - *Customized ssl_client.h to support STARTTLS protocol, version 1.0.5 + *Customized ssl_client.h to support STARTTLS protocol, version 1.0.8 * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) @@ -31,14 +31,14 @@ #define ESP_MAIL_SSL_CLIENT32_H #ifdef ESP32 - -#include -#include -#include -#include -#include -#include -#include +#include +#include "mbedtls/platform.h" +#include "mbedtls/net.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" static const char esp_ssl_client_str_1[] PROGMEM = "! E: "; static const char esp_ssl_client_str_2[] PROGMEM = "> C: starting socket"; @@ -57,49 +57,62 @@ static const char esp_ssl_client_str_14[] PROGMEM = "> C: set mbedtls config"; static const char esp_ssl_client_str_15[] PROGMEM = "> C: loading CRT cert"; static const char esp_ssl_client_str_16[] PROGMEM = "> C: loading private key"; static const char esp_ssl_client_str_17[] PROGMEM = "> C: setting hostname for TLS session"; -static const char esp_ssl_client_str_18[] PROGMEM = "> C: performing the SSL handshaking"; +static const char esp_ssl_client_str_18[] PROGMEM = "> C: performing the SSL/TLS handshake"; static const char esp_ssl_client_str_19[] PROGMEM = "> C: verifying peer X.509 certificate"; static const char esp_ssl_client_str_20[] PROGMEM = "! E: failed to verify peer certificate!"; static const char esp_ssl_client_str_21[] PROGMEM = "> C: certificate verified"; static const char esp_ssl_client_str_22[] PROGMEM = "> C: cleaning SSL connection"; -static const char esp_ssl_client_str_23[] PROGMEM = "!E: fingerprint too short"; -static const char esp_ssl_client_str_24[] PROGMEM = "!E: invalid hex sequence"; -static const char esp_ssl_client_str_25[] PROGMEM = "!E: could not fetch peer certificate"; -static const char esp_ssl_client_str_26[] PROGMEM = "!E: fingerprint doesn't match"; +static const char esp_ssl_client_str_23[] PROGMEM = "! E: fingerprint too short"; +static const char esp_ssl_client_str_24[] PROGMEM = "! E: invalid hex sequence"; +static const char esp_ssl_client_str_25[] PROGMEM = "! E: could not fetch peer certificate"; +static const char esp_ssl_client_str_26[] PROGMEM = "! E: fingerprint doesn't match"; +static const char esp_ssl_client_str_27[] PROGMEM = "! E: root certificate, PSK identity or keys are required for secured connection"; +static const char esp_ssl_client_str_28[] PROGMEM = "! W: Skipping SSL Verification. INSECURE!"; -typedef void (*DebugMsgCallback)(const char *msg); - -typedef struct esp_mail_ssl_ctx32 +class esp_mail_ssl_client32 { - int socket; - mbedtls_ssl_context ssl_ctx; - mbedtls_ssl_config ssl_conf; - mbedtls_net_context server_fd; +public: + esp_mail_ssl_client32(){}; - mbedtls_ctr_drbg_context drbg_ctx; - mbedtls_entropy_context entropy_ctx; + typedef void (*DebugMsgCallback)(const char *msg); - mbedtls_x509_crt ca_cert; - mbedtls_x509_crt client_cert; - mbedtls_pk_context client_key; - DebugMsgCallback _debugCallback; + typedef struct esp_mail_ssl_ctx32 + { + int socket; + mbedtls_ssl_context ssl_ctx; + mbedtls_ssl_config ssl_conf; - unsigned long handshake_timeout; -} esp_mail_ssl_ctx32; + mbedtls_ctr_drbg_context drbg_ctx; + mbedtls_entropy_context entropy_ctx; -void ssl_init(esp_mail_ssl_ctx32 *ssl_client); -int start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout); -int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey); -void stop_ssl_socket(esp_mail_ssl_ctx32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); -int data_to_read(esp_mail_ssl_ctx32 *ssl_client); -int send_ssl_data(esp_mail_ssl_ctx32 *ssl_client, const uint8_t *data, uint16_t len); -int get_ssl_receive(esp_mail_ssl_ctx32 *ssl_client, uint8_t *data, int length); -bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, const char *domain_name); -bool verify_ssl_dn(esp_mail_ssl_ctx32 *ssl_client, const char *domain_name); -int _ns_lwip_write(esp_mail_ssl_ctx32 *ssl_client, const char *buf, int bufLen); -int _ns_lwip_read(esp_mail_ssl_ctx32 *ssl_client, char *buf, int bufLen); -void ssl_client_debug_pgm_send_cb(esp_mail_ssl_ctx32 *ssl_client, PGM_P info); + mbedtls_x509_crt ca_cert; + mbedtls_x509_crt client_cert; + mbedtls_pk_context client_key; + DebugMsgCallback *_debugCallback = NULL; + + unsigned long handshake_timeout; + } esp_mail_ssl_ctx32; + + void ssl_init(esp_mail_ssl_ctx32 *ssl_client); + + int start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure); + int start_ssl_client(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure); + void stop_ssl_socket(esp_mail_ssl_ctx32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); + + int data_to_read(esp_mail_ssl_ctx32 *ssl_client); + int send_ssl_data(esp_mail_ssl_ctx32 *ssl_client, const uint8_t *data, size_t len); + int get_ssl_receive(esp_mail_ssl_ctx32 *ssl_client, uint8_t *data, int length); + bool verify_ssl_fingerprint(esp_mail_ssl_ctx32 *ssl_client, const char *fp, const char *domain_name); + bool verify_ssl_dn(esp_mail_ssl_ctx32 *ssl_client, const char *domain_name); + + int _ns_lwip_write(esp_mail_ssl_ctx32 *ssl_client, const char *buf, int bufLen); + int _ns_lwip_read(esp_mail_ssl_ctx32 *ssl_client, char *buf, int bufLen); + void ssl_client_send_mbedtls_error_cb(esp_mail_ssl_ctx32 *ssl_client, int errNo); + void ssl_client_debug_pgm_send_cb(esp_mail_ssl_ctx32 *ssl_client, PGM_P info); + bool parseHexNibble(char pb, uint8_t *res); + bool matchName(const std::string &name, const std::string &domainName); +}; #endif //ESP32 -#endif //SSL_CLIENT32_H +#endif //ESP_MAIL_SSL_CLIENT32_H diff --git a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.cpp b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.cpp index 02d50e04a..06a282e07 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.cpp +++ b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.cpp @@ -1,5 +1,5 @@ /* - * HTTP Client for ESP8266 wrapper v1.0.1 + * HTTP Client for ESP8266 wrapper v1.0.3 * * The MIT License (MIT) * Copyright (c) 2021 K. Suwatchai (Mobizt) @@ -187,6 +187,7 @@ bool ESP_Mail_HTTPClient::connect(bool secured) return connected(); } + void ESP_Mail_HTTPClient::setCACert(const char *caCert) { @@ -224,46 +225,29 @@ void ESP_Mail_HTTPClient::setCertFile(const char *caCertFile, esp_mail_file_stor if (_clockReady && strlen(caCertFile) > 0) { - if (storageType == 0) + fs::File f; + if (storageType == esp_mail_file_storage_type_flash) { - bool t = FLASH_FS.begin(); - if (t) - { - fs::File f; - if (FLASH_FS.exists(caCertFile)) - { - f = FLASH_FS.open(caCertFile, "r"); - size_t len = f.size(); - uint8_t *der = new uint8_t[len]; - - if (f.available()) - f.read(der, len); - - f.close(); - _wcs->setTrustAnchors(new ESP_Mail::ESP_Mail_X509List(der, len)); - delete[] der; - } - } + ESP_MAIL_FLASH_FS.begin(); + if (ESP_MAIL_FLASH_FS.exists(caCertFile)) + f = ESP_MAIL_FLASH_FS.open(caCertFile, "r"); } - else + else if (storageType == esp_mail_file_storage_type_sd) { - bool t = SD.begin(_sdPin); - if (t) - { - File f; - if (SD.exists(caCertFile)) - { - f = SD.open(caCertFile, FILE_READ); - size_t len = f.size(); - uint8_t *der = new uint8_t[len]; - if (f.available()) - f.read(der, len); + ESP_MAIL_SD_FS.begin(_sdPin); + if (ESP_MAIL_SD_FS.exists(caCertFile)) + f = ESP_MAIL_SD_FS.open(caCertFile, FILE_READ); + } - f.close(); - _wcs->setTrustAnchors(new ESP_Mail::ESP_Mail_X509List(der, len)); - delete[] der; - } - } + if (f) + { + size_t len = f.size(); + uint8_t *der = new uint8_t[len]; + if (f.available()) + f.read(der, len); + f.close(); + _wcs->setTrustAnchors(new ESP_Mail::ESP_Mail_X509List(der, len)); + delete[] der; } _certType = 2; } diff --git a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.h b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.h index ba032d212..71d623d2e 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.h +++ b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_HTTPClient.h @@ -1,20 +1,20 @@ /* - * HTTP Client for ESP8266 wrapper v1.0.1 - * + * HTTP Client for ESP8266 wrapper v1.0.3 + * * The MIT License (MIT) * Copyright (c) 2021 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 @@ -47,6 +47,9 @@ #include #include #include +#include + +#include "SDK_Version_Common.h" #ifndef ARDUINO_ESP8266_GIT_VER #error Your ESP8266 Arduino Core SDK is outdated, please update. From Arduino IDE go to Boards Manager and search 'esp8266' then select the latest version. @@ -65,16 +68,11 @@ #define FS_NO_GLOBALS #include #include -#include "extras/ESP_Mail_Client_FS.h" - -#ifdef USE_LITTLEFS -#include -#define FLASH_FS LittleFS -#else +#include "ESP_Mail_FS.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#define FLASH_FS SPIFFS -#endif +#define ESP_MAIL_FLASH_FS ESP_Mail_DEFAULT_FLASH_FS +#define ESP_MAIL_SD_FS ESP_Mail_DEFAULT_SD_FS #if __has_include() || __has_include() #error WiFi UART bridge was not supported. @@ -89,8 +87,7 @@ enum esp_mail_file_storage_type { esp_mail_file_storage_type_none, esp_mail_file_storage_type_flash, - esp_mail_file_storage_type_sd, - esp_mail_file_storage_type_univ + esp_mail_file_storage_type_sd }; class ESP_Mail_HTTPClient @@ -148,4 +145,4 @@ private: #endif /* ESP8266 */ -#endif /* ESP_Mail_HTTPClient_H */ +#endif /* ESP_Mail_HTTPClient_H */ \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.cpp b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.cpp index 606cba72a..f24adaef3 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.cpp +++ b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.cpp @@ -1,6 +1,6 @@ /* - Customized version of WiFiClientSecure.cpp - + Customized version of WiFiClientSecure.cpp v1.0.1 + WiFiClientBearSSL- SSL client/server for esp8266 using BearSSL libraries - Mostly compatible with Arduino WiFi shield library and standard WiFiClient/ServerSecure (except for certificate handling). @@ -53,9 +53,6 @@ extern "C" #include #include -//#define Optimistic_yield(A) optimistic_yield(A);ESP.wdtFeed(); -#define Optimistic_yield(A) optimistic_yield(A) - #if !CORE_MOCK // The BearSSL thunks in use for now @@ -262,7 +259,7 @@ namespace ESP_Mail return 0; } _host_name = name; - if (!_secured) + if (!_secured) return true; return _connectSSL(name); } @@ -318,7 +315,7 @@ namespace ESP_Mail // Ensure we yield if we need multiple fragments to avoid WDT if (sent_bytes) { - Optimistic_yield(1000); + optimistic_yield(1000); } // Get BearSSL to a state where we can send @@ -522,7 +519,7 @@ namespace ESP_Mail for (int no_work = 0; blocking || no_work < 2;) { - Optimistic_yield(100); + optimistic_yield(100); if (loopTimeout) { @@ -558,10 +555,10 @@ namespace ESP_Mail if (!blocking && len > availForWrite) { - /* + /* writes on WiFiClient will block if len > availableForWrite() this is needed to prevent available() calls from blocking - on dropped connections + on dropped connections */ len = availForWrite; } @@ -665,7 +662,7 @@ namespace ESP_Mail { _handshake_done = true; } - Optimistic_yield(1000); + optimistic_yield(1000); } return _handshake_done; } @@ -889,7 +886,6 @@ namespace ESP_Mail ctx->allow_self_signed = _allow_self_signed ? 1 : 0; } - // Some constants uses to init the server/client contexts // Note that suites_P needs to be copied to RAM before use w/BearSSL! // List copied verbatim from BearSSL/ssl_client_full.c @@ -2012,7 +2008,11 @@ namespace ESP_Mail return 0; } _client->setTimeout(_timeout); +#if defined(ESP8266_CORE_SDK_V3_X_X) + return _client->write((const char *)buf, size); +#else return _client->write(buf, size); +#endif } size_t ESP_Mail_WCS::_ns_write(Stream &stream, size_t unused) @@ -2028,17 +2028,32 @@ namespace ESP_Mail return 0; } _client->setTimeout(_timeout); +#if defined(ESP8266_CORE_SDK_V3_X_X) + size_t dl = stream.available(); + uint8_t buf[dl]; + stream.readBytes(buf, dl); + return _client->write((const char *)buf, dl); +#else return _client->write(stream); +#endif } size_t ESP_Mail_WCS::_ns_write_P(PGM_P buf, size_t size) { + if (!_client || !size) { return 0; } _client->setTimeout(_timeout); + +#if defined(ESP8266_CORE_SDK_V3_X_X) + char dest[size]; + memcpy_P((void *)dest, (PGM_VOID_P)buf, size); + return _client->write((const char *)dest, size); +#else return _client->write_P(buf, size); +#endif } int ESP_Mail_WCS::_ns_available() @@ -2050,7 +2065,7 @@ namespace ESP_Mail if (!result) { - Optimistic_yield(100); + optimistic_yield(100); } return result; } @@ -2119,4 +2134,4 @@ namespace ESP_Mail #endif /* ESP8266 */ -#endif /* ESP_Mail_WCS_CPP */ +#endif /* ESP_Mail_WCS_CPP */ \ No newline at end of file diff --git a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.h b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.h index 276129a32..aef48cc5e 100755 --- a/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.h +++ b/lib/lib_div/lib_mail/src/wcs/esp8266/ESP_Mail_WCS.h @@ -1,5 +1,5 @@ /* - Customized version of WiFiClientSecure.h + Customized version of WiFiClientSecure.h v1.0.1 WiFiClientBearSSL- SSL client/server for esp8266 using BearSSL libraries - Mostly compatible with Arduino WiFi shield library and standard @@ -32,7 +32,7 @@ #include #include "ESP_Mail_BearSSLHelpers.h" #include "ESP_Mail_CertStoreBearSSL.h" - +#include "SDK_Version_Common.h" namespace ESP_Mail {