mirror of https://github.com/arendst/Tasmota.git
update sendmail
This commit is contained in:
parent
e54487fd24
commit
218b5101b4
|
@ -0,0 +1,12 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ["https://www.paypal.me/mobizt"] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@ -0,0 +1,17 @@
|
|||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 20
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 5
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 mobizt
|
||||
Copyright (c) 2021 mobizt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
|
@ -0,0 +1,258 @@
|
|||
# Mail Client Arduino Library for ESP32 and ESP8266 v 1.0.13
|
||||
|
||||
[![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)
|
||||
|
||||
The complete and secure Mail Client for ESP32 and ESP8266 devices for sending and reading the Email through the SMTP and IMAP servers.
|
||||
|
||||
With this library, the devices can both send and read the Email with many types of attachments supported and provides more reliable and flexibilities of usages.
|
||||
|
||||
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)
|
||||
|
||||
Copyright (c) 2021 K. Suwatchai (Mobizt).
|
||||
|
||||
# Features
|
||||
|
||||
* 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 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).
|
||||
* Customizable operating configurations (see the examples for the usages)
|
||||
|
||||
## Tested Devices
|
||||
|
||||
This following devices were tested.
|
||||
|
||||
* Sparkfun ESP32 Thing
|
||||
* NodeMCU-32
|
||||
* WEMOS LOLIN32
|
||||
* TTGO T8 V1.8
|
||||
* M5Stack ESP32
|
||||
* NodeMCU ESP8266
|
||||
* Wemos D1 Mini (ESP8266)
|
||||
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
||||
The library requires Arduino's ESP32 or ESP8266 Core SDK to be installed based on the platform.
|
||||
|
||||
The latest Core SDK is recommended. For ESP8266, the Core SDK version 2.6.3 or later is recommended.
|
||||
|
||||
The ESP8266 Core SDK version 2.5.x and earlier are not supported.
|
||||
|
||||
|
||||
|
||||
## Instalation
|
||||
|
||||
|
||||
Click on **Clone or download** dropdown at the top of repository, select **Download ZIP** and save file on your computer.
|
||||
|
||||
From Arduino IDE, goto menu **Sketch** -> **Include Library** -> **Add .ZIP Library...** and choose **ESP-Mail-Client-master.zip** that previously downloaded.
|
||||
|
||||
Go to menu **Files** -> **Examples** -> **ESP-Mail-Client-master** and choose one from examples
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
See [Full Examples](/examples) for complete usages.
|
||||
|
||||
See [Function Description](/src/README.md) for all available functions.
|
||||
|
||||
|
||||
The following examples showed the minimum usage which many options are not configured.
|
||||
|
||||
The examples in the examples folder provide the full options usages.
|
||||
|
||||
|
||||
### Send the Email
|
||||
|
||||
|
||||
```C++
|
||||
|
||||
// Include ESP Mail Client library (this library)
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
|
||||
// Define the SMTP Session object which used for SMTP transsport
|
||||
SMTPSession smtp;
|
||||
|
||||
// Define the session config data which used to store the TCP session configuration
|
||||
ESP_Mail_Session session;
|
||||
|
||||
// Set the session config
|
||||
session.server.host_name = "smtp.office365.com"; //for outlook.com
|
||||
session.server.port = 587;
|
||||
session.login.email = "your Email address"; //set to empty for no SMTP Authentication
|
||||
session.login.password = "your Email password"; //set to empty for no SMTP Authentication
|
||||
session.login.user_domain = "client domain or ip e.g. mydomain.com";
|
||||
|
||||
// Define the SMTP_Message class variable to handle to message being transport
|
||||
SMTP_Message message;
|
||||
|
||||
// Set the message headers
|
||||
message.sender.name = "My Mail";
|
||||
message.sender.email = "sender or your Email address";
|
||||
message.subject = "Test sending Email";
|
||||
message.addRecipient("name1", "email1");
|
||||
message.addRecipient("name2", "email2");
|
||||
|
||||
message.addCc("email3");
|
||||
message.addBcc("email4");
|
||||
|
||||
// Set the message content
|
||||
message.text.content = "This is simple plain text message";
|
||||
|
||||
//Base64 data of image
|
||||
const char *greenImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RAQ0AMAgAoJviyWxtAtNYwzmoQGT/eqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBBaDPbQYiMoMAAAAASUVORK5CYII=";
|
||||
|
||||
// Define the attachment data
|
||||
SMTP_Attachment att;
|
||||
|
||||
// Set the attatchment info
|
||||
att.descr.filename = "green.png";
|
||||
att.descr.mime = "image/png";
|
||||
att.blob.data = (uint8_t *)greenImg;
|
||||
att.blob.size = strlen(greenImg);
|
||||
// Set the transfer encoding to base64
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
// We set the content encoding to match the above greenImage data
|
||||
att.descr.content_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
// Add attachment to the message
|
||||
message.addAttachment(att);
|
||||
|
||||
// Connect to server with the session config
|
||||
smtp.connect(&session);
|
||||
|
||||
// Start sending Email and close the session
|
||||
if (!MailClient.sendMail(&smtp, &message))
|
||||
Serial.println("Error sending Email, " + smtp.errorReason());
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Read the Email
|
||||
|
||||
|
||||
```C++
|
||||
|
||||
// Include ESP Mail Client library (this library)
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
|
||||
// Define the IMAP Session object which used for IMAP transsport
|
||||
IMAP_Config config;
|
||||
|
||||
|
||||
// Define the session config data which used to store the TCP session configuration
|
||||
ESP_Mail_Session session;
|
||||
|
||||
// Set the session config
|
||||
session.server.host_name = "outlook.office365.com"; //for outlook.com
|
||||
session.server.port = 993;
|
||||
session.login.email = "your Email address";
|
||||
session.login.password = "your Email password";
|
||||
|
||||
// Define the config class variable for searching or fetching operation and store the messsagess data
|
||||
IMAP_Config config;
|
||||
|
||||
// Define the message UID which required to fetch or read the message
|
||||
config.fetch.uid = "100";
|
||||
|
||||
// Define the empty search criteria to disable the messsage search
|
||||
config.search.criteria = "";
|
||||
|
||||
// Set to enable the message content which will be stored in the IMAP_Config data
|
||||
config.enable.html = true;
|
||||
config.enable.text = true;
|
||||
|
||||
|
||||
// Connect to the server with the defined session and options
|
||||
imap.connect(&session, &config);
|
||||
|
||||
// Open or select the mailbox folder to read the message
|
||||
imap.selectFolder("INBOX");
|
||||
|
||||
|
||||
// Read the Email and close the session
|
||||
MailClient.readMail(&imap);
|
||||
|
||||
|
||||
// Get the message(s) list
|
||||
IMAP_MSG_List msgList = imap.data();
|
||||
|
||||
for (size_t i = 0; i < msgList.msgItems.size(); i++)
|
||||
{
|
||||
// Iterate to get each message data through the message item data
|
||||
IMAP_MSG_Item msg = msgList.msgItems[i];
|
||||
|
||||
Serial.println("################################");
|
||||
Serial.printf("Messsage Number: %s\n", msg.msgNo);
|
||||
Serial.printf("Messsage UID: %s\n", msg.UID);
|
||||
Serial.printf("Messsage ID: %s\n", msg.ID);
|
||||
Serial.printf("Accept Language: %s\n", msg.acceptLang);
|
||||
Serial.printf("Content Language: %s\n", msg.contentLang);
|
||||
Serial.printf("From: %s\n", msg.from);
|
||||
Serial.printf("From Charset: %s\n", msg.fromCharset);
|
||||
Serial.printf("To: %s\n", msg.to);
|
||||
Serial.printf("To Charset: %s\n", msg.toCharset);
|
||||
Serial.printf("CC: %s\n", msg.cc);
|
||||
Serial.printf("CC Charset: %s\n", msg.ccCharset);
|
||||
Serial.printf("Date: %s\n", msg.date);
|
||||
Serial.printf("Subject: %s\n", msg.subject);
|
||||
Serial.printf("Subject Charset: %s\n", msg.subjectCharset);
|
||||
|
||||
// If the message body is available
|
||||
if (!imap.headerOnly())
|
||||
{
|
||||
Serial.printf("Text Message: %s\n", msg.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", msg.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", msg.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", msg.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## License
|
||||
|
||||
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
|
||||
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.
|
|
@ -0,0 +1 @@
|
|||
theme: jekyll-theme-cayman
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* This example showed how to copy messages from the opened mailbox folder to other folder.
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The log in credentials */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
#define AUTHOR_PASSWORD "################"
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.password = AUTHOR_PASSWORD;
|
||||
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* Define the MessageList class to add the message to copy */
|
||||
MessageList toCopy;
|
||||
|
||||
/* Add message uid to copy to the list */
|
||||
toCopy.add(3);
|
||||
toCopy.add(4);
|
||||
|
||||
//imap.createFolder("test");
|
||||
|
||||
/* Copy all messages in the list to the folder "test" */
|
||||
if (imap.deleteMessages(&toCopy, "test"))
|
||||
Serial.println("Messages copied");
|
||||
|
||||
/* Delete all messages in the list from the opened folder (move to trash) */
|
||||
//imap.deleteMessages(&toCopy);
|
||||
|
||||
//imap.deleteolder("test");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* This example showed how to delete messages from the opened mailbox folder.
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The log in credentials */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
#define AUTHOR_PASSWORD "################"
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.password = AUTHOR_PASSWORD;
|
||||
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* Define the MessageList class to add the message to delete */
|
||||
MessageList toDelete;
|
||||
/* Add message uid to delete to the list */
|
||||
toDelete.add(10);
|
||||
toDelete.add(12);
|
||||
|
||||
/* Delete all messages in the list (move to trash) */
|
||||
if(imap.deleteMessages(&toDelete))
|
||||
Serial.println("Messages deeted");
|
||||
|
||||
/* Delete all messages permanently by assign the second param to true*/
|
||||
//imap.deleteMessages(&toDelete, true);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,370 @@
|
|||
/**
|
||||
* This example will log in with the SASL XOAUTH2 mechanisme using OAuth2.0 access token.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The user Email for OAuth2.0 access token */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
|
||||
/** The OAuth2.0 access token
|
||||
* The generation, exchange and refresh of the access token are not available
|
||||
* in this library.
|
||||
*
|
||||
* To test this using GMail, get the OAuth2.0 access token from this web site
|
||||
* https://developers.google.com/oauthplayground/
|
||||
*
|
||||
* 1. Select the following scope (in Step 1) from Gmail API V1
|
||||
* https://mail.google.com/
|
||||
* https://mail.google.com/
|
||||
*
|
||||
* 2. Click Authorize APIs button.
|
||||
* 3. Cick Exchangeauthorization code for tokens.
|
||||
* 4. From the response, look at access_token from the JSON payload node.
|
||||
* 5. Copy that access token and paste to the AUTHOR_ACCESS_TOKEN value.
|
||||
*
|
||||
* The token will be expired in 3600 seconds (1 Hr).
|
||||
* The AUTHOR_EMAIL above is the Email address that you granted to access the Gmail services.
|
||||
*/
|
||||
#define AUTHOR_ACCESS_TOKEN "################"
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status);
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* Print all messages from the message list */
|
||||
void printMessages(IMAPSession &imap);
|
||||
|
||||
/* Print all rfc822 messages included in the message */
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg);
|
||||
|
||||
/* Print all attachments info from the message */
|
||||
void printAttacements(IMAP_MSG_Item &msg);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Set the callback function to get the reading results */
|
||||
imap.callback(imapCallback);
|
||||
|
||||
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
|
||||
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
|
||||
* For ESP32, assign all of SPI pins
|
||||
* MailClient.sdBegin(14,2,15,13)
|
||||
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
|
||||
* And for ESP8266, assign the CS pins of SPI port
|
||||
* MailClient.sdBegin(15)
|
||||
* Which pin 15 is the CS pin of SD card adapter
|
||||
*/
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.accessToken = AUTHOR_ACCESS_TOKEN;
|
||||
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
/* Message UID to fetch or read e.g. 100 */
|
||||
config.fetch.uid = "100";
|
||||
|
||||
/* Set seen flag*/
|
||||
//config.fetch.set_seen = true;
|
||||
|
||||
/* Search criteria */
|
||||
config.search.criteria = "";
|
||||
|
||||
/* Also search the unseen message */
|
||||
config.search.unseen_msg = true;
|
||||
|
||||
/* Set the storage to save the downloaded files and attachments */
|
||||
config.storage.saved_path = "/email_data";
|
||||
|
||||
/** The file storage type e.g.
|
||||
* esp_mail_file_storage_type_none,
|
||||
* esp_mail_file_storage_type_flash, and
|
||||
* esp_mail_file_storage_type_sd
|
||||
*/
|
||||
config.storage.type = esp_mail_file_storage_type_flash;
|
||||
|
||||
/** Set to download heades, text and html messaeges,
|
||||
* attachments and inline images respectively.
|
||||
*/
|
||||
config.download.header = true;
|
||||
config.download.text = true;
|
||||
config.download.html = true;
|
||||
config.download.attachment = true;
|
||||
config.download.inlineImg = true;
|
||||
|
||||
/** Set to enable the results i.e. html and text messaeges
|
||||
* which the content stored in the IMAPSession object is limited
|
||||
* by the option config.limit.msg_size.
|
||||
* The whole message can be download through config.download.text
|
||||
* or config.download.html which not depends on these enable options.
|
||||
*/
|
||||
config.enable.html = true;
|
||||
config.enable.text = true;
|
||||
|
||||
/* Set to enable the sort the result by message UID in the ascending order */
|
||||
config.enable.recent_sort = true;
|
||||
|
||||
/* Set to report the download progress via the default serial port */
|
||||
config.enable.download_status = true;
|
||||
|
||||
/* Set the limit of number of messages in the search results */
|
||||
config.limit.search = 5;
|
||||
|
||||
/** Set the maximum size of message stored in
|
||||
* IMAPSession object in byte
|
||||
*/
|
||||
config.limit.msg_size = 512;
|
||||
|
||||
/** Set the maximum attachments and inline images files size
|
||||
* that can be downloaded in byte.
|
||||
* The file which its size is largger than this limit may be saved
|
||||
* as truncated file.
|
||||
*/
|
||||
config.limit.attachment_size = 1024 * 1024 * 5;
|
||||
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printSelectedMailboxInfo(imap);
|
||||
|
||||
/* Read or search the Email and close the session */
|
||||
MailClient.readMail(&imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status)
|
||||
{
|
||||
/* Print the current status */
|
||||
Serial.println(status.info());
|
||||
|
||||
/* Show the result when reading finished */
|
||||
if (status.success())
|
||||
{
|
||||
/* Print the result */
|
||||
printMessages(imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
Serial.printf("Free Heap: %d", ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
|
||||
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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectedMailboxInfo(IMAPSession &imap)
|
||||
{
|
||||
/* Declare the selected folder info class to get the info of selected mailbox folder */
|
||||
SelectedFolderInfo sFolder = imap.selectedFolder();
|
||||
|
||||
/* Show the mailbox info */
|
||||
Serial.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
|
||||
Serial.printf("Predicted next UID: %d\n", sFolder.nextUID());
|
||||
for (size_t i = 0; i < sFolder.flagCount(); i++)
|
||||
Serial.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
|
||||
for (size_t j = 0; j < msg.rfc822.size(); j++)
|
||||
{
|
||||
IMAP_MSG_Item rfc822 = msg.rfc822[j];
|
||||
Serial.printf("%d. \n", j + 1);
|
||||
Serial.printf("Messsage ID: %s\n", rfc822.messageID);
|
||||
Serial.printf("From: %s\n", rfc822.from);
|
||||
Serial.printf("Sender: %s\n", rfc822.sender);
|
||||
Serial.printf("To: %s\n", rfc822.to);
|
||||
Serial.printf("CC: %s\n", rfc822.cc);
|
||||
Serial.printf("Subject: %s\n", rfc822.subject);
|
||||
Serial.printf("Date: %s\n", rfc822.date);
|
||||
Serial.printf("Reply-To: %s\n", rfc822.reply_to);
|
||||
Serial.printf("Return-Path: %s\n", rfc822.return_path);
|
||||
Serial.printf("Comment: %s\n", rfc822.comment);
|
||||
Serial.printf("Keyword: %s\n", rfc822.keyword);
|
||||
Serial.printf("Text Message: %s\n", rfc822.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", rfc822.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", rfc822.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", rfc822.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", rfc822.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", rfc822.html.transfer_encoding);
|
||||
|
||||
if (rfc822.attachments.size() > 0)
|
||||
printAttacements(rfc822);
|
||||
}
|
||||
}
|
||||
|
||||
void printAttacements(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("Attachment: %d file(s)\n****************************\n", msg.attachments.size());
|
||||
for (size_t j = 0; j < msg.attachments.size(); j++)
|
||||
{
|
||||
IMAP_Attach_Item att = msg.attachments[j];
|
||||
/** att.type can be
|
||||
* esp_mail_att_type_none or 0
|
||||
* esp_mail_att_type_attachment or 1
|
||||
* esp_mail_att_type_inline or 2
|
||||
*/
|
||||
Serial.printf("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.creationDate);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printMessages(IMAPSession &imap)
|
||||
{
|
||||
/* Get the message list from the message list data */
|
||||
IMAP_MSG_List msgList = imap.data();
|
||||
|
||||
for (size_t i = 0; i < msgList.msgItems.size(); i++)
|
||||
{
|
||||
/* Iterate to get each message data through the message item data */
|
||||
IMAP_MSG_Item msg = msgList.msgItems[i];
|
||||
|
||||
Serial.println("################################");
|
||||
Serial.printf("Messsage Number: %s\n", msg.msgNo);
|
||||
Serial.printf("Messsage UID: %s\n", msg.UID);
|
||||
Serial.printf("Messsage ID: %s\n", msg.ID);
|
||||
Serial.printf("Accept Language: %s\n", msg.acceptLang);
|
||||
Serial.printf("Content Language: %s\n", msg.contentLang);
|
||||
Serial.printf("From: %s\n", msg.from);
|
||||
Serial.printf("From Charset: %s\n", msg.fromCharset);
|
||||
Serial.printf("To: %s\n", msg.to);
|
||||
Serial.printf("To Charset: %s\n", msg.toCharset);
|
||||
Serial.printf("CC: %s\n", msg.cc);
|
||||
Serial.printf("CC Charset: %s\n", msg.ccCharset);
|
||||
Serial.printf("Date: %s\n", msg.date);
|
||||
Serial.printf("Subject: %s\n", msg.subject);
|
||||
Serial.printf("Subject Charset: %s\n", msg.subjectCharset);
|
||||
|
||||
/* If the result contains the message info (Fetch mode) */
|
||||
if (!imap.headerOnly())
|
||||
{
|
||||
Serial.printf("Text Message: %s\n", msg.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", msg.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", msg.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", msg.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
|
||||
|
||||
if (msg.attachments.size() > 0)
|
||||
printAttacements(msg);
|
||||
|
||||
if (msg.rfc822.size() > 0)
|
||||
printRFC822Messages(msg);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,349 @@
|
|||
/**
|
||||
* This example will fetch or read the Email which the known message UID
|
||||
* was used for fetching.
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The log in credentials */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
#define AUTHOR_PASSWORD "################"
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status);
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* Print all messages from the message list */
|
||||
void printMessages(IMAPSession &imap);
|
||||
|
||||
/* Print all rfc822 messages included in the message */
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg);
|
||||
|
||||
/* Print all attachments info from the message */
|
||||
void printAttacements(IMAP_MSG_Item &msg);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Set the callback function to get the reading results */
|
||||
imap.callback(imapCallback);
|
||||
|
||||
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
|
||||
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
|
||||
* For ESP32, assign all of SPI pins
|
||||
* MailClient.sdBegin(14,2,15,13)
|
||||
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
|
||||
* And for ESP8266, assign the CS pins of SPI port
|
||||
* MailClient.sdBegin(15)
|
||||
* Which pin 15 is the CS pin of SD card adapter
|
||||
*/
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.password = AUTHOR_PASSWORD;
|
||||
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
/* Message UID to fetch or read e.g. 100 */
|
||||
config.fetch.uid = "100";
|
||||
|
||||
/* Set seen flag */
|
||||
//config.fetch.set_seen = true;
|
||||
|
||||
/* Search criteria */
|
||||
config.search.criteria = "";
|
||||
|
||||
/* Also search the unseen message */
|
||||
config.search.unseen_msg = true;
|
||||
|
||||
/* Set the storage to save the downloaded files and attachments */
|
||||
config.storage.saved_path = "/email_data";
|
||||
|
||||
/** The file storage type e.g.
|
||||
* esp_mail_file_storage_type_none,
|
||||
* esp_mail_file_storage_type_flash, and
|
||||
* esp_mail_file_storage_type_sd
|
||||
*/
|
||||
config.storage.type = esp_mail_file_storage_type_flash;
|
||||
|
||||
/** Set to download heades, text and html messaeges,
|
||||
* attachments and inline images respectively.
|
||||
*/
|
||||
config.download.header = true;
|
||||
config.download.text = true;
|
||||
config.download.html = true;
|
||||
config.download.attachment = true;
|
||||
config.download.inlineImg = true;
|
||||
|
||||
/** Set to enable the results i.e. html and text messaeges
|
||||
* which the content stored in the IMAPSession object is limited
|
||||
* by the option config.limit.msg_size.
|
||||
* The whole message can be download through config.download.text
|
||||
* or config.download.html which not depends on these enable options.
|
||||
*/
|
||||
config.enable.html = true;
|
||||
config.enable.text = true;
|
||||
|
||||
/* Set to enable the sort the result by message UID in the ascending order */
|
||||
config.enable.recent_sort = true;
|
||||
|
||||
/* Set to report the download progress via the default serial port */
|
||||
config.enable.download_status = true;
|
||||
|
||||
/* Set the limit of number of messages in the search results */
|
||||
config.limit.search = 5;
|
||||
|
||||
/** Set the maximum size of message stored in
|
||||
* IMAPSession object in byte
|
||||
*/
|
||||
config.limit.msg_size = 512;
|
||||
|
||||
/** Set the maximum attachments and inline images files size
|
||||
* that can be downloaded in byte.
|
||||
* The file which its size is largger than this limit may be saved
|
||||
* as truncated file.
|
||||
*/
|
||||
config.limit.attachment_size = 1024 * 1024 * 5;
|
||||
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printSelectedMailboxInfo(imap);
|
||||
|
||||
/* Read or search the Email and close the session */
|
||||
MailClient.readMail(&imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status)
|
||||
{
|
||||
/* Print the current status */
|
||||
Serial.println(status.info());
|
||||
|
||||
/* Show the result when reading finished */
|
||||
if (status.success())
|
||||
{
|
||||
/* Print the result */
|
||||
printMessages(imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
Serial.printf("Free Heap: %d", ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
|
||||
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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectedMailboxInfo(IMAPSession &imap)
|
||||
{
|
||||
/* Declare the selected folder info class to get the info of selected mailbox folder */
|
||||
SelectedFolderInfo sFolder = imap.selectedFolder();
|
||||
|
||||
/* Show the mailbox info */
|
||||
Serial.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
|
||||
Serial.printf("Predicted next UID: %d\n", sFolder.nextUID());
|
||||
for (size_t i = 0; i < sFolder.flagCount(); i++)
|
||||
Serial.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
|
||||
for (size_t j = 0; j < msg.rfc822.size(); j++)
|
||||
{
|
||||
IMAP_MSG_Item rfc822 = msg.rfc822[j];
|
||||
Serial.printf("%d. \n", j + 1);
|
||||
Serial.printf("Messsage ID: %s\n", rfc822.messageID);
|
||||
Serial.printf("From: %s\n", rfc822.from);
|
||||
Serial.printf("Sender: %s\n", rfc822.sender);
|
||||
Serial.printf("To: %s\n", rfc822.to);
|
||||
Serial.printf("CC: %s\n", rfc822.cc);
|
||||
Serial.printf("Subject: %s\n", rfc822.subject);
|
||||
Serial.printf("Date: %s\n", rfc822.date);
|
||||
Serial.printf("Reply-To: %s\n", rfc822.reply_to);
|
||||
Serial.printf("Return-Path: %s\n", rfc822.return_path);
|
||||
Serial.printf("Comment: %s\n", rfc822.comment);
|
||||
Serial.printf("Keyword: %s\n", rfc822.keyword);
|
||||
Serial.printf("Text Message: %s\n", rfc822.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", rfc822.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", rfc822.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", rfc822.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", rfc822.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", rfc822.html.transfer_encoding);
|
||||
|
||||
if (rfc822.attachments.size() > 0)
|
||||
printAttacements(rfc822);
|
||||
}
|
||||
}
|
||||
|
||||
void printAttacements(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("Attachment: %d file(s)\n****************************\n", msg.attachments.size());
|
||||
for (size_t j = 0; j < msg.attachments.size(); j++)
|
||||
{
|
||||
IMAP_Attach_Item att = msg.attachments[j];
|
||||
/** att.type can be
|
||||
* esp_mail_att_type_none or 0
|
||||
* esp_mail_att_type_attachment or 1
|
||||
* esp_mail_att_type_inline or 2
|
||||
*/
|
||||
Serial.printf("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.creationDate);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printMessages(IMAPSession &imap)
|
||||
{
|
||||
/* Get the message list from the message list data */
|
||||
IMAP_MSG_List msgList = imap.data();
|
||||
|
||||
for (size_t i = 0; i < msgList.msgItems.size(); i++)
|
||||
{
|
||||
/* Iterate to get each message data through the message item data */
|
||||
IMAP_MSG_Item msg = msgList.msgItems[i];
|
||||
|
||||
Serial.println("################################");
|
||||
Serial.printf("Messsage Number: %s\n", msg.msgNo);
|
||||
Serial.printf("Messsage UID: %s\n", msg.UID);
|
||||
Serial.printf("Messsage ID: %s\n", msg.ID);
|
||||
Serial.printf("Accept Language: %s\n", msg.acceptLang);
|
||||
Serial.printf("Content Language: %s\n", msg.contentLang);
|
||||
Serial.printf("From: %s\n", msg.from);
|
||||
Serial.printf("From Charset: %s\n", msg.fromCharset);
|
||||
Serial.printf("To: %s\n", msg.to);
|
||||
Serial.printf("To Charset: %s\n", msg.toCharset);
|
||||
Serial.printf("CC: %s\n", msg.cc);
|
||||
Serial.printf("CC Charset: %s\n", msg.ccCharset);
|
||||
Serial.printf("Date: %s\n", msg.date);
|
||||
Serial.printf("Subject: %s\n", msg.subject);
|
||||
Serial.printf("Subject Charset: %s\n", msg.subjectCharset);
|
||||
|
||||
/* If the result contains the message info (Fetch mode) */
|
||||
if (!imap.headerOnly())
|
||||
{
|
||||
Serial.printf("Text Message: %s\n", msg.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", msg.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", msg.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", msg.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
|
||||
|
||||
if (msg.attachments.size() > 0)
|
||||
printAttacements(msg);
|
||||
|
||||
if (msg.rfc822.size() > 0)
|
||||
printRFC822Messages(msg);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
/**
|
||||
* This example will repeatedly fetch or read the Email via the loop function
|
||||
* using the predict next message UID as the starting count down message UID.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The log in credentials */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
#define AUTHOR_PASSWORD "################"
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status);
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* Print all messages from the message list */
|
||||
void printMessages(IMAPSession &imap);
|
||||
|
||||
/* Print all rfc822 messages included in the message */
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg);
|
||||
|
||||
/* Print all attachments info from the message */
|
||||
void printAttacements(IMAP_MSG_Item &msg);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
unsigned long readMillis = 0;
|
||||
|
||||
int nextMsgUID = 0;
|
||||
int msgUID = 0;
|
||||
int sign = -1;
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Set the callback function to get the reading results */
|
||||
imap.callback(imapCallback);
|
||||
|
||||
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
|
||||
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
|
||||
* For ESP32, assign all of SPI pins
|
||||
* MailClient.sdBegin(14,2,15,13)
|
||||
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
|
||||
* And for ESP8266, assign the CS pins of SPI port
|
||||
* MailClient.sdBegin(15)
|
||||
* Which pin 15 is the CS pin of SD card adapter
|
||||
*/
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.password = AUTHOR_PASSWORD;
|
||||
|
||||
|
||||
/* Message UID to fetch or read */
|
||||
config.fetch.uid = "";
|
||||
|
||||
/* Search criteria */
|
||||
config.search.criteria = "";
|
||||
|
||||
/* Also search the unseen message */
|
||||
config.search.unseen_msg = true;
|
||||
|
||||
/* Set the storage to save the downloaded files and attachments */
|
||||
config.storage.saved_path = "/email_data";
|
||||
|
||||
/** The file storage type e.g.
|
||||
* esp_mail_file_storage_type_none,
|
||||
* esp_mail_file_storage_type_flash, and
|
||||
* esp_mail_file_storage_type_sd
|
||||
*/
|
||||
config.storage.type = esp_mail_file_storage_type_flash;
|
||||
|
||||
/** Set to download heades, text and html messaeges,
|
||||
* attachments and inline images respectively.
|
||||
*/
|
||||
config.download.header = false;
|
||||
config.download.text = false;
|
||||
config.download.html = false;
|
||||
config.download.attachment = false;
|
||||
config.download.inlineImg = false;
|
||||
|
||||
/** Set to enable the results i.e. html and text messaeges
|
||||
* which the content stored in the IMAPSession object is limited
|
||||
* by the option config.limit.msg_size.
|
||||
* The whole message can be download through config.download.text
|
||||
* or config.download.html which not depends on these enable options.
|
||||
*/
|
||||
config.enable.html = true;
|
||||
config.enable.text = true;
|
||||
|
||||
/* Set to enable the sort the result by message UID in the ascending order */
|
||||
config.enable.recent_sort = true;
|
||||
|
||||
/* Set to report the download progress via the default serial port */
|
||||
config.enable.download_status = true;
|
||||
|
||||
/* Set the limit of number of messages in the search results */
|
||||
config.limit.search = 5;
|
||||
|
||||
/** Set the maximum size of message stored in
|
||||
* IMAPSession object in byte
|
||||
*/
|
||||
config.limit.msg_size = 512;
|
||||
|
||||
/** Set the maximum attachments and inline images files size
|
||||
* that can be downloaded in byte.
|
||||
* The file which its size is largger than this limit may be saved
|
||||
* as truncated file.
|
||||
*/
|
||||
config.limit.attachment_size = 1024 * 1024 * 5;
|
||||
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printSelectedMailboxInfo(imap);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (millis() - readMillis > 10000 || readMillis == 0)
|
||||
{
|
||||
readMillis = millis();
|
||||
|
||||
if (msgUID == 0)
|
||||
sign = 1;
|
||||
else if (msgUID >= nextMsgUID)
|
||||
sign = -1;
|
||||
|
||||
msgUID += sign;
|
||||
|
||||
String uid = String(msgUID);
|
||||
|
||||
/* Message UID to fetch or read */
|
||||
config.fetch.uid = uid.c_str();
|
||||
|
||||
/* Set seen flag */
|
||||
//config.fetch.set_seen = true;
|
||||
|
||||
/** Read or search the Email and keep the TCP session to open
|
||||
* The second parameter is for close the session.
|
||||
*/
|
||||
MailClient.readMail(&imap, false);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status)
|
||||
{
|
||||
/* Print the current status */
|
||||
Serial.println(status.info());
|
||||
|
||||
/* Show the result when reading finished */
|
||||
if (status.success())
|
||||
{
|
||||
/* Print the result */
|
||||
printMessages(imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
Serial.printf("Free Heap: %d", ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
|
||||
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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectedMailboxInfo(IMAPSession &imap)
|
||||
{
|
||||
/* Declare the selected folder info class to get the info of selected mailbox folder */
|
||||
SelectedFolderInfo sFolder = imap.selectedFolder();
|
||||
|
||||
nextMsgUID = sFolder.nextUID();
|
||||
msgUID = nextMsgUID;
|
||||
|
||||
/* Show the mailbox info */
|
||||
Serial.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
|
||||
Serial.printf("Predicted next UID: %d\n", sFolder.nextUID());
|
||||
for (size_t i = 0; i < sFolder.flagCount(); i++)
|
||||
Serial.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
|
||||
for (size_t j = 0; j < msg.rfc822.size(); j++)
|
||||
{
|
||||
IMAP_MSG_Item rfc822 = msg.rfc822[j];
|
||||
Serial.printf("%d. \n", j + 1);
|
||||
Serial.printf("Messsage ID: %s\n", rfc822.messageID);
|
||||
Serial.printf("From: %s\n", rfc822.from);
|
||||
Serial.printf("Sender: %s\n", rfc822.sender);
|
||||
Serial.printf("To: %s\n", rfc822.to);
|
||||
Serial.printf("CC: %s\n", rfc822.cc);
|
||||
Serial.printf("Subject: %s\n", rfc822.subject);
|
||||
Serial.printf("Date: %s\n", rfc822.date);
|
||||
Serial.printf("Reply-To: %s\n", rfc822.reply_to);
|
||||
Serial.printf("Return-Path: %s\n", rfc822.return_path);
|
||||
Serial.printf("Comment: %s\n", rfc822.comment);
|
||||
Serial.printf("Keyword: %s\n", rfc822.keyword);
|
||||
Serial.printf("Text Message: %s\n", rfc822.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", rfc822.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", rfc822.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", rfc822.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", rfc822.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", rfc822.html.transfer_encoding);
|
||||
|
||||
if (rfc822.attachments.size() > 0)
|
||||
printAttacements(rfc822);
|
||||
}
|
||||
}
|
||||
|
||||
void printAttacements(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("Attachment: %d file(s)\n****************************\n", msg.attachments.size());
|
||||
for (size_t j = 0; j < msg.attachments.size(); j++)
|
||||
{
|
||||
IMAP_Attach_Item att = msg.attachments[j];
|
||||
/** att.type can be
|
||||
* esp_mail_att_type_none or 0
|
||||
* esp_mail_att_type_attachment or 1
|
||||
* esp_mail_att_type_inline or 2
|
||||
*/
|
||||
Serial.printf("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.creationDate);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printMessages(IMAPSession &imap)
|
||||
{
|
||||
/* Get the message list from the message list data */
|
||||
IMAP_MSG_List msgList = imap.data();
|
||||
|
||||
for (size_t i = 0; i < msgList.msgItems.size(); i++)
|
||||
{
|
||||
/* Iterate to get each message data through the message item data */
|
||||
IMAP_MSG_Item msg = msgList.msgItems[i];
|
||||
|
||||
Serial.println("################################");
|
||||
Serial.printf("Messsage Number: %s\n", msg.msgNo);
|
||||
Serial.printf("Messsage UID: %s\n", msg.UID);
|
||||
Serial.printf("Messsage ID: %s\n", msg.ID);
|
||||
Serial.printf("Accept Language: %s\n", msg.acceptLang);
|
||||
Serial.printf("Content Language: %s\n", msg.contentLang);
|
||||
Serial.printf("From: %s\n", msg.from);
|
||||
Serial.printf("From Charset: %s\n", msg.fromCharset);
|
||||
Serial.printf("To: %s\n", msg.to);
|
||||
Serial.printf("To Charset: %s\n", msg.toCharset);
|
||||
Serial.printf("CC: %s\n", msg.cc);
|
||||
Serial.printf("CC Charset: %s\n", msg.ccCharset);
|
||||
Serial.printf("Date: %s\n", msg.date);
|
||||
Serial.printf("Subject: %s\n", msg.subject);
|
||||
Serial.printf("Subject Charset: %s\n", msg.subjectCharset);
|
||||
|
||||
/* If the result contains the message info (Fetch mode) */
|
||||
if (!imap.headerOnly())
|
||||
{
|
||||
Serial.printf("Text Message: %s\n", msg.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", msg.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", msg.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", msg.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
|
||||
|
||||
if (msg.attachments.size() > 0)
|
||||
printAttacements(msg);
|
||||
|
||||
if (msg.rfc822.size() > 0)
|
||||
printRFC822Messages(msg);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,387 @@
|
|||
/**
|
||||
* This example will search all Emails in the opened mailbox folder.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The log in credentials */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
#define AUTHOR_PASSWORD "################"
|
||||
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status);
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* Print all messages from the message list */
|
||||
void printMessages(IMAPSession &imap);
|
||||
|
||||
/* Print all rfc822 messages included in the message */
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg);
|
||||
|
||||
/* Print all attachments info from the message */
|
||||
void printAttacements(IMAP_MSG_Item &msg);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Set the callback function to get the reading results */
|
||||
imap.callback(imapCallback);
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
|
||||
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
|
||||
* For ESP32, assign all of SPI pins
|
||||
* MailClient.sdBegin(14,2,15,13)
|
||||
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
|
||||
* And for ESP8266, assign the CS pins of SPI port
|
||||
* MailClient.sdBegin(15)
|
||||
* Which pin 15 is the CS pin of SD card adapter
|
||||
*/
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.password = AUTHOR_PASSWORD;
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
/* Message UID to fetch or read */
|
||||
config.fetch.uid = "";
|
||||
|
||||
/** Search criteria
|
||||
*
|
||||
* A search key can also be a parenthesized list of one or more search keys
|
||||
* (e.g., for use with the OR and NOT keys).
|
||||
*
|
||||
* Since IMAP protocol uses Polish notation, the search criteria which in the polish notation form can be.
|
||||
*
|
||||
* To search the message from "someone@email.com" with the subject "my subject" since 1 Jan 2021, your search criteria can be
|
||||
* UID SEARCH (OR SUBJECT "my subject" FROM "someone@email.com") SINCE "Fri, 1 Jan 2021 21:52:25 -0800"
|
||||
*
|
||||
* To search the message from "mail1@domain.com" or from "mail2@domain.com", the search criteria will be
|
||||
* UID SEARCH OR FROM mail1@domain.com FROM mail2@domain.com
|
||||
*
|
||||
* For more details on using parentheses, AND, OR and NOT search keys in search criteria.
|
||||
* https://www.limilabs.com/blog/imap-search-requires-parentheses
|
||||
*
|
||||
*
|
||||
*/
|
||||
config.search.criteria = "UID SEARCH ALL";
|
||||
|
||||
/* Also search the unseen message */
|
||||
config.search.unseen_msg = true;
|
||||
|
||||
/* Set the storage to save the downloaded files and attachments */
|
||||
config.storage.saved_path = "/email_data";
|
||||
|
||||
/** The file storage type e.g.
|
||||
* esp_mail_file_storage_type_none,
|
||||
* esp_mail_file_storage_type_flash, and
|
||||
* esp_mail_file_storage_type_sd
|
||||
*/
|
||||
config.storage.type = esp_mail_file_storage_type_flash;
|
||||
|
||||
/** Set to download heades, text and html messaeges,
|
||||
* attachments and inline images respectively.
|
||||
*/
|
||||
config.download.header = true;
|
||||
config.download.text = true;
|
||||
config.download.html = true;
|
||||
config.download.attachment = true;
|
||||
config.download.inlineImg = true;
|
||||
|
||||
/** Set to enable the results i.e. html and text messaeges
|
||||
* which the content stored in the IMAPSession object is limited
|
||||
* by the option config.limit.msg_size.
|
||||
* The whole message can be download through config.download.text
|
||||
* or config.download.html which not depends on these enable options.
|
||||
*/
|
||||
config.enable.html = true;
|
||||
config.enable.text = true;
|
||||
|
||||
/* Set to enable the sort the result by message UID in the ascending order */
|
||||
config.enable.recent_sort = true;
|
||||
|
||||
/* Set to report the download progress via the default serial port */
|
||||
config.enable.download_status = true;
|
||||
|
||||
/* Set the limit of number of messages in the search results */
|
||||
config.limit.search = 5;
|
||||
|
||||
/** Set the maximum size of message stored in
|
||||
* IMAPSession object in byte
|
||||
*/
|
||||
config.limit.msg_size = 512;
|
||||
|
||||
/** Set the maximum attachments and inline images files size
|
||||
* that can be downloaded in byte.
|
||||
* The file which its size is largger than this limit may be saved
|
||||
* as truncated file.
|
||||
*/
|
||||
config.limit.attachment_size = 1024 * 1024 * 5;
|
||||
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printSelectedMailboxInfo(imap);
|
||||
|
||||
/** Read or search the Email and keep the TCP session to open
|
||||
* The second parameter is for close the session.
|
||||
*/
|
||||
MailClient.readMail(&imap, false);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
|
||||
/** Open or select other mailbox folder
|
||||
* The folder that previousely opened will be closed
|
||||
*/
|
||||
if (imap.selectFolder("Junk"))
|
||||
{
|
||||
/* {Optional] */
|
||||
printSelectedMailboxInfo(imap);
|
||||
|
||||
/* Config to search all messages in the opened mailboax (Search mode) */
|
||||
config.search.criteria = "UID SEARCH ALL";
|
||||
|
||||
/* No message UID provide for fetching */
|
||||
config.fetch.uid = "";
|
||||
|
||||
/* Search the Email and close the session */
|
||||
MailClient.readMail(&imap);
|
||||
}
|
||||
|
||||
/* Close the seeion in case the session is still open */
|
||||
imap.closeSession();
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status)
|
||||
{
|
||||
/* Print the current status */
|
||||
Serial.println(status.info());
|
||||
|
||||
/* Show the result when reading finished */
|
||||
if (status.success())
|
||||
{
|
||||
/* Print the result */
|
||||
printMessages(imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
}
|
||||
}
|
||||
|
||||
void printAllMailboxesInfo(IMAPSession &imap)
|
||||
{
|
||||
/* Declare the folder collection class to get the list of mailbox folders */
|
||||
FoldersCollection folders;
|
||||
|
||||
/* Get the mailbox folders */
|
||||
if (imap.getFolders(folders))
|
||||
{
|
||||
for (size_t i = 0; i < folders.size(); i++)
|
||||
{
|
||||
/* Iterate each folder info using the folder info item data */
|
||||
FolderInfo folderInfo = folders.info(i);
|
||||
Serial.printf("%s%s%s", i == 0 ? "\nAvailable folders: " : ", ", folderInfo.name, i == folders.size() - 1 ? "\n" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectedMailboxInfo(IMAPSession &imap)
|
||||
{
|
||||
/* Declare the selected folder info class to get the info of selected mailbox folder */
|
||||
SelectedFolderInfo sFolder = imap.selectedFolder();
|
||||
|
||||
/* Show the mailbox info */
|
||||
Serial.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
|
||||
Serial.printf("Predicted next UID: %d\n", sFolder.nextUID());
|
||||
for (size_t i = 0; i < sFolder.flagCount(); i++)
|
||||
Serial.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
|
||||
for (size_t j = 0; j < msg.rfc822.size(); j++)
|
||||
{
|
||||
IMAP_MSG_Item rfc822 = msg.rfc822[j];
|
||||
Serial.printf("%d. \n", j + 1);
|
||||
Serial.printf("Messsage ID: %s\n", rfc822.messageID);
|
||||
Serial.printf("From: %s\n", rfc822.from);
|
||||
Serial.printf("Sender: %s\n", rfc822.sender);
|
||||
Serial.printf("To: %s\n", rfc822.to);
|
||||
Serial.printf("CC: %s\n", rfc822.cc);
|
||||
Serial.printf("Subject: %s\n", rfc822.subject);
|
||||
Serial.printf("Date: %s\n", rfc822.date);
|
||||
Serial.printf("Reply-To: %s\n", rfc822.reply_to);
|
||||
Serial.printf("Return-Path: %s\n", rfc822.return_path);
|
||||
Serial.printf("Comment: %s\n", rfc822.comment);
|
||||
Serial.printf("Keyword: %s\n", rfc822.keyword);
|
||||
Serial.printf("Text Message: %s\n", rfc822.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", rfc822.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", rfc822.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", rfc822.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", rfc822.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", rfc822.html.transfer_encoding);
|
||||
|
||||
if (rfc822.attachments.size() > 0)
|
||||
printAttacements(rfc822);
|
||||
}
|
||||
}
|
||||
|
||||
void printAttacements(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("Attachment: %d file(s)\n****************************\n", msg.attachments.size());
|
||||
for (size_t j = 0; j < msg.attachments.size(); j++)
|
||||
{
|
||||
IMAP_Attach_Item att = msg.attachments[j];
|
||||
/** att.type can be
|
||||
* esp_mail_att_type_none or 0
|
||||
* esp_mail_att_type_attachment or 1
|
||||
* esp_mail_att_type_inline or 2
|
||||
*/
|
||||
Serial.printf("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.creationDate);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printMessages(IMAPSession &imap)
|
||||
{
|
||||
/* Get the message list from the message list data */
|
||||
IMAP_MSG_List msgList = imap.data();
|
||||
|
||||
for (size_t i = 0; i < msgList.msgItems.size(); i++)
|
||||
{
|
||||
/* Iterate to get each message data through the message item data */
|
||||
IMAP_MSG_Item msg = msgList.msgItems[i];
|
||||
|
||||
Serial.println("################################");
|
||||
Serial.printf("Messsage Number: %s\n", msg.msgNo);
|
||||
Serial.printf("Messsage UID: %s\n", msg.UID);
|
||||
Serial.printf("Messsage ID: %s\n", msg.ID);
|
||||
Serial.printf("Accept Language: %s\n", msg.acceptLang);
|
||||
Serial.printf("Content Language: %s\n", msg.contentLang);
|
||||
Serial.printf("From: %s\n", msg.from);
|
||||
Serial.printf("From Charset: %s\n", msg.fromCharset);
|
||||
Serial.printf("To: %s\n", msg.to);
|
||||
Serial.printf("To Charset: %s\n", msg.toCharset);
|
||||
Serial.printf("CC: %s\n", msg.cc);
|
||||
Serial.printf("CC Charset: %s\n", msg.ccCharset);
|
||||
Serial.printf("Date: %s\n", msg.date);
|
||||
Serial.printf("Subject: %s\n", msg.subject);
|
||||
Serial.printf("Subject Charset: %s\n", msg.subjectCharset);
|
||||
|
||||
/* If the result contains the message info (Fetch mode) */
|
||||
if (!imap.headerOnly())
|
||||
{
|
||||
Serial.printf("Text Message: %s\n", msg.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", msg.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", msg.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", msg.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
|
||||
|
||||
if (msg.attachments.size() > 0)
|
||||
printAttacements(msg);
|
||||
|
||||
if (msg.rfc822.size() > 0)
|
||||
printRFC822Messages(msg);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
|
||||
|
||||
/**
|
||||
*This example will log in with the SASL XOAUTH2 mechanisme using OAuth2.0 access token.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
|
||||
#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 user Email for OAuth2.0 access token */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
|
||||
/** The OAuth2.0 access token
|
||||
* The generation, exchange and refresh of the access token are not available
|
||||
* in this library.
|
||||
*
|
||||
* To test this using GMail, get the OAuth2.0 access token from this web site
|
||||
* https://developers.google.com/oauthplayground/
|
||||
*
|
||||
* 1. Select the following scope (in Step 1) from Gmail API V1
|
||||
* https://mail.google.com/
|
||||
* https://mail.google.com/
|
||||
*
|
||||
* 2. Click Authorize APIs button.
|
||||
* 3. Cick Exchangeauthorization code for tokens.
|
||||
* 4. From the response, look at access_token from the JSON payload node.
|
||||
* 5. Copy that access token and paste to the AUTHOR_ACCESS_TOKEN value.
|
||||
*
|
||||
* The token will be expired in 3600 seconds (1 Hr).
|
||||
* The AUTHOR_EMAIL above is the Email address that you granted to access the Gmail services.
|
||||
*/
|
||||
#define AUTHOR_ACCESS_TOKEN "################"
|
||||
|
||||
/* 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();
|
||||
|
||||
/** 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.accessToken = AUTHOR_ACCESS_TOKEN;
|
||||
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 Email using Access token";
|
||||
message.addRecipient("Admin", "####@#####_dot_com");
|
||||
|
||||
message.text.content = "This is simple plain text message";
|
||||
|
||||
/** The Plain text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.text.charSet = "us-ascii";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
|
||||
|
||||
/** The Delivery Status Notifications e.g.
|
||||
* esp_mail_smtp_notify_never
|
||||
* esp_mail_smtp_notify_success
|
||||
* esp_mail_smtp_notify_failure
|
||||
* esp_mail_smtp_notify_delay
|
||||
* The default value is esp_mail_smtp_notify_never
|
||||
*/
|
||||
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
|
||||
/* Connect to server with the session config */
|
||||
if (!smtp.connect(&session))
|
||||
return;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
/* Start sending Email and close the session */
|
||||
if (!MailClient.sendMail(&smtp, &message))
|
||||
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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email with attachments and
|
||||
* inline images stored in heap and flash memories.
|
||||
*
|
||||
* 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) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
/* This is for attachment data */
|
||||
#include "image.h"
|
||||
|
||||
#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();
|
||||
|
||||
/** 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 attachments and inline images";
|
||||
message.addRecipient("user1", "####@#####_dot_com");
|
||||
|
||||
message.html.content = "<span style=\"color:#ff0000;\">This message contains 3 inline images and 1 attachment file.</span><br/><br/><img src=\"firebase_logo.png\" width=\"80\" height=\"60\"> <img src=\"tree.gif\" width=\"40\" height=\"60\"> <img src=\"bird.gif\" width=\"116\" height=\"75\">";
|
||||
|
||||
/** The HTML text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.html.charSet = "utf-8";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
message.text.content = "This message contains 3 inline images and 1 attachment file.\r\nThe inline images were not shown in the plain text message.";
|
||||
message.text.charSet = "utf-8";
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
|
||||
|
||||
/** The Delivery Status Notifications e.g.
|
||||
* esp_mail_smtp_notify_never
|
||||
* esp_mail_smtp_notify_success
|
||||
* esp_mail_smtp_notify_failure
|
||||
* esp_mail_smtp_notify_delay
|
||||
* The default value is esp_mail_smtp_notify_never
|
||||
*/
|
||||
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <user1@gmail.com>");
|
||||
|
||||
/* The attachment data item */
|
||||
SMTP_Attachment att;
|
||||
|
||||
/** Set the inline image info e.g.
|
||||
* file name, MIME type, BLOB data, BLOB data size,
|
||||
* transfer encoding (should be base64 for inline image)
|
||||
*/
|
||||
att.descr.filename = "firebase_logo.png";
|
||||
att.descr.mime = "image/png";
|
||||
att.blob.data = firebase_png;
|
||||
att.blob.size = sizeof(firebase_png);
|
||||
att.descr.transfer_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, BLOB data, BLOB data size.
|
||||
* The default transfer encoding is base64.
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "tree.gif";
|
||||
att.descr.mime = "image/gif";
|
||||
att.blob.data = tree_gif;
|
||||
att.blob.size = sizeof(tree_gif);
|
||||
att.descr.transfer_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, BLOB data, BLOB data size.
|
||||
* The default transfer encoding is base64.
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "bird.gif";
|
||||
att.descr.mime = "image/gif";
|
||||
att.blob.data = bird_gif;
|
||||
att.blob.size = sizeof(bird_gif);
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/* Add inline image to the message */
|
||||
message.addInlineImage(att);
|
||||
|
||||
/* Prepare the attachment data (from ram) */
|
||||
uint8_t *a = new uint8_t[512];
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
a[i] = j;
|
||||
j++;
|
||||
if (j > 255)
|
||||
j = 0;
|
||||
}
|
||||
|
||||
/** Set the attachment info e.g.
|
||||
* file name, MIME type, BLOB data, BLOB data size.
|
||||
* The default transfer encoding is base64.
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "test.dat";
|
||||
att.descr.mime = "application/octet-stream";
|
||||
att.blob.data = a;
|
||||
att.blob.size = 512;
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
/* Add attachment to the message */
|
||||
message.addAttachment(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");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,391 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email with attachments and
|
||||
* inline images stored in flash and SD card.
|
||||
*
|
||||
* 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) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#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();
|
||||
|
||||
static uint8_t buf[512];
|
||||
|
||||
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
|
||||
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
|
||||
* For ESP32, assign all of SPI pins
|
||||
* MailClient.sdBegin(14,2,15,13)
|
||||
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
|
||||
* And for ESP8266, assign the CS pins of SPI port
|
||||
* MailClient.sdBegin(15)
|
||||
* Which pin 15 is the CS pin of SD card adapter
|
||||
*/
|
||||
|
||||
Serial.println("Mounting SD Card...");
|
||||
|
||||
#if defined(ESP32)
|
||||
if (SD.begin()) // MailClient.sdBegin(14,2,15,13) for TTGO T8 v1.7 or 1.8
|
||||
#elif defined(ESP8266)
|
||||
if (SD.begin(15))
|
||||
#endif
|
||||
{
|
||||
|
||||
if (SD.exists("/orange.png"))
|
||||
SD.remove("/orange.png");
|
||||
if (SD.exists("/bin1.dat"))
|
||||
SD.remove("/bin1.dat");
|
||||
|
||||
Serial.println("Preparing SD file attachments...");
|
||||
|
||||
const char *orangeImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RMQ0AMAgAsCFgftHLiQpsENJaaFT+fqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBGi/oCaOpTXoAAAAASUVORK5CYII=";
|
||||
|
||||
File file = SD.open("/orange.png", FILE_WRITE);
|
||||
file.print(orangeImg);
|
||||
file.close();
|
||||
|
||||
file = SD.open("/bin1.dat", FILE_WRITE);
|
||||
|
||||
buf[0] = 'H';
|
||||
buf[1] = 'E';
|
||||
buf[2] = 'A';
|
||||
buf[3] = 'D';
|
||||
file.write(buf, 4);
|
||||
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
memset(buf, i + 1, 512);
|
||||
file.write(buf, 512);
|
||||
}
|
||||
|
||||
buf[0] = 'T';
|
||||
buf[1] = 'A';
|
||||
buf[2] = 'I';
|
||||
buf[3] = 'L';
|
||||
file.write(buf, 4);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("SD Card Monting Failed");
|
||||
}
|
||||
|
||||
Serial.println("Mounting SPIFFS...");
|
||||
|
||||
#if defined(ESP32)
|
||||
if (SPIFFS.begin(true))
|
||||
#elif defined(ESP8266)
|
||||
if (SPIFFS.begin())
|
||||
#endif
|
||||
{
|
||||
//SPIFFS.format();
|
||||
|
||||
if (SPIFFS.exists("/green.png"))
|
||||
SPIFFS.remove("/green.png");
|
||||
if (SPIFFS.exists("/bin2.dat"))
|
||||
SPIFFS.remove("/bin2.dat");
|
||||
|
||||
Serial.println("Preparing SPIFFS attachments...");
|
||||
|
||||
const char *greenImg = "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAoUlEQVR42u3RAQ0AMAgAoJviyWxtAtNYwzmoQGT/eqwRQoQgRAhChCBECEKECBGCECEIEYIQIQgRghCECEGIEIQIQYgQhCBECEKEIEQIQoQgBCFCECIEIUIQIgQhCBGCECEIEYIQIQhBiBCECEGIEIQIQQhChCBECEKEIEQIQhAiBCFCECIEIUIQghAhCBGCECEIEYIQIUKEIEQIQoQg5LoBBaDPbQYiMoMAAAAASUVORK5CYII=";
|
||||
|
||||
#if defined(ESP32)
|
||||
File file = SPIFFS.open("/green.png", FILE_WRITE);
|
||||
#elif defined(ESP8266)
|
||||
File file = SPIFFS.open("/green.png", "w");
|
||||
#endif
|
||||
|
||||
file.print(greenImg);
|
||||
file.close();
|
||||
|
||||
#if defined(ESP32)
|
||||
file = SPIFFS.open("/bin2.dat", FILE_WRITE);
|
||||
#elif defined(ESP8266)
|
||||
file = SPIFFS.open("/bin2.dat", "w");
|
||||
#endif
|
||||
|
||||
buf[0] = 'H';
|
||||
buf[1] = 'E';
|
||||
buf[2] = 'L';
|
||||
buf[3] = 'L';
|
||||
buf[4] = 'O';
|
||||
file.write(buf, 5);
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
memset(buf, i + 1, 512);
|
||||
file.write(buf, 512);
|
||||
}
|
||||
|
||||
buf[0] = 'G';
|
||||
buf[1] = 'O';
|
||||
buf[2] = 'O';
|
||||
buf[3] = 'D';
|
||||
buf[4] = 'B';
|
||||
buf[5] = 'Y';
|
||||
buf[6] = 'E';
|
||||
file.write(buf, 7);
|
||||
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 attachments and inline images from SD card and Flash";
|
||||
message.addRecipient("user1", "####@#####_dot_com");
|
||||
|
||||
/** Two alternative content versions are sending in this example e.g. plain text and html */
|
||||
message.html.content = "<span style=\"color:#ff0000;\">This message contains 2 inline images and 2 attachment files.</span><br/><br/><img src=\"green.png\" width=\"100\" height=\"100\"> <img src=\"orange.png\" width=\"100\" height=\"100\">";
|
||||
|
||||
/** 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";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
message.text.content = "This message contains 2 inline images and 2 attachment files.\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;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
|
||||
|
||||
/** The Delivery Status Notifications e.g.
|
||||
* esp_mail_smtp_notify_never
|
||||
* esp_mail_smtp_notify_success
|
||||
* esp_mail_smtp_notify_failure
|
||||
* esp_mail_smtp_notify_delay
|
||||
* The default value is esp_mail_smtp_notify_never
|
||||
*/
|
||||
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <user1@gmail.com>");
|
||||
|
||||
/* 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";
|
||||
|
||||
/** 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_sd;
|
||||
|
||||
/* 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 attachment info e.g.
|
||||
* file name, MIME type, file path, file storage type,
|
||||
* transfer encoding and content encoding
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "bin1.dat";
|
||||
att.descr.mime = "application/octet-stream"; //binary data
|
||||
att.file.path = "/bin1.dat";
|
||||
att.file.storage_type = esp_mail_file_storage_type_sd;
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/* Add attachment to the message */
|
||||
message.addAttachment(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.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);
|
||||
|
||||
/** Set the attachment info e.g.
|
||||
* file name, MIME type, file path, file storage type,
|
||||
* transfer encoding and content encoding
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "bin2.dat";
|
||||
att.descr.mime = "application/octet-stream";
|
||||
att.file.path = "/bin2.dat";
|
||||
att.file.storage_type = esp_mail_file_storage_type_flash;
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
message.addAttachment(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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email which the
|
||||
* message html and text body will be embedded as
|
||||
* attachment or inline content.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
|
||||
#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 25
|
||||
|
||||
/* 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();
|
||||
|
||||
/** 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;
|
||||
|
||||
/* Set the message headers */
|
||||
message.sender.name = "ESP Mail";
|
||||
message.sender.email = AUTHOR_EMAIL;
|
||||
message.subject = "Test sending message as embedded files";
|
||||
message.addRecipient("Admin", "####@#####_dot_com");
|
||||
|
||||
message.html.content = "<span style=\"color:#0055ff;\">This is html message</span>";
|
||||
|
||||
/** The Plain text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.html.charSet = "utf-8";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
/* Enable to send this message body as file */
|
||||
message.html.embed.enable = true;
|
||||
|
||||
/* The name of embedded file */
|
||||
message.html.embed.filename = "test.html";
|
||||
|
||||
/** The embedded type
|
||||
* esp_mail_smtp_embed_message_type_attachment or 0
|
||||
* esp_mail_smtp_embed_message_type_inline or 1
|
||||
*/
|
||||
message.html.embed.type = esp_mail_smtp_embed_message_type_attachment;
|
||||
|
||||
|
||||
|
||||
message.text.content = "This is simple plain text message";
|
||||
message.text.charSet = "utf-8";
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
message.text.embed.enable = true;
|
||||
message.text.embed.filename = "test.txt";
|
||||
message.text.embed.type = esp_mail_smtp_embed_message_type_inline;
|
||||
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
|
||||
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
|
||||
/* 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 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email in enriched text version.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#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 25
|
||||
|
||||
/* 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();
|
||||
|
||||
/** 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;
|
||||
|
||||
/* Set the message headers */
|
||||
message.sender.name = "ESP Mail";
|
||||
message.sender.email = AUTHOR_EMAIL;
|
||||
message.subject = "Test sending enriched text Email";
|
||||
message.addRecipient("Someone", "####@#####_dot_com");
|
||||
|
||||
message.text.content = "This is <bold><italic>enriched </italic></bold> <smaller>as defined in RFC 1896</smaller>\r\n\r\nIsn't it <bigger><bigger>cool?</bigger></bigger>";
|
||||
|
||||
message.text.content_type = "text/enriched";
|
||||
|
||||
/** The Plain text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.text.charSet = "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: <abcde.fghij@gmail.com>");
|
||||
|
||||
/* 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 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email in
|
||||
* the html version.
|
||||
*
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
|
||||
#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 25
|
||||
|
||||
/* 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();
|
||||
|
||||
/** 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;
|
||||
|
||||
/* Set the message headers */
|
||||
message.sender.name = "ESP Mail";
|
||||
message.sender.email = AUTHOR_EMAIL;
|
||||
message.subject = "Test sending html Email";
|
||||
message.addRecipient("Admin", "####@#####_dot_com");
|
||||
|
||||
message.html.content = "<p>This is the <span style=\"color:#ff0000;\">html text</span> message.</p><p>The message was sent via ESP device.</p>";
|
||||
|
||||
/** The html text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.html.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.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
|
||||
|
||||
/** The Delivery Status Notifications e.g.
|
||||
* esp_mail_smtp_notify_never
|
||||
* esp_mail_smtp_notify_success
|
||||
* esp_mail_smtp_notify_failure
|
||||
* esp_mail_smtp_notify_delay
|
||||
* The default value is esp_mail_smtp_notify_never
|
||||
*/
|
||||
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
|
||||
/* 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 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email with media as parallen attachments
|
||||
* e.g. audio and images and play or display them simultaneously on the Email client.
|
||||
*
|
||||
* This depends on the Mail client supports.
|
||||
*
|
||||
* 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) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
/* This is for attachment data */
|
||||
#include "data.h"
|
||||
|
||||
#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
|
||||
*/
|
||||
#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();
|
||||
|
||||
/** 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 parallel attachments";
|
||||
message.addRecipient("user1", "####@#####_dot_com");
|
||||
|
||||
message.html.content = "<span style=\"color:#ff0000;\">This message contains image and audio file which will play on the Mail client in parallel or simultaneously (depends on the client supports).";
|
||||
|
||||
/** The HTML text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.html.charSet = "utf-8";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
message.text.content = "This message contains image and audio file which will play on the Mail client in parallel or simultaneously (depends on the client supports).";
|
||||
message.text.charSet = "us-ascii";
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
|
||||
|
||||
/** The Delivery Status Notifications e.g.
|
||||
* esp_mail_smtp_notify_never
|
||||
* esp_mail_smtp_notify_success
|
||||
* esp_mail_smtp_notify_failure
|
||||
* esp_mail_smtp_notify_delay
|
||||
* The default value is esp_mail_smtp_notify_never
|
||||
*/
|
||||
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <user1@gmail.com>");
|
||||
|
||||
/* The attachment data item */
|
||||
SMTP_Attachment att;
|
||||
|
||||
/** Set the attachment info e.g.
|
||||
* file name, MIME type, file path, file storage type,
|
||||
* transfer encoding and content encoding
|
||||
*/
|
||||
att.descr.filename = "haun.png";
|
||||
att.descr.mime = "image/png";
|
||||
att.blob.data = shaun_png;
|
||||
att.blob.size = sizeof(shaun_png);
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
message.addParallelAttachment(att);
|
||||
|
||||
/** Set the attachment info e.g.
|
||||
* file name, MIME type, file path, file storage type,
|
||||
* transfer encoding and content encoding
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "mu_law.wav";
|
||||
att.descr.mime = "audio/basic";
|
||||
att.blob.data = mu_law_wave;
|
||||
att.blob.size = sizeof(mu_law_wave);
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
message.addParallelAttachment(att);
|
||||
|
||||
/* Connect to 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");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,252 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email in plain text version
|
||||
* with rfc822 message attachment which the rfc822 message
|
||||
* also contains its attachement.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
/* This is for attachment data */
|
||||
#include "image.h"
|
||||
|
||||
#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 25
|
||||
|
||||
/* 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("Connect to NTP server and set the device time\r\nPlease wait...\r\n");
|
||||
float timeZone = 3;//GMT+3
|
||||
float daylightOffset = 0;
|
||||
|
||||
/* Set the device time */
|
||||
MailClient.Time.setClock(timeZone, daylightOffset);
|
||||
|
||||
/** 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;
|
||||
|
||||
/* Set the message headers */
|
||||
message.sender.name = "ESP Mail";
|
||||
message.sender.email = AUTHOR_EMAIL;
|
||||
message.subject = "Test sending Email with rfc822 attachment";
|
||||
message.addRecipient("Someone", "####@#####_dot_com");
|
||||
|
||||
message.text.content = "This is simple plain text message with rfc822 attachment";
|
||||
|
||||
/** The Plain text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.text.charSet = "us-ascii";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
SMTP_Message rfc822;
|
||||
rfc822.messageID = "1234@local.machine.example";
|
||||
rfc822.from.name = "rob";
|
||||
rfc822.from.email = "rob@example.com";
|
||||
rfc822.sender.name = "steve";
|
||||
rfc822.sender.email = "steve@example.com";
|
||||
String dt = MailClient.Time.getDateTimeString();
|
||||
rfc822.date = dt.c_str();
|
||||
rfc822.subject = "Test rfc822 message";
|
||||
rfc822.comment = "This is comment";
|
||||
rfc822.addRecipient("joe", "joe@example.com");
|
||||
rfc822.response.reply_to = "rob@example.com";
|
||||
rfc822.text.charSet = "utf-8";
|
||||
rfc822.text.content = "This is rfc822 text message";
|
||||
rfc822.text.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
rfc822.html.charSet = "utf-8";
|
||||
rfc822.html.content = "This is rfc822 html message";
|
||||
rfc822.html.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/* The attachment data item */
|
||||
SMTP_Attachment att;
|
||||
|
||||
/** Set the attachment info e.g.
|
||||
* file name, MIME type, BLOB data, BLOB data size,
|
||||
* and transfer encoding
|
||||
*/
|
||||
att.descr.filename = "firebase_logo.png";
|
||||
att.descr.mime = "image/png";
|
||||
att.blob.data = firebase_png;
|
||||
att.blob.size = sizeof(firebase_png);
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/* Add the attachment to the rfc822 message */
|
||||
rfc822.addAttachment(att);
|
||||
|
||||
/* Prepare other attachment data */
|
||||
uint8_t *a = new uint8_t[512];
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
a[i] = j;
|
||||
j++;
|
||||
if (j > 255)
|
||||
j = 0;
|
||||
}
|
||||
|
||||
/** Set the attachment info e.g.
|
||||
* file name, MIME type, BLOB data, BLOB data size.
|
||||
* The default transfer encoding is base64.
|
||||
*/
|
||||
message.resetAttachItem(att); //Clear the attach item data to reuse
|
||||
att.descr.filename = "test.dat";
|
||||
att.descr.mime = "application/octet-stream";
|
||||
att.blob.data = a;
|
||||
att.blob.size = 512;
|
||||
|
||||
/* Add this attachment to the message */
|
||||
message.addAttachment(att);
|
||||
|
||||
/* Add rfc822 message in the message */
|
||||
message.addRMessage(rfc822);
|
||||
|
||||
/* 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 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");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,245 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send multiple messages which
|
||||
* the session was keep open during sending.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
|
||||
#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();
|
||||
|
||||
/** 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;
|
||||
|
||||
/* Set the message headers */
|
||||
message.sender.name = "ESP Mail";
|
||||
message.sender.email = AUTHOR_EMAIL;
|
||||
message.subject = "First Email with session reusage";
|
||||
message.addRecipient("Admin1", "####@#####_dot_com");
|
||||
message.addRecipient("Admin2", "####@#####_dot_com");
|
||||
message.addCc("####@#####_dot_com");
|
||||
message.addBcc("####@#####_dot_com");
|
||||
|
||||
message.html.content = "<p>This is the <span style=\"color:#ff0000;\">first message</span>.</p>";
|
||||
|
||||
/** 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";
|
||||
|
||||
/** The content transfer encoding e.g.
|
||||
* enc_7bit or "7bit" (not encoded)
|
||||
* enc_qp or "quoted-printable" (encoded)
|
||||
* enc_base64 or "base64" (encoded)
|
||||
* enc_binary or "binary" (not encoded)
|
||||
* enc_8bit or "8bit" (not encoded)
|
||||
* The default value is "7bit"
|
||||
*/
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
/** The option to add soft line break to to the message for
|
||||
* the long text message > 78 characters (rfc 3676)
|
||||
* Some Servers may not compliant with the standard.
|
||||
*/
|
||||
message.text.flowed = true;
|
||||
|
||||
message.text.content = "This is the first message";
|
||||
message.text.charSet = "us-ascii";
|
||||
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
|
||||
/** The message priority
|
||||
* esp_mail_smtp_priority_high or 1
|
||||
* esp_mail_smtp_priority_normal or 3
|
||||
* esp_mail_smtp_priority_low or 5
|
||||
* The default value is esp_mail_smtp_priority_low
|
||||
*/
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
|
||||
|
||||
/** The Delivery Status Notifications e.g.
|
||||
* esp_mail_smtp_notify_never
|
||||
* esp_mail_smtp_notify_success
|
||||
* esp_mail_smtp_notify_failure
|
||||
* esp_mail_smtp_notify_delay
|
||||
* The default value is esp_mail_smtp_notify_never
|
||||
*/
|
||||
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <Admin1@gmail.com>");
|
||||
|
||||
Serial.println();
|
||||
Serial.println("Sending first Email...");
|
||||
|
||||
/* Connect to server with the session config */
|
||||
if (!smtp.connect(&session))
|
||||
return;
|
||||
|
||||
/** Start sending the first Email and keep open the session
|
||||
* The third parameter is for close the session.
|
||||
*/
|
||||
if (!MailClient.sendMail(&smtp, &message, false))
|
||||
Serial.println("Error sending Email, " + smtp.errorReason());
|
||||
|
||||
|
||||
/* To clear all message data */
|
||||
//message.clear();
|
||||
|
||||
/** Clear primary recipients, Cc recipients, Bcc recipients, custom headers
|
||||
* attachments and inline images
|
||||
*/
|
||||
message.clearRecipients();
|
||||
message.clearCc();
|
||||
message.clearBcc();
|
||||
//message.clearAttachments();
|
||||
//message.clearInlineimages();
|
||||
|
||||
message.subject = "Second Email with session reusage";
|
||||
|
||||
message.addRecipient("Admin3", "####@#####_dot_com");
|
||||
message.addRecipient("Admin4", "####@#####_dot_com");
|
||||
message.addCc("####@#####_dot_com");
|
||||
message.addBcc("####@#####_dot_com");
|
||||
|
||||
message.html.content = "<p>This is the <span style=\"color:#ff0000;\">second message</span>.</p>";
|
||||
message.html.charSet = "us-ascii";
|
||||
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
|
||||
|
||||
message.text.content = "This is the second message";
|
||||
message.text.charSet = "UTF-8";
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_qp;
|
||||
|
||||
/* Set the custom message header */
|
||||
message.addHeader("Message-ID: <Admin3@gmail.com>");
|
||||
|
||||
Serial.println();
|
||||
Serial.println("Sending second Email...");
|
||||
|
||||
/* Start sending the second mail and close the session */
|
||||
if (!MailClient.sendMail(&smtp, &message))
|
||||
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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email in plain text version.
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#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 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);
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* 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;
|
||||
|
||||
/* 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");
|
||||
|
||||
message.text.content = "This is simple plain text message";
|
||||
|
||||
/** The Plain text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.text.charSet = "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: <abcde.fghij@gmail.com>");
|
||||
|
||||
/* 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 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
|
||||
|
||||
/**
|
||||
* This example will send the Email in plain text version
|
||||
* with the quoted text and long line text.
|
||||
*
|
||||
*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 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
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#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 25
|
||||
|
||||
/* 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();
|
||||
|
||||
/** 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;
|
||||
|
||||
/* Set the message headers */
|
||||
message.sender.name = "ESP Mail";
|
||||
message.sender.email = AUTHOR_EMAIL;
|
||||
message.subject = "Test sending flowed plain text Email";
|
||||
message.addRecipient("Someone", "####@#####_dot_com");
|
||||
|
||||
/** The option to add soft line break to to the message for
|
||||
* the long text message > 78 characters (rfc 3676)
|
||||
* Some Servers may not compliant with the standard.
|
||||
*/
|
||||
message.text.flowed = true;
|
||||
|
||||
/** if the option message.text.flowed is true,
|
||||
* the following plain text message will be wrapped.
|
||||
*/
|
||||
message.text.content = "The text below is the long quoted text which breaks into several lines.\r\n\r\n>> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\r\n\r\nThis is the normal short text.\r\n\r\nAnother long text, abcdefg hijklmnop qrstuv wxyz abcdefg hijklmnop qrstuv wxyz abcdefg hijklmnop qrstuv wxyz.";
|
||||
|
||||
/** The Plain text message character set e.g.
|
||||
* us-ascii
|
||||
* utf-8
|
||||
* utf-7
|
||||
* The default value is utf-8
|
||||
*/
|
||||
message.text.charSet = "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: <abcde.fghij@gmail.com>");
|
||||
|
||||
/* 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 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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,363 @@
|
|||
/**
|
||||
* This example will set the argument to the flags and read the message.
|
||||
*
|
||||
* Email: suwatchai@outlook.com
|
||||
*
|
||||
* Github: https://github.com/mobizt/ESP-Mail-Client
|
||||
*
|
||||
* Copyright (c) 2020 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
/** To receive Email using Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
* and also https://accounts.google.com/b/0/DisplayUnlockCaptcha
|
||||
*
|
||||
*/
|
||||
|
||||
/** For ESP8266, with BearSSL WiFi Client
|
||||
* The memory reserved for completed valid SSL response from IMAP is 16 kbytes which
|
||||
* may cause your device out of memory reset in case the memory
|
||||
* allocation error.
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#define WIFI_SSID "################"
|
||||
#define WIFI_PASSWORD "################"
|
||||
|
||||
/* The imap host name e.g. imap.gmail.com for GMail or outlook.office365.com for Outlook */
|
||||
#define IMAP_HOST "################"
|
||||
|
||||
/** The imap port e.g.
|
||||
* 143 or esp_mail_imap_port_143
|
||||
* 993 or esp_mail_imap_port_993
|
||||
*/
|
||||
#define IMAP_PORT 993
|
||||
|
||||
/* The log in credentials */
|
||||
#define AUTHOR_EMAIL "################"
|
||||
#define AUTHOR_PASSWORD "################"
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status);
|
||||
|
||||
/* Print the list of mailbox folders */
|
||||
void printAllMailboxesInfo(IMAPSession &imap);
|
||||
|
||||
/* Print the selected folder info */
|
||||
void printSelectedMailboxInfo(IMAPSession &imap);
|
||||
|
||||
/* Print all messages from the message list */
|
||||
void printMessages(IMAPSession &imap);
|
||||
|
||||
/* Print all rfc822 messages included in the message */
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg);
|
||||
|
||||
/* Print all attachments info from the message */
|
||||
void printAttacements(IMAP_MSG_Item &msg);
|
||||
|
||||
/* The IMAP Session object used for Email reading */
|
||||
IMAPSession imap;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
Serial.print("Connecting to AP");
|
||||
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
Serial.print(".");
|
||||
delay(200);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected.");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.println();
|
||||
|
||||
/** Enable the debug via Serial port
|
||||
* none debug or 0
|
||||
* basic debug or 1
|
||||
*/
|
||||
imap.debug(1);
|
||||
|
||||
/* Set the callback function to get the reading results */
|
||||
imap.callback(imapCallback);
|
||||
|
||||
/** In case the SD card/adapter was used for the file storagge, the SPI pins can be configure from
|
||||
* MailClient.sdBegin function which may be different for ESP32 and ESP8266
|
||||
* For ESP32, assign all of SPI pins
|
||||
* MailClient.sdBegin(14,2,15,13)
|
||||
* Which SCK = 14, MISO = 2, MOSI = 15 and SS = 13
|
||||
* And for ESP8266, assign the CS pins of SPI port
|
||||
* MailClient.sdBegin(15)
|
||||
* Which pin 15 is the CS pin of SD card adapter
|
||||
*/
|
||||
|
||||
/* Declare the session config data */
|
||||
ESP_Mail_Session session;
|
||||
|
||||
/* Set the session config */
|
||||
session.server.host_name = IMAP_HOST;
|
||||
session.server.port = IMAP_PORT;
|
||||
session.login.email = AUTHOR_EMAIL;
|
||||
session.login.password = AUTHOR_PASSWORD;
|
||||
|
||||
|
||||
/* Setup the configuration for searching or fetching operation and its result */
|
||||
IMAP_Config config;
|
||||
|
||||
/* Message UID to fetch or read e.g. 100 */
|
||||
config.fetch.uid = "100";
|
||||
|
||||
/* Set seen flag */
|
||||
//config.fetch.set_seen = true;
|
||||
|
||||
/* Search criteria */
|
||||
config.search.criteria = "";
|
||||
|
||||
/* Also search the unseen message */
|
||||
config.search.unseen_msg = true;
|
||||
|
||||
/* Set the storage to save the downloaded files and attachments */
|
||||
config.storage.saved_path = "/email_data";
|
||||
|
||||
/** The file storage type e.g.
|
||||
* esp_mail_file_storage_type_none,
|
||||
* esp_mail_file_storage_type_flash, and
|
||||
* esp_mail_file_storage_type_sd
|
||||
*/
|
||||
config.storage.type = esp_mail_file_storage_type_flash;
|
||||
|
||||
/** Set to download heades, text and html messaeges,
|
||||
* attachments and inline images respectively.
|
||||
*/
|
||||
config.download.header = true;
|
||||
config.download.text = true;
|
||||
config.download.html = true;
|
||||
config.download.attachment = true;
|
||||
config.download.inlineImg = true;
|
||||
|
||||
/** Set to enable the results i.e. html and text messaeges
|
||||
* which the content stored in the IMAPSession object is limited
|
||||
* by the option config.limit.msg_size.
|
||||
* The whole message can be download through config.download.text
|
||||
* or config.download.html which not depends on these enable options.
|
||||
*/
|
||||
config.enable.html = true;
|
||||
config.enable.text = true;
|
||||
|
||||
/* Set to enable the sort the result by message UID in the ascending order */
|
||||
config.enable.recent_sort = true;
|
||||
|
||||
/* Set to report the download progress via the default serial port */
|
||||
config.enable.download_status = true;
|
||||
|
||||
/* Set the limit of number of messages in the search results */
|
||||
config.limit.search = 5;
|
||||
|
||||
/** Set the maximum size of message stored in
|
||||
* IMAPSession object in byte
|
||||
*/
|
||||
config.limit.msg_size = 512;
|
||||
|
||||
/** Set the maximum attachments and inline images files size
|
||||
* that can be downloaded in byte.
|
||||
* The file which its size is largger than this limit may be saved
|
||||
* as truncated file.
|
||||
*/
|
||||
config.limit.attachment_size = 1024 * 1024 * 5;
|
||||
|
||||
|
||||
|
||||
/* Connect to server with the session and config */
|
||||
if (!imap.connect(&session, &config))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printAllMailboxesInfo(imap);
|
||||
|
||||
/* Open or select the mailbox folder to read or search the message */
|
||||
if (!imap.selectFolder("INBOX"))
|
||||
return;
|
||||
|
||||
/* {Optional] */
|
||||
printSelectedMailboxInfo(imap);
|
||||
|
||||
/** Set \Seen and \Answered to flags for message with UID 100
|
||||
* The seesion will keep open.
|
||||
*/
|
||||
if (MailClient.setFlag(&imap, 100, "\\Seen \\Answered", false))
|
||||
Serial.println("Setting FLAG success");
|
||||
else
|
||||
Serial.println("Error, setting FLAG");
|
||||
|
||||
/* Add \Seen and \Answered to flags for message with UID 100 */
|
||||
//MailClient.addFlag(imap, 100, "\\Seen \\Answered", false);
|
||||
|
||||
/* Remove \Seen and \Answered from flags for message with UID 100 */
|
||||
//MailClient.removeFlag(imap, 100, "\\Seen \\Answered", false);
|
||||
|
||||
/* Read or search the Email and close the session */
|
||||
MailClient.readMail(&imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Callback function to get the Email reading status */
|
||||
void imapCallback(IMAP_Status status)
|
||||
{
|
||||
/* Print the current status */
|
||||
Serial.println(status.info());
|
||||
|
||||
/* Show the result when reading finished */
|
||||
if (status.success())
|
||||
{
|
||||
/* Print the result */
|
||||
printMessages(imap);
|
||||
|
||||
/* Clear all stored data in IMAPSession object */
|
||||
imap.empty();
|
||||
Serial.printf("Free Heap: %d", ESP.getFreeHeap());
|
||||
}
|
||||
}
|
||||
|
||||
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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printSelectedMailboxInfo(IMAPSession &imap)
|
||||
{
|
||||
/* Declare the selected folder info class to get the info of selected mailbox folder */
|
||||
SelectedFolderInfo sFolder = imap.selectedFolder();
|
||||
|
||||
/* Show the mailbox info */
|
||||
Serial.printf("\nInfo of the selected folder\nTotal Messages: %d\n", sFolder.msgCount());
|
||||
Serial.printf("Predicted next UID: %d\n", sFolder.nextUID());
|
||||
for (size_t i = 0; i < sFolder.flagCount(); i++)
|
||||
Serial.printf("%s%s%s", i == 0 ? "Flags: " : ", ", sFolder.flag(i).c_str(), i == sFolder.flagCount() - 1 ? "\n" : "");
|
||||
}
|
||||
|
||||
void printRFC822Messages(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("RFC822 Messages: %d message(s)\n****************************\n", msg.rfc822.size());
|
||||
for (size_t j = 0; j < msg.rfc822.size(); j++)
|
||||
{
|
||||
IMAP_MSG_Item rfc822 = msg.rfc822[j];
|
||||
Serial.printf("%d. \n", j + 1);
|
||||
Serial.printf("Messsage ID: %s\n", rfc822.messageID);
|
||||
Serial.printf("From: %s\n", rfc822.from);
|
||||
Serial.printf("Sender: %s\n", rfc822.sender);
|
||||
Serial.printf("To: %s\n", rfc822.to);
|
||||
Serial.printf("CC: %s\n", rfc822.cc);
|
||||
Serial.printf("Subject: %s\n", rfc822.subject);
|
||||
Serial.printf("Date: %s\n", rfc822.date);
|
||||
Serial.printf("Reply-To: %s\n", rfc822.reply_to);
|
||||
Serial.printf("Return-Path: %s\n", rfc822.return_path);
|
||||
Serial.printf("Comment: %s\n", rfc822.comment);
|
||||
Serial.printf("Keyword: %s\n", rfc822.keyword);
|
||||
Serial.printf("Text Message: %s\n", rfc822.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", rfc822.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", rfc822.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", rfc822.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", rfc822.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", rfc822.html.transfer_encoding);
|
||||
|
||||
if (rfc822.attachments.size() > 0)
|
||||
printAttacements(rfc822);
|
||||
}
|
||||
}
|
||||
|
||||
void printAttacements(IMAP_MSG_Item &msg)
|
||||
{
|
||||
Serial.printf("Attachment: %d file(s)\n****************************\n", msg.attachments.size());
|
||||
for (size_t j = 0; j < msg.attachments.size(); j++)
|
||||
{
|
||||
IMAP_Attach_Item att = msg.attachments[j];
|
||||
/** att.type can be
|
||||
* esp_mail_att_type_none or 0
|
||||
* esp_mail_att_type_attachment or 1
|
||||
* esp_mail_att_type_inline or 2
|
||||
*/
|
||||
Serial.printf("%d. Filename: %s, Name: %s, Size: %d, MIME: %s, Type: %s, Creation Date: %s\n", j + 1, att.filename, att.name, att.size, att.mime, att.type == esp_mail_att_type_attachment ? "attachment" : "inline", att.creationDate);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printMessages(IMAPSession &imap)
|
||||
{
|
||||
/* Get the message list from the message list data */
|
||||
IMAP_MSG_List msgList = imap.data();
|
||||
|
||||
for (size_t i = 0; i < msgList.msgItems.size(); i++)
|
||||
{
|
||||
/* Iterate to get each message data through the message item data */
|
||||
IMAP_MSG_Item msg = msgList.msgItems[i];
|
||||
|
||||
Serial.println("################################");
|
||||
Serial.printf("Messsage Number: %s\n", msg.msgNo);
|
||||
Serial.printf("Messsage UID: %s\n", msg.UID);
|
||||
Serial.printf("Messsage ID: %s\n", msg.ID);
|
||||
Serial.printf("Accept Language: %s\n", msg.acceptLang);
|
||||
Serial.printf("Content Language: %s\n", msg.contentLang);
|
||||
Serial.printf("From: %s\n", msg.from);
|
||||
Serial.printf("From Charset: %s\n", msg.fromCharset);
|
||||
Serial.printf("To: %s\n", msg.to);
|
||||
Serial.printf("To Charset: %s\n", msg.toCharset);
|
||||
Serial.printf("CC: %s\n", msg.cc);
|
||||
Serial.printf("CC Charset: %s\n", msg.ccCharset);
|
||||
Serial.printf("Date: %s\n", msg.date);
|
||||
Serial.printf("Subject: %s\n", msg.subject);
|
||||
Serial.printf("Subject Charset: %s\n", msg.subjectCharset);
|
||||
|
||||
/* If the result contains the message info (Fetch mode) */
|
||||
if (!imap.headerOnly())
|
||||
{
|
||||
Serial.printf("Text Message: %s\n", msg.text.content);
|
||||
Serial.printf("Text Message Charset: %s\n", msg.text.charSet);
|
||||
Serial.printf("Text Message Transfer Encoding: %s\n", msg.text.transfer_encoding);
|
||||
Serial.printf("HTML Message: %s\n", msg.html.content);
|
||||
Serial.printf("HTML Message Charset: %s\n", msg.html.charSet);
|
||||
Serial.printf("HTML Message Transfer Encoding: %s\n\n", msg.html.transfer_encoding);
|
||||
|
||||
if (msg.attachments.size() > 0)
|
||||
printAttacements(msg);
|
||||
|
||||
if (msg.rfc822.size() > 0)
|
||||
printRFC822Messages(msg);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
######################################
|
||||
# Syntax Coloring Map ESP Mail Client
|
||||
######################################
|
||||
|
||||
#######################################
|
||||
# Classes and Structured Type (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
MailClient KEYWORD1
|
||||
IMAPSession KEYWORD1
|
||||
SMTPSession KEYWORD1
|
||||
SMTP_Message KEYWORD1
|
||||
IMAP_Config KEYWORD1
|
||||
FoldersCollection KEYWORD1
|
||||
imapStatusCallback KEYWORD1
|
||||
IMAP_MSG_List KEYWORD1
|
||||
SelectedFolderInfo KEYWORD1
|
||||
ESP_Mail_Session KEYWORD1
|
||||
smtpStatusCallback KEYWORD1
|
||||
SMTP_Attachment KEYWORD1
|
||||
SMTP_Result KEYWORD1
|
||||
IMAP_MSG_Item KEYWORD1
|
||||
Content_Transfer_Encoding KEYWORD1
|
||||
MessageList KEYWORD1
|
||||
|
||||
###############################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
###############################################
|
||||
|
||||
sendMail KEYWORD2
|
||||
readMail KEYWORD2
|
||||
setFlag KEYWORD2
|
||||
addFlag KEYWORD2
|
||||
removeFlag KEYWORD2
|
||||
sdBegin KEYWORD2
|
||||
connect KEYWORD2
|
||||
closeSession KEYWORD2
|
||||
debug KEYWORD2
|
||||
getFolders KEYWORD2
|
||||
selectFolder KEYWORD2
|
||||
openFolder KEYWORD2
|
||||
closeFolder KEYWORD2
|
||||
callback KEYWORD2
|
||||
headerOnly KEYWORD2
|
||||
data KEYWORD2
|
||||
selectedFolder KEYWORD2
|
||||
errorReason KEYWORD2
|
||||
empty KEYWORD2
|
||||
resetAttachItem KEYWORD2
|
||||
clear KEYWORD2
|
||||
clearInlineimages KEYWORD2
|
||||
clearAttachments KEYWORD2
|
||||
clearRFC822Messages KEYWORD2
|
||||
clearRecipients KEYWORD2
|
||||
clearCc KEYWORD2
|
||||
clearBcc KEYWORD2
|
||||
clearHeader KEYWORD2
|
||||
addAttachment KEYWORD2
|
||||
addParallelAttachment KEYWORD2
|
||||
addInlineImage KEYWORD2
|
||||
addMessage KEYWORD2
|
||||
addRecipient KEYWORD2
|
||||
addCc KEYWORD2
|
||||
addBcc KEYWORD2
|
||||
addHeader KEYWORD2
|
||||
info KEYWORD2
|
||||
successs KEYWORD2
|
||||
completedCount KEYWORD2
|
||||
failedCount KEYWORD2
|
||||
getItem KEYWORD2
|
||||
size KEYWORD2
|
||||
flagCount KEYWORD2
|
||||
msgCount KEYWORD2
|
||||
nextUID KEYWORD2
|
||||
searchCount KEYWORD2
|
||||
availableMessages KEYWORD2
|
||||
flag KEYWORD2
|
||||
setClock KEYWORD2
|
||||
getUnixTime KEYWORD2
|
||||
getTimestamp KEYWORD2
|
||||
getYear KEYWORD2
|
||||
getMonth KEYWORD2
|
||||
getDay KEYWORD2
|
||||
getDayOfWeek KEYWORD2
|
||||
getDayOfWeekString KEYWORD2
|
||||
getHour KEYWORD2
|
||||
getMin KEYWORD2
|
||||
getSecond KEYWORD2
|
||||
getNumberOfDayThisYear KEYWORD2
|
||||
getTotalDays KEYWORD2
|
||||
dayofWeek KEYWORD2
|
||||
getCurrentSecond KEYWORD2
|
||||
getCurrentTimestamp KEYWORD2
|
||||
getTimeFromSec KEYWORD2
|
||||
getDateTimeString KEYWORD2
|
||||
copyMessages KEYWORD2
|
||||
deleteMessages KEYWORD2
|
||||
createFolder KEYWORD2
|
||||
deleteFolder KEYWORD2
|
||||
|
||||
|
||||
#######################################
|
||||
# Struct (LITERAL1)
|
||||
#######################################
|
||||
|
||||
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_file_storage_type_none LITERAL1
|
||||
esp_mail_file_storage_type_flash LITERAL1
|
||||
esp_mail_file_storage_type_sd LITERAL1
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "ESP Mail Client",
|
||||
"version": "1.0.13",
|
||||
"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": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mobizt/ESP-Mail-Client.git"
|
||||
},
|
||||
"authors": [{
|
||||
"name": "Mobizt",
|
||||
"email": "suwatchai@outlook.com"
|
||||
}],
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32, espressif8266"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
name=ESP Mail Client
|
||||
version=1.0.13
|
||||
author=Mobizt
|
||||
maintainer=Mobizt <suwatchai@outlook.com>
|
||||
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
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 15 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* ESP32 Internet Time Helper Arduino Library v 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person returning a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ESPTimeHelper_CPP
|
||||
#define ESPTimeHelper_CPP
|
||||
|
||||
#include "ESPTimeHelper.h"
|
||||
|
||||
ESPTimeHelper::ESPTimeHelper()
|
||||
{
|
||||
}
|
||||
uint32_t ESPTimeHelper::getUnixTime()
|
||||
{
|
||||
uint32_t utime = (msec_time_diff + millis()) / 1000;
|
||||
return utime;
|
||||
}
|
||||
|
||||
time_t ESPTimeHelper::getTimestamp(int year, int mon, int date, int hour, int mins, int sec)
|
||||
{
|
||||
struct tm timeinfo;
|
||||
timeinfo.tm_year = year - 1900;
|
||||
timeinfo.tm_mon = mon - 1;
|
||||
timeinfo.tm_mday = date;
|
||||
timeinfo.tm_hour = hour;
|
||||
timeinfo.tm_min = mins;
|
||||
timeinfo.tm_sec = sec;
|
||||
time_t ts = mktime(&timeinfo);
|
||||
return ts;
|
||||
}
|
||||
|
||||
bool ESPTimeHelper::setClock(float gmtOffset, float daylightOffset)
|
||||
{
|
||||
TZ = gmtOffset;
|
||||
DST_MN = daylightOffset;
|
||||
configTime((TZ)*3600, (DST_MN)*60, "pool.ntp.org", "time.nist.gov");
|
||||
|
||||
now = time(nullptr);
|
||||
uint8_t attempts = 0;
|
||||
while (now < 1577836800)
|
||||
{
|
||||
now = time(nullptr);
|
||||
attempts++;
|
||||
if (attempts > 200 || now > 1577836800)
|
||||
break;
|
||||
delay(100);
|
||||
}
|
||||
|
||||
uint64_t tmp = now;
|
||||
tmp = tmp * 1000;
|
||||
msec_time_diff = tmp - millis();
|
||||
|
||||
#if defined(ESP32)
|
||||
getLocalTime(&timeinfo);
|
||||
#elif defined(ESP8266)
|
||||
gmtime_r(&now, &timeinfo);
|
||||
#endif
|
||||
|
||||
clockReady = now > 8 * 3600 * 2;
|
||||
return clockReady;
|
||||
}
|
||||
|
||||
int ESPTimeHelper::getYear()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_year + 1900;
|
||||
}
|
||||
int ESPTimeHelper::getMonth()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_mon + 1;
|
||||
}
|
||||
int ESPTimeHelper::getDay()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_mday;
|
||||
}
|
||||
|
||||
int ESPTimeHelper::getDayOfWeek()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_wday;
|
||||
}
|
||||
String ESPTimeHelper::getDayOfWeekString()
|
||||
{
|
||||
setSysTime();
|
||||
return dow[timeinfo.tm_wday];
|
||||
}
|
||||
|
||||
int ESPTimeHelper::getHour()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_hour;
|
||||
}
|
||||
|
||||
int ESPTimeHelper::getMin()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_min;
|
||||
}
|
||||
int ESPTimeHelper::getSec()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_sec;
|
||||
}
|
||||
int ESPTimeHelper::getNumberOfDayThisYear()
|
||||
{
|
||||
setSysTime();
|
||||
return timeinfo.tm_yday + 1;
|
||||
}
|
||||
|
||||
int ESPTimeHelper::totalDays(int y, int m, int d)
|
||||
{
|
||||
static char daytab[2][13] =
|
||||
{
|
||||
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||
int daystotal = d;
|
||||
for (int year = 1; year <= y; year++)
|
||||
{
|
||||
int max_month = (year < y ? 12 : m - 1);
|
||||
int leap = (year % 4 == 0);
|
||||
if (year % 100 == 0 && year % 400 != 0)
|
||||
leap = 0;
|
||||
for (int month = 1; month <= max_month; month++)
|
||||
{
|
||||
daystotal += daytab[leap][month];
|
||||
}
|
||||
}
|
||||
return daystotal;
|
||||
}
|
||||
int ESPTimeHelper::getTotalDays(int year, int month, int day)
|
||||
{
|
||||
return totalDays(year, month, day) - totalDays(1970, 1, 1);
|
||||
}
|
||||
|
||||
int ESPTimeHelper::dayofWeek(int year, int month, int day) /* 1 <= m <= 12, y > 1752 (in the U.K.) */
|
||||
{
|
||||
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||
year -= month < 3;
|
||||
return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
|
||||
}
|
||||
|
||||
int ESPTimeHelper::getCurrentSecond()
|
||||
{
|
||||
return (timeinfo.tm_hour * 3600) + (timeinfo.tm_min * 60) + timeinfo.tm_sec;
|
||||
}
|
||||
uint64_t ESPTimeHelper::getCurrentTimestamp()
|
||||
{
|
||||
return now;
|
||||
}
|
||||
struct tm ESPTimeHelper::getTimeFromSec(int seconds)
|
||||
{
|
||||
struct tm timeinfo;
|
||||
int _yrs = seconds / (365 * 24 * 3600);
|
||||
seconds = seconds - _yrs * (365 * 24 * 3600);
|
||||
timeinfo.tm_year = _yrs - 1900;
|
||||
int _months = seconds / (30 * 24 * 3600);
|
||||
seconds = seconds - _months * (30 * 24 * 3600);
|
||||
timeinfo.tm_mon = _months - 1;
|
||||
int _days = seconds / (24 * 3600);
|
||||
seconds = seconds - _days * (24 * 3600);
|
||||
timeinfo.tm_mday = _days;
|
||||
int _hr = seconds / 3600;
|
||||
seconds = seconds - _hr * 3600;
|
||||
timeinfo.tm_hour = _hr;
|
||||
int _min = seconds / 60;
|
||||
seconds = seconds - _min * 60;
|
||||
timeinfo.tm_min = _min;
|
||||
timeinfo.tm_sec = seconds;
|
||||
return timeinfo;
|
||||
}
|
||||
|
||||
char *ESPTimeHelper::intStr(int value)
|
||||
{
|
||||
char *buf = new char[36];
|
||||
memset(buf, 0, 36);
|
||||
itoa(value, buf, 10);
|
||||
return buf;
|
||||
}
|
||||
|
||||
String ESPTimeHelper::getDateTimeString()
|
||||
{
|
||||
setSysTime();
|
||||
std::string s;
|
||||
|
||||
s = sdow[timeinfo.tm_wday];
|
||||
|
||||
s += ", ";
|
||||
char *tmp = intStr(timeinfo.tm_mday);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
s += " ";
|
||||
s += months[timeinfo.tm_mon];
|
||||
|
||||
s += " ";
|
||||
tmp = intStr(timeinfo.tm_year + 1900);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
s += " ";
|
||||
if (timeinfo.tm_hour < 10)
|
||||
s += "0";
|
||||
tmp = intStr(timeinfo.tm_hour);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
s += ":";
|
||||
if (timeinfo.tm_min < 10)
|
||||
s += "0";
|
||||
tmp = intStr(timeinfo.tm_min);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
s += ":";
|
||||
if (timeinfo.tm_sec < 10)
|
||||
s += "0";
|
||||
tmp = intStr(timeinfo.tm_sec);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
int p = 1;
|
||||
if (TZ < 0)
|
||||
p = -1;
|
||||
int tz = TZ;
|
||||
float dif = (p * (TZ - tz)) * 60.0;
|
||||
if (TZ < 0)
|
||||
s += " -";
|
||||
else
|
||||
s += " +";
|
||||
|
||||
if (tz < 10)
|
||||
s += "0";
|
||||
tmp = intStr(tz);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
if (dif < 10)
|
||||
s += "0";
|
||||
tmp = intStr((int)dif);
|
||||
s += tmp;
|
||||
delete[] tmp;
|
||||
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
void ESPTimeHelper::setSysTime()
|
||||
{
|
||||
#if defined(ESP32)
|
||||
getLocalTime(&timeinfo);
|
||||
#elif defined(ESP8266)
|
||||
now = time(nullptr);
|
||||
localtime_r(&now, &timeinfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //ESPTimeHelper_CPP
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* ESP8266/ESP32 Internet Time Helper Arduino Library v 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2020 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person returning a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ESPTimeHelper_H
|
||||
#define ESPTimeHelper_H
|
||||
|
||||
#include <time.h>
|
||||
#include <Arduino.h>
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
|
||||
class ESPTimeHelper
|
||||
{
|
||||
public:
|
||||
ESPTimeHelper();
|
||||
|
||||
/** Set the system time from the NTP server
|
||||
*
|
||||
* @param gmtOffset The GMT time offset in hour.
|
||||
* @param daylightOffset The Daylight time offset in hour.
|
||||
* @return boolean The status indicates the success of operation.
|
||||
*
|
||||
* @note This requires internet connection
|
||||
*/
|
||||
bool setClock(float gmtOffset, float daylightOffset);
|
||||
|
||||
/** Provide the Unix time
|
||||
*
|
||||
* @return uint32_t The value of current Unix time.
|
||||
*/
|
||||
uint32_t getUnixTime();
|
||||
|
||||
/** Provide the timestamp from the year, month, date, hour, minute,
|
||||
* and second provided.
|
||||
*
|
||||
* @param year The year.
|
||||
* @param mon The month from 1 to 12.
|
||||
* @param date The dates.
|
||||
* @param hour The hours.
|
||||
* @param mins The minutes.
|
||||
* @param sec The seconds.
|
||||
* @return time_t The value of timestamp.
|
||||
*/
|
||||
time_t getTimestamp(int year, int mon, int date, int hour, int mins, int sec);
|
||||
|
||||
/** Provide the current year.
|
||||
*
|
||||
* @return int The value of current year.
|
||||
*/
|
||||
int getYear();
|
||||
|
||||
/** Provide the current month.
|
||||
*
|
||||
* @return int The value of current month.
|
||||
*/
|
||||
int getMonth();
|
||||
|
||||
/** Provide the current date.
|
||||
*
|
||||
* @return int The value of current date.
|
||||
*/
|
||||
int getDay();
|
||||
|
||||
/** Provide the current day of week.
|
||||
*
|
||||
* @return int The value of current day of week.
|
||||
*
|
||||
* @note 1 for sunday and 7 for saturday.
|
||||
*/
|
||||
int getDayOfWeek();
|
||||
|
||||
/** Provide the current day of week in String.
|
||||
*
|
||||
* @return String The value of day of week.
|
||||
*/
|
||||
String getDayOfWeekString();
|
||||
|
||||
/** Provide the current hour.
|
||||
*
|
||||
* @return int The value of current hour (0 to 23).
|
||||
*/
|
||||
int getHour();
|
||||
|
||||
/** Provide the current minute.
|
||||
*
|
||||
* @return int The value of current minute.
|
||||
*/
|
||||
int getMin();
|
||||
|
||||
/** Provide the current second.
|
||||
*
|
||||
* @return int The value of current second.
|
||||
*/
|
||||
int getSec();
|
||||
|
||||
/** Provide the total days of current year.
|
||||
*
|
||||
* @return int The value of total days of current year.
|
||||
*/
|
||||
int getNumberOfDayThisYear();
|
||||
|
||||
/** Provide the total days of from January 1, 1970 to specific date.
|
||||
*
|
||||
* @param year The year from 1970.
|
||||
* @param mon The month from 1 to 12.
|
||||
* @param day The dates.
|
||||
* @return int The value of total days.
|
||||
*/
|
||||
int getTotalDays(int year, int month, int day);
|
||||
|
||||
/** Provide the day of week from specific date.
|
||||
*
|
||||
* @param year The year from 1970.
|
||||
* @param mon The month from 1 to 12.
|
||||
* @param day The dates.
|
||||
* @return int the value of day of week.
|
||||
* @note 1 for sunday and 7 for saturday
|
||||
*/
|
||||
int dayofWeek(int year, int month, int day);
|
||||
|
||||
/** Provide the second of current hour.
|
||||
*
|
||||
* @return int The value of current second.
|
||||
*/
|
||||
int getCurrentSecond();
|
||||
|
||||
/** Provide the current timestamp.
|
||||
*
|
||||
* @return uint64_t The value of current timestamp.
|
||||
*/
|
||||
uint64_t getCurrentTimestamp();
|
||||
|
||||
/** Provide the date and time from second counted from January 1, 1970.
|
||||
*
|
||||
* @param sec The seconds from January 1, 1970 00.00.
|
||||
* @return tm The tm structured data.
|
||||
*
|
||||
* @note The returned structured data tm has the members e.g.
|
||||
* tm_year (from 1900), tm_mon (from 0 to 11), tm_mday, tm_hour,
|
||||
* tm_min and tm_sec.
|
||||
*/
|
||||
struct tm getTimeFromSec(int seconds);
|
||||
|
||||
/** Provide the current date time string that valid for Email.
|
||||
*
|
||||
* @return String The current date time string.
|
||||
*/
|
||||
String getDateTimeString();
|
||||
|
||||
time_t now;
|
||||
uint64_t msec_time_diff = 0;
|
||||
struct tm timeinfo;
|
||||
float TZ = 0.0;
|
||||
uint8_t DST_MN = 0;
|
||||
bool clockReady = false;
|
||||
|
||||
private:
|
||||
int totalDays(int y, int m, int d);
|
||||
char *intStr(int value);
|
||||
void setSysTime();
|
||||
const char *dow[7] = {"sunday", "monday", "tuesday", "wednesday", "thurseday", "friday", "saturday"};
|
||||
const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
const char *sdow[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||
};
|
||||
|
||||
#endif //ESPTimeHelper_H
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
/*
|
||||
|
||||
To use LittleFS file system instead of SPIFFS, uncomment the following line
|
||||
|
||||
*/
|
||||
|
||||
//#define USE_LITTLEFS
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef MIMEInfo_H
|
||||
#define MIMEInfo_H
|
||||
#include <Arduino.h>
|
||||
|
||||
enum esp_mail_file_extension
|
||||
{
|
||||
esp_mail_file_extension_html,
|
||||
esp_mail_file_extension_htm,
|
||||
esp_mail_file_extension_css,
|
||||
esp_mail_file_extension_txt,
|
||||
esp_mail_file_extension_js,
|
||||
esp_mail_file_extension_json,
|
||||
esp_mail_file_extension_png,
|
||||
esp_mail_file_extension_gif,
|
||||
esp_mail_file_extension_jpg,
|
||||
esp_mail_file_extension_ico,
|
||||
esp_mail_file_extension_svg,
|
||||
esp_mail_file_extension_ttf,
|
||||
esp_mail_file_extension_otf,
|
||||
esp_mail_file_extension_woff,
|
||||
esp_mail_file_extension_woff2,
|
||||
esp_mail_file_extension_eot,
|
||||
esp_mail_file_extension_sfnt,
|
||||
esp_mail_file_extension_xml,
|
||||
esp_mail_file_extension_pdf,
|
||||
esp_mail_file_extension_zip,
|
||||
esp_mail_file_extension_gz,
|
||||
esp_mail_file_extension_appcache,
|
||||
esp_mail_file_extension_none,
|
||||
esp_mail_file_extension_maxType
|
||||
};
|
||||
|
||||
struct esp_mail_mime_prop_t
|
||||
{
|
||||
char endsWith[10];
|
||||
char mimeType[50];
|
||||
};
|
||||
|
||||
const struct esp_mail_mime_prop_t mimeinfo[esp_mail_file_extension_maxType] PROGMEM =
|
||||
{
|
||||
{".html", "text/html"},
|
||||
{".htm", "text/html"},
|
||||
{".css", "text/css"},
|
||||
{".txt", "text/plain"},
|
||||
{".js", "application/javascript"},
|
||||
{".json", "application/json"},
|
||||
{".png", "image/png"},
|
||||
{".gif", "image/gif"},
|
||||
{".jpg", "image/jpeg"},
|
||||
{".ico", "image/x-icon"},
|
||||
{".svg", "image/svg+xml"},
|
||||
{".ttf", "application/x-font-ttf"},
|
||||
{".otf", "application/x-font-opentype"},
|
||||
{".woff", "application/font-woff"},
|
||||
{".woff2", "application/font-woff2"},
|
||||
{".eot", "application/vnd.ms-fontobject"},
|
||||
{".sfnt", "application/font-sfnt"},
|
||||
{".xml", "text/xml"},
|
||||
{".pdf", "application/pdf"},
|
||||
{".zip", "application/zip"},
|
||||
{".gz", "application/x-gzip"},
|
||||
{".appcache", "text/cache-manifest"},
|
||||
{"", "application/octet-stream"}};
|
||||
|
||||
#endif
|
|
@ -1,14 +1,13 @@
|
|||
#ifndef RFC2047_CPP
|
||||
#define RFC2047_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "RFC2047.h"
|
||||
|
||||
RFC2047::RFC2047(){}
|
||||
RFC2047_Decoder::RFC2047_Decoder() {}
|
||||
RFC2047_Decoder::~RFC2047_Decoder() {}
|
||||
|
||||
|
||||
void RFC2047::rfc2047Decode(char *d, const char *s, size_t dlen){
|
||||
void RFC2047_Decoder::rfc2047Decode(char *d, const char *s, size_t dlen)
|
||||
{
|
||||
|
||||
const char *p, *q;
|
||||
size_t n;
|
||||
|
@ -52,10 +51,10 @@ void RFC2047::rfc2047Decode(char *d, const char *s, size_t dlen){
|
|||
d += n;
|
||||
}
|
||||
*d = 0;
|
||||
|
||||
}
|
||||
|
||||
void RFC2047::rfc2047DecodeWord(char *d, const char *s, size_t dlen){
|
||||
void RFC2047_Decoder::rfc2047DecodeWord(char *d, const char *s, size_t dlen)
|
||||
{
|
||||
|
||||
char *p = safe_strdup (s);
|
||||
char *pp = p;
|
||||
|
@ -154,8 +153,7 @@ void RFC2047::rfc2047DecodeWord(char *d, const char *s, size_t dlen){
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
void *RFC2047::safe_calloc (size_t nmemb, size_t size)
|
||||
void *RFC2047_Decoder::safe_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
|
@ -169,7 +167,7 @@ void *RFC2047::safe_calloc (size_t nmemb, size_t size)
|
|||
return p;
|
||||
}
|
||||
|
||||
void *RFC2047::safe_malloc (unsigned int siz)
|
||||
void *RFC2047_Decoder::safe_malloc(unsigned int siz)
|
||||
{
|
||||
void *p;
|
||||
|
||||
|
@ -183,7 +181,7 @@ void *RFC2047::safe_malloc (unsigned int siz)
|
|||
return (p);
|
||||
}
|
||||
|
||||
void RFC2047::safe_realloc (void **p, size_t siz)
|
||||
void RFC2047_Decoder::safe_realloc(void **p, size_t siz)
|
||||
{
|
||||
void *r;
|
||||
|
||||
|
@ -213,7 +211,7 @@ void RFC2047::safe_realloc (void **p, size_t siz)
|
|||
*p = r;
|
||||
}
|
||||
|
||||
void RFC2047::safe_free (void *ptr)
|
||||
void RFC2047_Decoder::safe_free(void *ptr)
|
||||
{
|
||||
void **p = (void **)ptr;
|
||||
if (*p)
|
||||
|
@ -223,7 +221,7 @@ void RFC2047::safe_free (void *ptr)
|
|||
}
|
||||
}
|
||||
|
||||
char *RFC2047::safe_strdup (const char *s)
|
||||
char *RFC2047_Decoder::safe_strdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
size_t l;
|
||||
|
@ -235,6 +233,5 @@ char *RFC2047::safe_strdup (const char *s)
|
|||
return (p);
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //RFC2047_CPP
|
|
@ -2,7 +2,6 @@
|
|||
#ifndef RFC2047_H
|
||||
#define RFC2047_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
|
@ -47,10 +46,11 @@ __attribute__((used)) static int Index_64[128] = {
|
|||
#define hexval(c) Index_hex[(unsigned int)(c)]
|
||||
#define base64val(c) Index_64[(unsigned int)(c)]
|
||||
|
||||
class RFC2047{
|
||||
class RFC2047_Decoder{
|
||||
|
||||
public:
|
||||
RFC2047();
|
||||
RFC2047_Decoder();
|
||||
~RFC2047_Decoder();
|
||||
void rfc2047Decode(char *d, const char *s, size_t dlen);
|
||||
|
||||
|
||||
|
@ -65,6 +65,5 @@ class RFC2047{
|
|||
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //RFC2047_H
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Customized version of ESP32 HTTPClient Library.
|
||||
*
|
||||
* v 1.1.1
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_Mail_HTTPClient32_CPP
|
||||
#define ESP_Mail_HTTPClient32_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "ESP_Mail_HTTPClient32.h"
|
||||
|
||||
ESP_Mail_HTTPClient32::ESP_Mail_HTTPClient32()
|
||||
{
|
||||
transportTraits = ESP_Mail_TransportTraitsPtr(new ESP_Mail_TLSTraits(nullptr));
|
||||
_wcs = transportTraits->create();
|
||||
}
|
||||
|
||||
ESP_Mail_HTTPClient32::~ESP_Mail_HTTPClient32()
|
||||
{
|
||||
if (_wcs)
|
||||
{
|
||||
_wcs->stop();
|
||||
_wcs.reset(nullptr);
|
||||
_wcs.release();
|
||||
}
|
||||
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)
|
||||
{
|
||||
_host = host;
|
||||
_port = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient32::connected()
|
||||
{
|
||||
if (_wcs)
|
||||
{
|
||||
if (_secured)
|
||||
return _wcs->connected();
|
||||
else
|
||||
return _wcs->_ns_connected();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient32::send(const char *header)
|
||||
{
|
||||
if (!connected())
|
||||
return false;
|
||||
if (_secured)
|
||||
return (_wcs->write(header, strlen(header)) == strlen(header));
|
||||
else
|
||||
return (_wcs->_ns_write(header, strlen(header)) == strlen(header));
|
||||
}
|
||||
|
||||
int ESP_Mail_HTTPClient32::send(const char *header, const char *payload)
|
||||
{
|
||||
size_t size = strlen(payload);
|
||||
if (strlen(header) > 0)
|
||||
{
|
||||
if (!connect(_secured))
|
||||
{
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_CONNECTION_REFUSED;
|
||||
}
|
||||
|
||||
if (!send(header))
|
||||
{
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_SEND_HEADER_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
if (_secured)
|
||||
{
|
||||
if (_wcs->write(&payload[0], size) != size)
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_wcs->_ns_write(&payload[0], size) != size)
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WiFiClient *ESP_Mail_HTTPClient32::stream(void)
|
||||
{
|
||||
if (connected())
|
||||
return _wcs.get();
|
||||
return nullptr;
|
||||
}
|
||||
ESP_Mail_WCS32 *ESP_Mail_HTTPClient32::_stream(void)
|
||||
{
|
||||
if (connected())
|
||||
return _wcs.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t ESP_Mail_HTTPClient32::_ns_print(const char *buf)
|
||||
{
|
||||
size_t size = strlen(buf);
|
||||
return _wcs->_ns_write(&buf[0], size);
|
||||
}
|
||||
|
||||
size_t ESP_Mail_HTTPClient32::_ns_println(const char *buf)
|
||||
{
|
||||
size_t size = strlen(buf);
|
||||
size_t wr = _wcs->_ns_write((const char *)&buf[0], size);
|
||||
std::string s = "\r\n";
|
||||
wr += _wcs->_ns_write(s.c_str(), s.length());
|
||||
return wr;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient32::connect(void)
|
||||
{
|
||||
return connect(false);
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient32::connect(bool secured)
|
||||
{
|
||||
_secured = secured;
|
||||
|
||||
if (connected())
|
||||
{
|
||||
if (_secured)
|
||||
{
|
||||
while (_wcs->available() > 0)
|
||||
_wcs->read();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (_wcs->_ns_available() > 0)
|
||||
_wcs->_ns_read();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transportTraits)
|
||||
return false;
|
||||
|
||||
transportTraits->verify(*_wcs, _host.c_str(), !secured, _debugCallback);
|
||||
if (!_wcs->connect(_host.c_str(), _port))
|
||||
return false;
|
||||
return connected();
|
||||
}
|
||||
|
||||
void ESP_Mail_HTTPClient32::setDebugCallback(DebugMsgCallback cb)
|
||||
{
|
||||
_debugCallback = std::move(cb);
|
||||
}
|
||||
|
||||
void ESP_Mail_HTTPClient32::setCACert(const char *caCert)
|
||||
{
|
||||
if (caCert)
|
||||
{
|
||||
transportTraits.reset(nullptr);
|
||||
transportTraits = ESP_Mail_TransportTraitsPtr(new ESP_Mail_TLSTraits(caCert));
|
||||
_certType = 1;
|
||||
}
|
||||
else
|
||||
_certType = 0;
|
||||
}
|
||||
|
||||
void ESP_Mail_HTTPClient32::setCertFile(const char *caCertFile, esp_mail_file_storage_type storageType)
|
||||
{
|
||||
|
||||
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 (SPIFFS.exists(caCertFile))
|
||||
f = SPIFFS.open(caCertFile, FILE_READ);
|
||||
}
|
||||
else if (storageType == esp_mail_file_storage_type::esp_mail_file_storage_type_sd)
|
||||
{
|
||||
if (SD.exists(caCertFile))
|
||||
f = SD.open(caCertFile, FILE_READ);
|
||||
}
|
||||
|
||||
if (f)
|
||||
{
|
||||
size_t len = f.size();
|
||||
_cacert.reset(new char);
|
||||
_cacert = nullptr;
|
||||
_cacert = std::unique_ptr<char>(new char[len]);
|
||||
|
||||
if (f.available())
|
||||
f.readBytes(_cacert.get(), len);
|
||||
|
||||
f.close();
|
||||
|
||||
transportTraits.reset(nullptr);
|
||||
transportTraits = ESP_Mail_TransportTraitsPtr(new ESP_Mail_TLSTraits(_cacert.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP_Mail_HTTPClient32_CPP
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Customized version of ESP32 HTTPClient Library.
|
||||
*
|
||||
* v 1.1.1
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_Mail_HTTPClient32_H
|
||||
#define ESP_Mail_HTTPClient32_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <FS.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <SD.h>
|
||||
#include "ESP_Mail_WCS32.h"
|
||||
|
||||
#if __has_include(<WiFiEspAT.h>) || __has_include(<espduino.h>)
|
||||
#error WiFi UART bridge was not supported.
|
||||
#endif
|
||||
|
||||
#define ESP_MAIL_ERROR_HTTPC_ERROR_CONNECTION_REFUSED (-1)
|
||||
#define ESP_MAIL_ERROR_HTTPC_ERROR_SEND_HEADER_FAILED (-2)
|
||||
#define ESP_MAIL_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED (-3)
|
||||
#define ESP_MAIL_DEFAULT_TCP_TIMEOUT_SEC 30
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
class ESP_Mail_TransportTraits
|
||||
{
|
||||
public:
|
||||
virtual ~ESP_Mail_TransportTraits() {}
|
||||
|
||||
virtual std::unique_ptr<ESP_Mail_WCS32> create()
|
||||
{
|
||||
return std::unique_ptr<ESP_Mail_WCS32>(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<ESP_Mail_WCS32> create() override
|
||||
{
|
||||
return std::unique_ptr<ESP_Mail_WCS32>(new ESP_Mail_WCS32());
|
||||
}
|
||||
|
||||
bool verify(ESP_Mail_WCS32 &client, const char *host, bool starttls, DebugMsgCallback cb) override
|
||||
{
|
||||
ESP_Mail_WCS32 &wcs = static_cast<ESP_Mail_WCS32 &>(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_TransportTraits> ESP_Mail_TransportTraitsPtr;
|
||||
|
||||
class ESP_Mail_HTTPClient32
|
||||
{
|
||||
public:
|
||||
ESP_Mail_HTTPClient32();
|
||||
~ESP_Mail_HTTPClient32();
|
||||
|
||||
/**
|
||||
* Initialization of new http connection.
|
||||
* \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
|
||||
*/
|
||||
bool begin(const char *host, uint16_t port);
|
||||
|
||||
/**
|
||||
* Check the http connection status.
|
||||
* \return True if connected.
|
||||
*/
|
||||
bool connected();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
bool send(const char *header);
|
||||
|
||||
/**
|
||||
* Get the WiFi client pointer.
|
||||
* \return WiFi client pointer.
|
||||
*/
|
||||
WiFiClient *stream(void);
|
||||
|
||||
ESP_Mail_WCS32 *_stream(void);
|
||||
size_t _ns_print(const char *buf);
|
||||
size_t _ns_println(const char *buf);
|
||||
|
||||
int tcpTimeout = 40000;
|
||||
bool connect(void);
|
||||
bool connect(bool secured);
|
||||
void setCACert(const char *caCert);
|
||||
void setCertFile(const char *caCertFile, esp_mail_file_storage_type storageType);
|
||||
void setDebugCallback(DebugMsgCallback cb);
|
||||
bool _secured = true;
|
||||
|
||||
int _certType = -1;
|
||||
std::string _caCertFile = "";
|
||||
esp_mail_file_storage_type _caCertFileStoreageType = esp_mail_file_storage_type::esp_mail_file_storage_type_none;
|
||||
|
||||
protected:
|
||||
DebugMsgCallback _debugCallback = NULL;
|
||||
ESP_Mail_TransportTraitsPtr transportTraits;
|
||||
std::unique_ptr<ESP_Mail_WCS32> _wcs;
|
||||
std::unique_ptr<char> _cacert;
|
||||
|
||||
std::string _host = "";
|
||||
uint16_t _port = 0;
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP_Mail_HTTPClient32_H
|
|
@ -0,0 +1,553 @@
|
|||
/*
|
||||
*Customized WiFiClientSecure.cpp version 1.0.3
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
WiFiClientSecure.cpp - Client Secure class for ESP32
|
||||
Copyright (c) 2016 Hristo Gochkov All right reserved.
|
||||
Additions Copyright (C) 2017 Evandro Luis Copercini.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ESP_Mail_WCS32_CPP
|
||||
#define ESP_Mail_WCS32_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "ESP_Mail_WCS32.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#undef connect
|
||||
#undef write
|
||||
#undef read
|
||||
|
||||
ESP_Mail_WCS32::ESP_Mail_WCS32()
|
||||
{
|
||||
_connected = false;
|
||||
|
||||
sslclient = new esp_mail_ssl_ctx32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = -1;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
ESP_Mail_WCS32::ESP_Mail_WCS32(int sock)
|
||||
{
|
||||
_connected = false;
|
||||
_timeout = 0;
|
||||
|
||||
sslclient = new esp_mail_ssl_ctx32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = sock;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
|
||||
if (sock >= 0)
|
||||
{
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
ESP_Mail_WCS32::ESP_Mail_WCS32(bool secured)
|
||||
{
|
||||
_connected = false;
|
||||
sslclient = new esp_mail_ssl_ctx32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = -1;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
_secured = secured;
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
ESP_Mail_WCS32::~ESP_Mail_WCS32()
|
||||
{
|
||||
stop();
|
||||
delete sslclient;
|
||||
}
|
||||
|
||||
ESP_Mail_WCS32 &ESP_Mail_WCS32::operator=(const ESP_Mail_WCS32 &other)
|
||||
{
|
||||
stop();
|
||||
sslclient->socket = other.sslclient->socket;
|
||||
_connected = other._connected;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::stop()
|
||||
{
|
||||
if (sslclient->socket >= 0)
|
||||
{
|
||||
close(sslclient->socket);
|
||||
sslclient->socket = -1;
|
||||
_connected = false;
|
||||
_peek = -1;
|
||||
}
|
||||
stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(ip, port, _pskIdent, _psKey);
|
||||
return connect(ip, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::connect(IPAddress ip, uint16_t port, int32_t timeout)
|
||||
{
|
||||
_timeout = timeout;
|
||||
return connect(ip, port);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::connect(const char *host, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(host, port, _pskIdent, _psKey);
|
||||
return connect(host, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::connect(const char *host, uint16_t port, int32_t timeout)
|
||||
{
|
||||
_timeout = 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
_host = host;
|
||||
_port = port;
|
||||
_withCert = true;
|
||||
|
||||
if (_timeout > 0)
|
||||
{
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
|
||||
int ret = start_socket(sslclient, host, port, _timeout);
|
||||
_lastError = ret;
|
||||
if (ret < 0)
|
||||
{
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_secured)
|
||||
{
|
||||
ret = start_ssl_client(sslclient, host, port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL);
|
||||
_lastError = ret;
|
||||
if (ret < 0)
|
||||
{
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey)
|
||||
{
|
||||
_host = host;
|
||||
_port = port;
|
||||
_withCert = true;
|
||||
|
||||
log_v("start_ssl_client with PSK");
|
||||
if (_timeout > 0)
|
||||
{
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_socket(sslclient, host, port, _timeout);
|
||||
_lastError = ret;
|
||||
if (ret < 0)
|
||||
{
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_secured)
|
||||
{
|
||||
ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey);
|
||||
_lastError = ret;
|
||||
if (ret < 0)
|
||||
{
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::peek()
|
||||
{
|
||||
if (_peek >= 0)
|
||||
{
|
||||
return _peek;
|
||||
}
|
||||
_peek = timedRead();
|
||||
return _peek;
|
||||
}
|
||||
|
||||
size_t ESP_Mail_WCS32::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::read()
|
||||
{
|
||||
uint8_t data = -1;
|
||||
int res = read(&data, 1);
|
||||
if (res < 0)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t ESP_Mail_WCS32::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_connected)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int res = send_ssl_data(sslclient, buf, size);
|
||||
if (res < 0)
|
||||
{
|
||||
stop();
|
||||
res = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
int peeked = 0;
|
||||
int avail = available();
|
||||
if ((!buf && size) || avail <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (_peek >= 0)
|
||||
{
|
||||
buf[0] = _peek;
|
||||
_peek = -1;
|
||||
size--;
|
||||
avail--;
|
||||
if (!size || !avail)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
buf++;
|
||||
peeked = 1;
|
||||
}
|
||||
|
||||
int res = get_ssl_receive(sslclient, buf, size);
|
||||
if (res < 0)
|
||||
{
|
||||
stop();
|
||||
return peeked ? peeked : res;
|
||||
}
|
||||
return res + peeked;
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::available()
|
||||
{
|
||||
int peeked = (_peek >= 0);
|
||||
if (!_connected)
|
||||
{
|
||||
return peeked;
|
||||
}
|
||||
int res = data_to_read(sslclient);
|
||||
if (res < 0)
|
||||
{
|
||||
stop();
|
||||
return peeked ? peeked : res;
|
||||
}
|
||||
return res + peeked;
|
||||
}
|
||||
|
||||
uint8_t ESP_Mail_WCS32::connected()
|
||||
{
|
||||
uint8_t dummy = 0;
|
||||
read(&dummy, 0);
|
||||
|
||||
return _connected;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setCACert(const char *rootCA)
|
||||
{
|
||||
_CA_cert = rootCA;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setCertificate(const char *client_ca)
|
||||
{
|
||||
_cert = client_ca;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setPrivateKey(const char *private_key)
|
||||
{
|
||||
_private_key = private_key;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setPreSharedKey(const char *pskIdent, const char *psKey)
|
||||
{
|
||||
_pskIdent = pskIdent;
|
||||
_psKey = psKey;
|
||||
}
|
||||
|
||||
bool ESP_Mail_WCS32::verify(const char *fp, const char *domain_name)
|
||||
{
|
||||
if (!sslclient)
|
||||
return false;
|
||||
|
||||
return 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);
|
||||
if (!dest)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (size != stream.readBytes(dest, size))
|
||||
{
|
||||
free(dest);
|
||||
dest = nullptr;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool ESP_Mail_WCS32::loadCACert(Stream &stream, size_t size)
|
||||
{
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest)
|
||||
{
|
||||
setCACert(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ESP_Mail_WCS32::loadCertificate(Stream &stream, size_t size)
|
||||
{
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest)
|
||||
{
|
||||
setCertificate(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ESP_Mail_WCS32::loadPrivateKey(Stream &stream, size_t size)
|
||||
{
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest)
|
||||
{
|
||||
setPrivateKey(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::lastError(char *buf, const size_t size)
|
||||
{
|
||||
if (!_lastError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(_lastError, error_buf, 100);
|
||||
snprintf(buf, size, "%s", error_buf);
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setHandshakeTimeout(unsigned long handshake_timeout)
|
||||
{
|
||||
sslclient->handshake_timeout = handshake_timeout * 1000;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setSTARTTLS(bool enable)
|
||||
{
|
||||
_secured = !enable;
|
||||
}
|
||||
|
||||
void ESP_Mail_WCS32::setDebugCB(DebugMsgCallback cb)
|
||||
{
|
||||
sslclient->_debugCallback = std::move(cb);
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::_ns_available()
|
||||
{
|
||||
if (sslclient->socket < 0)
|
||||
return false;
|
||||
|
||||
if (_rxBuf.length() == 0)
|
||||
{
|
||||
int bufLen = 1024;
|
||||
char *tmp = new char[bufLen];
|
||||
memset(tmp, 0, bufLen);
|
||||
int ret = _ns_lwip_read(sslclient, tmp, bufLen);
|
||||
if (ret > 0)
|
||||
_rxBuf += tmp;
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
int result = _rxBuf.length();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
optimistic_yield(100);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
size_t ESP_Mail_WCS32::_ns_read(char *buf, size_t size)
|
||||
{
|
||||
if (_rxBuf.length() == 0)
|
||||
return _ns_lwip_read(sslclient, buf, size);
|
||||
else
|
||||
{
|
||||
size_t sz = size;
|
||||
if (sz > _rxBuf.length())
|
||||
sz = _rxBuf.length();
|
||||
strncpy(buf, _rxBuf.c_str(), sz);
|
||||
_rxBuf.erase(0, sz);
|
||||
return sz;
|
||||
}
|
||||
}
|
||||
|
||||
int ESP_Mail_WCS32::_ns_read()
|
||||
{
|
||||
int c = -1;
|
||||
if (_rxBuf.length() == 0)
|
||||
{
|
||||
char *buf = new char[2];
|
||||
memset(buf, 0, 2);
|
||||
int ret = _ns_lwip_read(sslclient, buf, 1);
|
||||
if (ret > 0)
|
||||
c = buf[0];
|
||||
delete[] buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = _rxBuf.c_str()[0];
|
||||
_rxBuf.erase(0, 1);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
uint8_t ESP_Mail_WCS32::_ns_connected()
|
||||
{
|
||||
return sslclient->socket >= 0;
|
||||
}
|
||||
|
||||
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);
|
||||
else if (_withCert)
|
||||
ret = start_ssl_client(sslclient, _host.c_str(), _port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey);
|
||||
|
||||
_lastError = ret;
|
||||
if (ret < 0)
|
||||
{
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //WiFiClientSecureESP32_CPP
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
/*
|
||||
*Customized WiFiClientSecure.h to support STARTTLS protocol, version 1.0.1
|
||||
*Customized WiFiClientSecure.h version 1.0.3
|
||||
*
|
||||
* 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 obtaining a copy of
|
||||
|
@ -25,7 +25,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
WiFiClientSecureESP32.h - Base class that provides Client SSL to ESP32
|
||||
WiFiClientSecure.h - Base class that provides Client SSL to ESP32
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
Additions Copyright (C) 2017 Evandro Luis Copercini.
|
||||
|
||||
|
@ -44,22 +44,22 @@
|
|||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WiFiClientSecureESP32_H
|
||||
#define WiFiClientSecureESP32_H
|
||||
#ifndef ESP_Mail_WCS32_H
|
||||
#define ESP_Mail_WCS32_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "IPAddress.h"
|
||||
#include <WiFi.h>
|
||||
#include "ssl_client32.h"
|
||||
#include "esp_mail_ssl_client32.h"
|
||||
|
||||
typedef void (*DebugMsgCallback)(const char *msg);
|
||||
|
||||
class WiFiClientSecureESP32 : public WiFiClient
|
||||
class ESP_Mail_WCS32 : public WiFiClient
|
||||
{
|
||||
protected:
|
||||
sslclient_context32 *sslclient;
|
||||
esp_mail_ssl_ctx32 *sslclient;
|
||||
|
||||
int _lastError = 0;
|
||||
int _peek = -1;
|
||||
|
@ -72,11 +72,12 @@ protected:
|
|||
DebugMsgCallback _debugCallback = NULL;
|
||||
|
||||
public:
|
||||
WiFiClientSecureESP32 *next;
|
||||
WiFiClientSecureESP32();
|
||||
WiFiClientSecureESP32(int socket);
|
||||
WiFiClientSecureESP32(bool starttls);
|
||||
~WiFiClientSecureESP32();
|
||||
friend class ESP_Mail_HTTPClient32;
|
||||
ESP_Mail_WCS32 *next;
|
||||
ESP_Mail_WCS32();
|
||||
ESP_Mail_WCS32(int socket);
|
||||
ESP_Mail_WCS32(bool secured);
|
||||
~ESP_Mail_WCS32();
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port, int32_t timeout);
|
||||
int connect(const char *host, uint16_t port);
|
||||
|
@ -104,14 +105,20 @@ public:
|
|||
bool loadPrivateKey(Stream &stream, size_t size);
|
||||
bool verify(const char *fingerprint, const char *domain_name);
|
||||
void setHandshakeTimeout(unsigned long handshake_timeout);
|
||||
void setSTARTTLS(bool starttls);
|
||||
void setSTARTTLS(bool enable);
|
||||
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);
|
||||
int _ns_read();
|
||||
uint8_t _ns_connected();
|
||||
bool _ns_connect_ssl();
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
WiFiClientSecureESP32 &operator=(const WiFiClientSecureESP32 &other);
|
||||
ESP_Mail_WCS32 &operator=(const ESP_Mail_WCS32 &other);
|
||||
bool operator==(const bool value)
|
||||
{
|
||||
return bool() == value;
|
||||
|
@ -120,8 +127,8 @@ public:
|
|||
{
|
||||
return bool() != value;
|
||||
}
|
||||
bool operator==(const WiFiClientSecureESP32 &);
|
||||
bool operator!=(const WiFiClientSecureESP32 &rhs)
|
||||
bool operator==(const ESP_Mail_WCS32 &);
|
||||
bool operator!=(const ESP_Mail_WCS32 &rhs)
|
||||
{
|
||||
return !this->operator==(rhs);
|
||||
};
|
||||
|
@ -133,6 +140,12 @@ public:
|
|||
|
||||
private:
|
||||
char *_streamLoad(Stream &stream, size_t size);
|
||||
bool _secured = true;
|
||||
bool _withCert = false;
|
||||
bool _withKey = false;
|
||||
std::string _host = "";
|
||||
std::string _rxBuf = "";
|
||||
int _port;
|
||||
|
||||
//friend class WiFiServer;
|
||||
using Print::write;
|
||||
|
@ -140,6 +153,4 @@ private:
|
|||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //WiFiClientSecureESP32_H
|
||||
|
||||
|
||||
#endif //ESP_Mail_WCS32_H
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
*Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.3
|
||||
*Customized ssl_client.cpp to support STARTTLS protocol, version 1.0.5
|
||||
*
|
||||
* 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 obtaining a copy of
|
||||
|
@ -31,8 +31,8 @@
|
|||
* Additions Copyright (C) 2017 Evandro Luis Copercini, Apache 2.0 License.
|
||||
*/
|
||||
|
||||
#ifndef SSL_CLIENT32_CPP
|
||||
#define SSL_CLIENT32_CPP
|
||||
#ifndef ESP_MAIL_SSL_CLIENT32_CPP
|
||||
#define ESP_MAIL_SSL_CLIENT32_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
|
@ -46,10 +46,10 @@
|
|||
#include <mbedtls/oid.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "ssl_client32.h"
|
||||
#include "WiFi.h"
|
||||
#include "esp_mail_ssl_client32.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
const char *pers32 = "esp32-tls";
|
||||
const char *_esp_mail_pers32 = "esp32-tls";
|
||||
|
||||
static int handle_error(int err)
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ static int handle_error(int err)
|
|||
return err;
|
||||
}
|
||||
|
||||
void ssl_init(sslclient_context32 *ssl_client)
|
||||
void ssl_init(esp_mail_ssl_ctx32 *ssl_client)
|
||||
{
|
||||
mbedtls_ssl_init(&ssl_client->ssl_ctx);
|
||||
mbedtls_ssl_config_init(&ssl_client->ssl_conf);
|
||||
|
@ -74,14 +74,12 @@ void ssl_init(sslclient_context32 *ssl_client)
|
|||
mbedtls_net_init(&ssl_client->server_fd);
|
||||
}
|
||||
|
||||
int start_ssl_client(sslclient_context32 *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 start_socket(esp_mail_ssl_ctx32 *ssl_client, const char *host, uint32_t port, int timeout)
|
||||
{
|
||||
char buf[512];
|
||||
int ret, flags;
|
||||
int enable = 1;
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_2, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_2);
|
||||
|
||||
log_v("Free internal heap before TLS %u", ESP.getFreeHeap());
|
||||
|
||||
|
@ -92,7 +90,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
if (ssl_client->socket < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_3, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_3);
|
||||
log_e("ERROR opening socket");
|
||||
return ssl_client->socket;
|
||||
}
|
||||
|
@ -101,7 +99,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
if (!WiFiGenericClass::hostByName(host, srv))
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_4, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -112,7 +110,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
serv_addr.sin_port = htons(port);
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_5, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_5);
|
||||
|
||||
if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0)
|
||||
{
|
||||
|
@ -124,48 +122,40 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
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));
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_6, ssl_client);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_7, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_7);
|
||||
log_e("Connect to Server failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fcntl(ssl_client->socket, F_SETFL, fcntl(ssl_client->socket, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
if (ssl_client->starttls && (port == 25 || port == 587 || port == 143))
|
||||
{
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_8, ssl_client);
|
||||
|
||||
if ((ret = starttlsHandshake(ssl_client, port)) != 0)
|
||||
{
|
||||
log_e("STARTTLS failed!");
|
||||
return -1;
|
||||
}
|
||||
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)
|
||||
{
|
||||
char buf[512];
|
||||
int ret, flags;
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_9, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_9);
|
||||
|
||||
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 *)pers32, strlen(pers32));
|
||||
&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, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -176,7 +166,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_10, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_10);
|
||||
|
||||
log_v("Setting up the SSL/TLS structure...");
|
||||
|
||||
|
@ -189,7 +179,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -204,7 +194,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
if (rootCABuff != NULL)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_11, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_11);
|
||||
log_v("Loading CA cert");
|
||||
mbedtls_x509_crt_init(&ssl_client->ca_cert);
|
||||
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
|
@ -217,7 +207,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -229,13 +219,13 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
else if (pskIdent != NULL && psKey != NULL)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_12, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_12);
|
||||
log_v("Setting up PSK");
|
||||
// convert PSK from hex to binary
|
||||
if ((strlen(psKey) & 1) != 0 || strlen(psKey) > 2 * MBEDTLS_PSK_MAX_LEN)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_13, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_13);
|
||||
log_e("pre-shared key not valid hex or too long");
|
||||
return -1;
|
||||
}
|
||||
|
@ -266,7 +256,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
}
|
||||
// set mbedtls config
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_14, ssl_client);
|
||||
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)
|
||||
|
@ -275,7 +265,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -299,7 +289,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
mbedtls_pk_init(&ssl_client->client_key);
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_15, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_15);
|
||||
|
||||
log_v("Loading CRT cert");
|
||||
|
||||
|
@ -310,7 +300,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -320,7 +310,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_16, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_16);
|
||||
|
||||
log_v("Loading private key");
|
||||
ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0);
|
||||
|
@ -334,7 +324,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_17, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_17);
|
||||
|
||||
log_v("Setting hostname for TLS session...");
|
||||
|
||||
|
@ -345,7 +335,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -362,7 +352,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -375,7 +365,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_18, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_18);
|
||||
|
||||
log_v("Performing the SSL/TLS handshake...");
|
||||
unsigned long handshake_start_time = millis();
|
||||
|
@ -387,7 +377,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
{
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -415,7 +405,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
}
|
||||
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_19, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_19);
|
||||
|
||||
log_v("Verifying peer X.509 certificate...");
|
||||
|
||||
|
@ -424,7 +414,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
bzero(buf, sizeof(buf));
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags);
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_20, ssl_client);
|
||||
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);
|
||||
|
@ -432,7 +422,7 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_21, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_21);
|
||||
log_v("Certificate verified.");
|
||||
}
|
||||
|
||||
|
@ -456,10 +446,10 @@ int start_ssl_client(sslclient_context32 *ssl_client, const char *host, uint32_t
|
|||
return ssl_client->socket;
|
||||
}
|
||||
|
||||
void stop_ssl_socket(sslclient_context32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key)
|
||||
void stop_ssl_socket(esp_mail_ssl_ctx32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_22, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_22);
|
||||
log_v("Cleaning SSL connection.");
|
||||
|
||||
if (ssl_client->socket >= 0)
|
||||
|
@ -474,7 +464,7 @@ void stop_ssl_socket(sslclient_context32 *ssl_client, const char *rootCABuff, co
|
|||
mbedtls_entropy_free(&ssl_client->entropy_ctx);
|
||||
}
|
||||
|
||||
int data_to_read(sslclient_context32 *ssl_client)
|
||||
int data_to_read(esp_mail_ssl_ctx32 *ssl_client)
|
||||
{
|
||||
int ret, res;
|
||||
ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, NULL, 0);
|
||||
|
@ -488,7 +478,7 @@ int data_to_read(sslclient_context32 *ssl_client)
|
|||
char *buf = new char[512];
|
||||
char *error_buf = new char[100];
|
||||
memset(buf, 0, 512);
|
||||
strcpy_P(buf, ESP32_SSL_CLIENT_STR_1);
|
||||
strcpy_P(buf, esp_ssl_client_str_1);
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
strcat(buf, error_buf);
|
||||
ssl_client->_debugCallback(buf);
|
||||
|
@ -501,7 +491,7 @@ int data_to_read(sslclient_context32 *ssl_client)
|
|||
return res;
|
||||
}
|
||||
|
||||
int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t len)
|
||||
int send_ssl_data(esp_mail_ssl_ctx32 *ssl_client, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
|
||||
log_v("Writing HTTP request..."); //for low level debug
|
||||
|
@ -520,7 +510,7 @@ int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t
|
|||
return ret;
|
||||
}
|
||||
|
||||
int get_ssl_receive(sslclient_context32 *ssl_client, uint8_t *data, int length)
|
||||
int get_ssl_receive(esp_mail_ssl_ctx32 *ssl_client, uint8_t *data, int length)
|
||||
{
|
||||
|
||||
//log_d( "Reading HTTP response..."); //for low level debug
|
||||
|
@ -584,7 +574,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(sslclient_context32 *ssl_client, const char *fp, const char *domain_name)
|
||||
bool 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];
|
||||
|
@ -599,7 +589,7 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con
|
|||
if (pos > len - 2)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_23, ssl_client);
|
||||
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;
|
||||
}
|
||||
|
@ -607,7 +597,7 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con
|
|||
if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos + 1], &low))
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_24, ssl_client);
|
||||
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;
|
||||
}
|
||||
|
@ -621,7 +611,7 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con
|
|||
if (!crt)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_25, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_25);
|
||||
log_d("could not fetch peer certificate");
|
||||
return false;
|
||||
}
|
||||
|
@ -638,7 +628,7 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con
|
|||
if (memcmp(fingerprint_local, fingerprint_remote, 32))
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_26, ssl_client);
|
||||
ssl_client_debug_pgm_send_cb(ssl_client, esp_ssl_client_str_26);
|
||||
log_d("fingerprint doesn't match");
|
||||
return false;
|
||||
}
|
||||
|
@ -651,7 +641,7 @@ bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char *fp, con
|
|||
}
|
||||
|
||||
// Checks if peer certificate has specified domain in CN or SANs
|
||||
bool verify_ssl_dn(sslclient_context32 *ssl_client, const char *domain_name)
|
||||
bool 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);
|
||||
|
@ -698,15 +688,13 @@ bool verify_ssl_dn(sslclient_context32 *ssl_client, const char *domain_name)
|
|||
return false;
|
||||
}
|
||||
|
||||
int starttlsHandshake(sslclient_context32 *ssl_client, int port)
|
||||
int _ns_lwip_write(esp_mail_ssl_ctx32 *ssl_client, const char *buf, int bufLen)
|
||||
{
|
||||
return lwip_write(ssl_client->socket, buf, bufLen);
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
size_t msgLen = 100;
|
||||
size_t bufLen = 512;
|
||||
char *buf = new char[bufLen];
|
||||
char *hMsg = new char[msgLen];
|
||||
|
||||
int _ns_lwip_read(esp_mail_ssl_ctx32 *ssl_client, char *buf, int bufLen)
|
||||
{
|
||||
fd_set readset;
|
||||
fd_set writeset;
|
||||
fd_set errset;
|
||||
|
@ -723,127 +711,21 @@ int starttlsHandshake(sslclient_context32 *ssl_client, int port)
|
|||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_27, ssl_client);
|
||||
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
ret = read(ssl_client->socket, buf, bufLen);
|
||||
int ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_28, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ssl_client->_debugCallback(buf);
|
||||
return ret;
|
||||
|
||||
return read(ssl_client->socket, buf, bufLen);
|
||||
}
|
||||
|
||||
if (port == 587 || port == 25)
|
||||
{
|
||||
|
||||
memset(hMsg, 0, msgLen);
|
||||
strcpy_P(hMsg, ESP32_SSL_CLIENT_STR_29);
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_30, ssl_client);
|
||||
ret = lwip_write(ssl_client->socket, hMsg, strlen(hMsg));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_31, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_32, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
memset(buf, 0, bufLen);
|
||||
ret = lwip_read(ssl_client->socket, buf, bufLen);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_33, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ssl_client->_debugCallback(buf);
|
||||
}
|
||||
}
|
||||
|
||||
memset(hMsg, 0, msgLen);
|
||||
strcpy_P(hMsg, ESP32_SSL_CLIENT_STR_34);
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_35, ssl_client);
|
||||
ret = lwip_write(ssl_client->socket, hMsg, strlen(hMsg));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_36, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
ret = lwip_select(ssl_client->socket, &readset, &writeset, &errset, &tv);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_37, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
|
||||
memset(buf, 0, bufLen);
|
||||
ret = lwip_read(ssl_client->socket, buf, bufLen);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ESP32SSLClientDebugInfo(ESP32_SSL_CLIENT_STR_38, ssl_client);
|
||||
goto starttls_exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssl_client->_debugCallback)
|
||||
ssl_client->_debugCallback(buf);
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
delete[] hMsg;
|
||||
|
||||
return 0;
|
||||
|
||||
starttls_exit:
|
||||
|
||||
delete[] buf;
|
||||
delete[] hMsg;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ESP32SSLClientDebugInfo(PGM_P info, sslclient_context32 *ssl_client)
|
||||
void ssl_client_debug_pgm_send_cb(esp_mail_ssl_ctx32 *ssl_client, PGM_P info)
|
||||
{
|
||||
size_t dbgInfoLen = strlen_P(info) + 1;
|
||||
char *dbgInfo = new char[dbgInfoLen];
|
||||
memset(dbgInfo, 0, dbgInfoLen);
|
||||
strcpy_P(dbgInfo, info);
|
||||
|
||||
ssl_client->_debugCallback(dbgInfo);
|
||||
delete[] dbgInfo;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
*Customized ssl_client.h to support STARTTLS protocol, version 1.0.5
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Provide SSL/TLS functions to ESP32 with Arduino IDE
|
||||
* by Evandro Copercini - 2017 - Apache 2.0 License
|
||||
*/
|
||||
|
||||
#ifndef ESP_MAIL_SSL_CLIENT32_H
|
||||
#define ESP_MAIL_SSL_CLIENT32_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#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";
|
||||
static const char esp_ssl_client_str_3[] PROGMEM = "! E: opening socket";
|
||||
static const char esp_ssl_client_str_4[] PROGMEM = "! E: could not get ip from host";
|
||||
static const char esp_ssl_client_str_5[] PROGMEM = "> C: connecting to Server";
|
||||
static const char esp_ssl_client_str_6[] PROGMEM = "> C: server connected";
|
||||
static const char esp_ssl_client_str_7[] PROGMEM = "! E: connect to Server failed!";
|
||||
static const char esp_ssl_client_str_8[] PROGMEM = "< S: ";
|
||||
static const char esp_ssl_client_str_9[] PROGMEM = "> C: seeding the random number generator";
|
||||
static const char esp_ssl_client_str_10[] PROGMEM = "> C: setting up the SSL/TLS structure";
|
||||
static const char esp_ssl_client_str_11[] PROGMEM = "> C: loading CA cert";
|
||||
static const char esp_ssl_client_str_12[] PROGMEM = "> C: setting up PSK";
|
||||
static const char esp_ssl_client_str_13[] PROGMEM = "! E: pre-shared key not valid hex or too long";
|
||||
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_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";
|
||||
|
||||
typedef void (*DebugMsgCallback)(const char *msg);
|
||||
|
||||
typedef struct esp_mail_ssl_ctx32
|
||||
{
|
||||
int socket;
|
||||
mbedtls_ssl_context ssl_ctx;
|
||||
mbedtls_ssl_config ssl_conf;
|
||||
mbedtls_net_context server_fd;
|
||||
|
||||
mbedtls_ctr_drbg_context drbg_ctx;
|
||||
mbedtls_entropy_context entropy_ctx;
|
||||
|
||||
mbedtls_x509_crt ca_cert;
|
||||
mbedtls_x509_crt client_cert;
|
||||
mbedtls_pk_context client_key;
|
||||
DebugMsgCallback _debugCallback;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //SSL_CLIENT32_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Copy of BearSSLHelpers.h
|
||||
|
||||
WiFiClientBearSSL- SSL client/server for esp8266 using BearSSL libraries
|
||||
- Mostly compatible with Arduino WiFi shield library and standard
|
||||
WiFiClient/ServerSecure (except for certificate handling).
|
||||
|
||||
Copyright (c) 2018 Earle F. Philhower, III
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ESP_Mail_BearSSLHelpers_H
|
||||
#define ESP_Mail_BearSSLHelpers_H
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#include <bearssl/bearssl.h>
|
||||
#include <Updater.h>
|
||||
|
||||
// Internal opaque structures, not needed by user applications
|
||||
namespace ESP_Mail_brssl
|
||||
{
|
||||
class public_key;
|
||||
class private_key;
|
||||
}; // namespace ESP_Mail_brssl
|
||||
|
||||
namespace ESP_Mail
|
||||
{
|
||||
|
||||
// Holds either a single public RSA or EC key for use when BearSSL wants a pubkey.
|
||||
// Copies all associated data so no need to keep input PEM/DER keys.
|
||||
// All inputs can be either in RAM or PROGMEM.
|
||||
class PublicKey
|
||||
{
|
||||
public:
|
||||
PublicKey();
|
||||
PublicKey(const char *pemKey);
|
||||
PublicKey(const uint8_t *derKey, size_t derLen);
|
||||
~PublicKey();
|
||||
|
||||
bool parse(const char *pemKey);
|
||||
bool parse(const uint8_t *derKey, size_t derLen);
|
||||
|
||||
// Accessors for internal use, not needed by apps
|
||||
bool isRSA() const;
|
||||
bool isEC() const;
|
||||
const br_rsa_public_key *getRSA() const;
|
||||
const br_ec_public_key *getEC() const;
|
||||
|
||||
// Disable the copy constructor, we're pointer based
|
||||
PublicKey(const PublicKey &that) = delete;
|
||||
|
||||
private:
|
||||
ESP_Mail_brssl::public_key *_key;
|
||||
};
|
||||
|
||||
// Holds either a single private RSA or EC key for use when BearSSL wants a secretkey.
|
||||
// Copies all associated data so no need to keep input PEM/DER keys.
|
||||
// All inputs can be either in RAM or PROGMEM.
|
||||
class PrivateKey
|
||||
{
|
||||
public:
|
||||
PrivateKey();
|
||||
PrivateKey(const char *pemKey);
|
||||
PrivateKey(const uint8_t *derKey, size_t derLen);
|
||||
~PrivateKey();
|
||||
|
||||
bool parse(const char *pemKey);
|
||||
bool parse(const uint8_t *derKey, size_t derLen);
|
||||
|
||||
// Accessors for internal use, not needed by apps
|
||||
bool isRSA() const;
|
||||
bool isEC() const;
|
||||
const br_rsa_private_key *getRSA() const;
|
||||
const br_ec_private_key *getEC() const;
|
||||
|
||||
// Disable the copy constructor, we're pointer based
|
||||
PrivateKey(const PrivateKey &that) = delete;
|
||||
|
||||
private:
|
||||
ESP_Mail_brssl::private_key *_key;
|
||||
};
|
||||
|
||||
// Holds one or more X.509 certificates and associated trust anchors for
|
||||
// use whenever BearSSL needs a cert or TA. May want to have multiple
|
||||
// certs for things like a series of trusted CAs (but check the CertStore class
|
||||
// for a more memory efficient way).
|
||||
// Copies all associated data so no need to keep input PEM/DER certs.
|
||||
// All inputs can be either in RAM or PROGMEM.
|
||||
class ESP_Mail_X509List
|
||||
{
|
||||
public:
|
||||
ESP_Mail_X509List();
|
||||
ESP_Mail_X509List(const char *pemCert);
|
||||
ESP_Mail_X509List(const uint8_t *derCert, size_t derLen);
|
||||
~ESP_Mail_X509List();
|
||||
|
||||
bool append(const char *pemCert);
|
||||
bool append(const uint8_t *derCert, size_t derLen);
|
||||
|
||||
// Accessors
|
||||
size_t getCount() const
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
const br_x509_certificate *getX509Certs() const
|
||||
{
|
||||
return _cert;
|
||||
}
|
||||
const br_x509_trust_anchor *getTrustAnchors() const
|
||||
{
|
||||
return _ta;
|
||||
}
|
||||
|
||||
// Disable the copy constructor, we're pointer based
|
||||
ESP_Mail_X509List(const ESP_Mail_X509List &that) = delete;
|
||||
|
||||
private:
|
||||
size_t _count;
|
||||
br_x509_certificate *_cert;
|
||||
br_x509_trust_anchor *_ta;
|
||||
};
|
||||
|
||||
// Opaque object which wraps the BearSSL SSL session to make repeated connections
|
||||
// significantly faster. Completely optional.
|
||||
class ESP_Mail_WCS;
|
||||
|
||||
class Session
|
||||
{
|
||||
friend class ESP_Mail_WCS;
|
||||
|
||||
public:
|
||||
Session() { memset(&_session, 0, sizeof(_session)); }
|
||||
|
||||
private:
|
||||
br_ssl_session_parameters *getSession() { return &_session; }
|
||||
// The actual BearSSL ession information
|
||||
br_ssl_session_parameters _session;
|
||||
};
|
||||
|
||||
// Updater SHA256 hash and signature verification
|
||||
class HashSHA256 : public UpdaterHashClass
|
||||
{
|
||||
public:
|
||||
virtual void begin() override;
|
||||
virtual void add(const void *data, uint32_t len) override;
|
||||
virtual void end() override;
|
||||
virtual int len() override;
|
||||
virtual const void *hash() override;
|
||||
virtual const unsigned char *oid() override;
|
||||
|
||||
private:
|
||||
br_sha256_context _cc;
|
||||
unsigned char _sha256[32];
|
||||
};
|
||||
|
||||
class SigningVerifier : public UpdaterVerifyClass
|
||||
{
|
||||
public:
|
||||
virtual uint32_t length() override;
|
||||
virtual bool verify(UpdaterHashClass *hash, const void *signature, uint32_t signatureLen) override;
|
||||
|
||||
public:
|
||||
SigningVerifier(PublicKey *pubKey) { _pubKey = pubKey; }
|
||||
|
||||
private:
|
||||
PublicKey *_pubKey;
|
||||
};
|
||||
/*
|
||||
// Stack thunked versions of calls
|
||||
extern "C" {
|
||||
extern unsigned char *thunk_br_ssl_engine_recvapp_buf( const br_ssl_engine_context *cc, size_t *len);
|
||||
extern void thunk_br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
|
||||
extern unsigned char *thunk_br_ssl_engine_recvrec_buf( const br_ssl_engine_context *cc, size_t *len);
|
||||
extern void thunk_br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
|
||||
extern unsigned char *thunk_br_ssl_engine_sendapp_buf( const br_ssl_engine_context *cc, size_t *len);
|
||||
extern void thunk_br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
|
||||
extern unsigned char *thunk_br_ssl_engine_sendrec_buf( const br_ssl_engine_context *cc, size_t *len);
|
||||
extern void thunk_br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
|
||||
};
|
||||
*/
|
||||
|
||||
}; // namespace ESP_Mail
|
||||
|
||||
#endif /* ESP8266 */
|
||||
|
||||
#endif /* ESP_Mail_BearSSLHelpers_H */
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
Copy of CertStoreBearSSL.cpp - Library for Arduino ESP8266
|
||||
Copyright (c) 2018 Earle F. Philhower, III
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef ESP_Mail_CertStoreBearSSL_CPP
|
||||
#define ESP_Mail_CertStoreBearSSL_CPP
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#include "ESP_Mail_CertStoreBearSSL.h"
|
||||
#include <memory>
|
||||
|
||||
|
||||
#ifdef DEBUG_ESP_SSL
|
||||
#define DEBUG_BSSL(fmt, ...) DEBUG_ESP_PORT.printf_P((PGM_P)PSTR( "BSSL:" fmt), ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_BSSL(...)
|
||||
#endif
|
||||
|
||||
namespace ESP_Mail {
|
||||
|
||||
extern "C" {
|
||||
// Callback for the x509 decoder
|
||||
static void dn_append(void *ctx, const void *buf, size_t len) {
|
||||
br_sha256_context *sha1 = (br_sha256_context*)ctx;
|
||||
br_sha256_update(sha1, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ESP_Mail_CertStore::~ESP_Mail_CertStore() {
|
||||
free(_indexName);
|
||||
free(_dataName);
|
||||
}
|
||||
|
||||
ESP_Mail_CertStore::ESP_Mail_CertInfo ESP_Mail_CertStore::_preprocessCert(uint32_t length, uint32_t offset, const void *raw) {
|
||||
ESP_Mail_CertStore::ESP_Mail_CertInfo ci;
|
||||
|
||||
// Clear the CertInfo
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
// Process it using SHA256, same as the hashed_dn
|
||||
br_x509_decoder_context *ctx = new br_x509_decoder_context;
|
||||
br_sha256_context *sha256 = new br_sha256_context;
|
||||
if (!ctx || !sha256) {
|
||||
DEBUG_BSSL("CertStore::_preprocessCert: OOM\n");
|
||||
return ci;
|
||||
}
|
||||
|
||||
br_sha256_init(sha256);
|
||||
br_x509_decoder_init(ctx, dn_append, sha256, nullptr, nullptr);
|
||||
br_x509_decoder_push(ctx, (const void*)raw, length);
|
||||
|
||||
// Copy result to structure
|
||||
br_sha256_out(sha256, &ci.sha256);
|
||||
ci.length = length;
|
||||
ci.offset = offset;
|
||||
|
||||
// Clean up allocated memory
|
||||
delete sha256;
|
||||
delete ctx;
|
||||
|
||||
// Return result
|
||||
return ci;
|
||||
}
|
||||
|
||||
// The certs.ar file is a UNIX ar format file, concatenating all the
|
||||
// individual certificates into a single blob in a space-efficient way.
|
||||
int ESP_Mail_CertStore::initCertStore(FS &fs, const char *indexFileName, const char *dataFileName) {
|
||||
int count = 0;
|
||||
uint32_t offset = 0;
|
||||
|
||||
_fs = &fs;
|
||||
|
||||
// In case initCertStore called multiple times, don't leak old filenames
|
||||
free(_indexName);
|
||||
free(_dataName);
|
||||
|
||||
// No strdup_P, so manually do it
|
||||
_indexName = (char *)malloc(strlen_P(indexFileName) + 1);
|
||||
_dataName = (char *)malloc(strlen_P(dataFileName) + 1);
|
||||
if (!_indexName || !_dataName) {
|
||||
free(_indexName);
|
||||
free(_dataName);
|
||||
return 0;
|
||||
}
|
||||
memcpy_P(_indexName, indexFileName, strlen_P(indexFileName) + 1);
|
||||
memcpy_P(_dataName, dataFileName, strlen_P(dataFileName) + 1);
|
||||
|
||||
File index = _fs->open(_indexName, "w");
|
||||
if (!index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
File data = _fs->open(_dataName, "r");
|
||||
if (!data) {
|
||||
index.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t magic[8];
|
||||
if (data.read(magic, sizeof(magic)) != sizeof(magic) ||
|
||||
memcmp(magic, "!<arch>\n", sizeof(magic)) ) {
|
||||
data.close();
|
||||
index.close();
|
||||
return 0;
|
||||
}
|
||||
offset += sizeof(magic);
|
||||
|
||||
while (true) {
|
||||
uint8_t fileHeader[60];
|
||||
// 0..15 = filename in ASCII
|
||||
// 48...57 = length in decimal ASCII
|
||||
uint32_t length;
|
||||
if (data.read(fileHeader, sizeof(fileHeader)) != sizeof(fileHeader)) {
|
||||
break;
|
||||
}
|
||||
offset += sizeof(fileHeader);
|
||||
fileHeader[58] = 0;
|
||||
if (1 != sscanf((char *)(fileHeader + 48), "%d", &length) || !length) {
|
||||
break;
|
||||
}
|
||||
|
||||
void *raw = malloc(length);
|
||||
if (!raw) {
|
||||
break;
|
||||
}
|
||||
if (data.read((uint8_t *)raw, length) != length) {
|
||||
free(raw);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the filename starts with "//" then this is a rename file, skip it
|
||||
if (fileHeader[0] != '/' || fileHeader[1] != '/') {
|
||||
ESP_Mail_CertStore::ESP_Mail_CertInfo ci = _preprocessCert(length, offset, raw);
|
||||
if (index.write((uint8_t *)&ci, sizeof(ci)) != (ssize_t)sizeof(ci)) {
|
||||
free(raw);
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
offset += length;
|
||||
free(raw);
|
||||
if (offset & 1) {
|
||||
uint8_t x;
|
||||
data.read(&x, 1);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
data.close();
|
||||
index.close();
|
||||
return count;
|
||||
}
|
||||
|
||||
void ESP_Mail_CertStore::installCertStore(br_x509_minimal_context *ctx) {
|
||||
br_x509_minimal_set_dynamic(ctx, (void*)this, findHashedTA, freeHashedTA);
|
||||
}
|
||||
|
||||
const br_x509_trust_anchor *ESP_Mail_CertStore::findHashedTA(void *ctx, void *hashed_dn, size_t len) {
|
||||
ESP_Mail_CertStore *cs = static_cast<ESP_Mail_CertStore*>(ctx);
|
||||
ESP_Mail_CertStore::ESP_Mail_CertInfo ci;
|
||||
|
||||
if (!cs || len != sizeof(ci.sha256) || !cs->_indexName || !cs->_dataName || !cs->_fs) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
File index = cs->_fs->open(cs->_indexName, "r");
|
||||
if (!index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while (index.read((uint8_t *)&ci, sizeof(ci)) == sizeof(ci)) {
|
||||
if (!memcmp(ci.sha256, hashed_dn, sizeof(ci.sha256))) {
|
||||
index.close();
|
||||
uint8_t *der = (uint8_t*)malloc(ci.length);
|
||||
if (!der) {
|
||||
return nullptr;
|
||||
}
|
||||
File data = cs->_fs->open(cs->_dataName, "r");
|
||||
if (!data) {
|
||||
free(der);
|
||||
return nullptr;
|
||||
}
|
||||
if (!data.seek(ci.offset, SeekSet)) {
|
||||
data.close();
|
||||
free(der);
|
||||
return nullptr;
|
||||
}
|
||||
if (data.read((uint8_t *)der, ci.length) != ci.length) {
|
||||
free(der);
|
||||
return nullptr;
|
||||
}
|
||||
data.close();
|
||||
cs->_x509 = new ESP_Mail_X509List(der, ci.length);
|
||||
free(der);
|
||||
if (!cs->_x509) {
|
||||
DEBUG_BSSL("CertStore::findHashedTA: OOM\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
br_x509_trust_anchor *ta = (br_x509_trust_anchor*)cs->_x509->getTrustAnchors();
|
||||
memcpy(ta->dn.data, ci.sha256, sizeof(ci.sha256));
|
||||
ta->dn.len = sizeof(ci.sha256);
|
||||
|
||||
return ta;
|
||||
}
|
||||
}
|
||||
index.close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ESP_Mail_CertStore::freeHashedTA(void *ctx, const br_x509_trust_anchor *ta) {
|
||||
ESP_Mail_CertStore *cs = static_cast<ESP_Mail_CertStore*>(ctx);
|
||||
(void) ta; // Unused
|
||||
delete cs->_x509;
|
||||
cs->_x509 = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* ESP8266 */
|
||||
|
||||
#endif /* ESP_Mail_CertStoreBearSSL_CPP */
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
Copy of CertStoreBearSSL.h - Library for Arduino ESP8266
|
||||
Copyright (c) 2018 Earle F. Philhower, III
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ESP_Mail_CertStoreBearSSL_H
|
||||
#define ESP_Mail_CertStoreBearSSL_H
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP_Mail_BearSSLHelpers.h"
|
||||
#include <bearssl/bearssl.h>
|
||||
#include <FS.h>
|
||||
|
||||
// Base class for the certificate stores, which allow use
|
||||
// of a large set of certificates stored on FS or SD card to
|
||||
// be dynamically used when validating a X509 certificate
|
||||
|
||||
namespace ESP_Mail {
|
||||
|
||||
class ESP_Mail_CertStore {
|
||||
public:
|
||||
ESP_Mail_CertStore() { };
|
||||
~ESP_Mail_CertStore();
|
||||
|
||||
// Set the file interface instances, do preprocessing
|
||||
int initCertStore(FS &fs, const char *indexFileName, const char *dataFileName);
|
||||
|
||||
// Installs the cert store into the X509 decoder (normally via static function callbacks)
|
||||
void installCertStore(br_x509_minimal_context *ctx);
|
||||
|
||||
protected:
|
||||
FS *_fs = nullptr;
|
||||
char *_indexName = nullptr;
|
||||
char *_dataName = nullptr;
|
||||
ESP_Mail_X509List *_x509 = nullptr;
|
||||
|
||||
// These need to be static as they are callbacks from BearSSL C code
|
||||
static const br_x509_trust_anchor *findHashedTA(void *ctx, void *hashed_dn, size_t len);
|
||||
static void freeHashedTA(void *ctx, const br_x509_trust_anchor *ta);
|
||||
|
||||
// The binary format of the index file
|
||||
class ESP_Mail_CertInfo {
|
||||
public:
|
||||
uint8_t sha256[32];
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
};
|
||||
static ESP_Mail_CertInfo _preprocessCert(uint32_t length, uint32_t offset, const void *raw);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* ESP8266 */
|
||||
|
||||
#endif /* ESP_Mail_CertStoreBearSSL_H */
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
* HTTP Client for ESP8266 wrapper v1.0.1
|
||||
*
|
||||
* 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
|
||||
* 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_HTTPClient_CPP
|
||||
#define ESP_Mail_HTTPClient_CPP
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#include "ESP_Mail_HTTPClient.h"
|
||||
|
||||
ESP_Mail_HTTPClient::ESP_Mail_HTTPClient()
|
||||
{
|
||||
}
|
||||
|
||||
ESP_Mail_HTTPClient::~ESP_Mail_HTTPClient()
|
||||
{
|
||||
if (_wcs)
|
||||
{
|
||||
_wcs->stop();
|
||||
_wcs.reset(nullptr);
|
||||
_wcs.release();
|
||||
}
|
||||
|
||||
std::string().swap(_host);
|
||||
std::string().swap(_caCertFile);
|
||||
_cacert.reset(new char);
|
||||
_cacert = nullptr;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient::begin(const char *host, uint16_t port)
|
||||
{
|
||||
if (strcmp(_host.c_str(), host) != 0)
|
||||
mflnChecked = false;
|
||||
|
||||
_host = host;
|
||||
_port = port;
|
||||
|
||||
//probe for fragmentation support at the specified size
|
||||
if (!mflnChecked)
|
||||
{
|
||||
fragmentable = _wcs->probeMaxFragmentLength(_host.c_str(), _port, chunkSize);
|
||||
if (fragmentable)
|
||||
{
|
||||
_bsslRxSize = chunkSize;
|
||||
_bsslTxSize = chunkSize;
|
||||
_wcs->setBufferSizes(_bsslRxSize, _bsslTxSize);
|
||||
}
|
||||
mflnChecked = true;
|
||||
}
|
||||
|
||||
if (!fragmentable)
|
||||
_wcs->setBufferSizes(maxRXBufSize / rxBufDivider, maxTXBufSize / txBufDivider);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient::connected()
|
||||
{
|
||||
if (_wcs)
|
||||
{
|
||||
if (_secured)
|
||||
return _wcs->connected();
|
||||
else
|
||||
return _wcs->_ns_connected();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient::send(const char *header)
|
||||
{
|
||||
if (!connected())
|
||||
return false;
|
||||
if (_secured)
|
||||
return (_wcs->write((uint8_t *)header, strlen(header)) == strlen(header));
|
||||
else
|
||||
return (_wcs->_ns_write((uint8_t *)header, strlen(header)) == strlen(header));
|
||||
}
|
||||
|
||||
int ESP_Mail_HTTPClient::send(const char *header, const char *payload)
|
||||
{
|
||||
size_t size = strlen(payload);
|
||||
if (strlen(header) > 0)
|
||||
{
|
||||
if (!connect(_secured))
|
||||
{
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_CONNECTION_REFUSED;
|
||||
}
|
||||
|
||||
if (!send(header))
|
||||
{
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_SEND_HEADER_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
if (_secured)
|
||||
{
|
||||
if (_wcs->write((uint8_t *)&payload[0], size) != size)
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_wcs->_ns_write((uint8_t *)&payload[0], size) != size)
|
||||
return ESP_MAIL_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WiFiClient *ESP_Mail_HTTPClient::stream(void)
|
||||
{
|
||||
if (connected())
|
||||
return _wcs.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ESP_Mail::ESP_Mail_WCS *ESP_Mail_HTTPClient::_stream(void)
|
||||
{
|
||||
if (connected())
|
||||
return _wcs.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t ESP_Mail_HTTPClient::_ns_print(const char *buf)
|
||||
{
|
||||
size_t size = strlen(buf);
|
||||
return _wcs->_ns_write((uint8_t *)&buf[0], size);
|
||||
}
|
||||
|
||||
size_t ESP_Mail_HTTPClient::_ns_println(const char *buf)
|
||||
{
|
||||
size_t size = strlen(buf);
|
||||
size_t wr = _wcs->_ns_write((uint8_t *)&buf[0], size);
|
||||
std::string s = "\r\n";
|
||||
wr += _wcs->_ns_write((uint8_t *)s.c_str(), s.length());
|
||||
return wr;
|
||||
}
|
||||
|
||||
bool ESP_Mail_HTTPClient::connect(bool secured)
|
||||
{
|
||||
_secured = secured;
|
||||
|
||||
if (connected())
|
||||
{
|
||||
if (_secured)
|
||||
{
|
||||
while (_wcs->available() > 0)
|
||||
_wcs->read();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (_wcs->_ns_available() > 0)
|
||||
_wcs->_ns_read();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_wcs->setStartTLS(!_secured);
|
||||
if (!_wcs->connect(_host.c_str(), _port))
|
||||
return false;
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
void ESP_Mail_HTTPClient::setCACert(const char *caCert)
|
||||
{
|
||||
|
||||
#ifndef USING_AXTLS
|
||||
_wcs->setBufferSizes(_bsslRxSize, _bsslTxSize);
|
||||
#endif
|
||||
|
||||
if (caCert)
|
||||
{
|
||||
#ifndef USING_AXTLS
|
||||
_wcs->setTrustAnchors(new ESP_Mail::ESP_Mail_X509List(caCert));
|
||||
#else
|
||||
_wcs->setCACert_P(caCert, strlen_P(caCert));
|
||||
#endif
|
||||
_certType = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef USING_AXTLS
|
||||
_wcs->setInsecure();
|
||||
#endif
|
||||
_certType = 0;
|
||||
}
|
||||
|
||||
_wcs->setNoDelay(true);
|
||||
}
|
||||
|
||||
void ESP_Mail_HTTPClient::setCertFile(const char *caCertFile, esp_mail_file_storage_type storageType, uint8_t sdPin)
|
||||
{
|
||||
|
||||
#ifndef USING_AXTLS
|
||||
_sdPin = sdPin;
|
||||
_wcs->setBufferSizes(_bsslRxSize, _bsslTxSize);
|
||||
|
||||
if (_clockReady && strlen(caCertFile) > 0)
|
||||
{
|
||||
|
||||
if (storageType == 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
f.close();
|
||||
_wcs->setTrustAnchors(new ESP_Mail::ESP_Mail_X509List(der, len));
|
||||
delete[] der;
|
||||
}
|
||||
}
|
||||
}
|
||||
_certType = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
_wcs->setNoDelay(true);
|
||||
}
|
||||
|
||||
#endif /* ESP8266 */
|
||||
|
||||
#endif /* ESP_Mail_HTTPClient_CPP */
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* HTTP Client for ESP8266 wrapper v1.0.1
|
||||
*
|
||||
* 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
|
||||
* 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_HTTPClient_H
|
||||
#define ESP_Mail_HTTPClient_H
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
//ARDUINO_ESP8266_GIT_VER
|
||||
//2.6.2 0xbc204a9b
|
||||
//2.6.1 0x482516e3
|
||||
//2.6.0 0x643ec203
|
||||
//2.5.2 0x8b899c12
|
||||
//2.5.1 0xac02aff5
|
||||
//2.5.0 0x951aeffa
|
||||
//2.5.0-beta3 0x21db8fc9
|
||||
//2.5.0-beta2 0x0fd86a07
|
||||
//2.5.0-beta1 0x9c1e03a1
|
||||
//2.4.2 0xbb28d4a3
|
||||
//2.4.1 0x614f7c32
|
||||
//2.4.0 0x4ceabea9
|
||||
//2.4.0-rc2 0x0c897c37
|
||||
//2.4.0-rc1 0xf6d232f1
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <core_version.h>
|
||||
#include <time.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.
|
||||
#endif
|
||||
|
||||
#include <WiFiClient.h>
|
||||
|
||||
#if ARDUINO_ESP8266_GIT_VER != 0xf6d232f1 && ARDUINO_ESP8266_GIT_VER != 0x0c897c37 && ARDUINO_ESP8266_GIT_VER != 0x4ceabea9 && ARDUINO_ESP8266_GIT_VER != 0x614f7c32 && ARDUINO_ESP8266_GIT_VER != 0xbb28d4a3
|
||||
#include "ESP_Mail_WCS.h"
|
||||
#include "ESP_Mail_BearSSLHelpers.h"
|
||||
#define ESP_MAIL_SSL_CLIENT ESP_Mail::ESP_Mail_WCS
|
||||
#else
|
||||
#error Please update the ESP8266 Arduino Core SDK to latest version.
|
||||
#endif
|
||||
|
||||
#define FS_NO_GLOBALS
|
||||
#include <FS.h>
|
||||
#include <SD.h>
|
||||
#include "extras/ESP_Mail_Client_FS.h"
|
||||
|
||||
#ifdef USE_LITTLEFS
|
||||
#include <LittleFS.h>
|
||||
#define FLASH_FS LittleFS
|
||||
#else
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#define FLASH_FS SPIFFS
|
||||
#endif
|
||||
|
||||
#if __has_include(<WiFiEspAT.h>) || __has_include(<espduino.h>)
|
||||
#error WiFi UART bridge was not supported.
|
||||
#endif
|
||||
|
||||
#define ESP_MAIL_ERROR_HTTPC_ERROR_CONNECTION_REFUSED (-1)
|
||||
#define ESP_MAIL_ERROR_HTTPC_ERROR_SEND_HEADER_FAILED (-2)
|
||||
#define ESP_MAIL_ERROR_HTTPC_ERROR_SEND_PAYLOAD_FAILED (-3)
|
||||
#define ESP_MAIL_DEFAULT_TCP_TIMEOUT_SEC 30
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
class ESP_Mail_HTTPClient
|
||||
{
|
||||
|
||||
public:
|
||||
ESP_Mail_HTTPClient();
|
||||
~ESP_Mail_HTTPClient();
|
||||
|
||||
bool begin(const char *host, uint16_t port);
|
||||
|
||||
bool connected(void);
|
||||
|
||||
int send(const char *header, const char *payload);
|
||||
|
||||
bool send(const char *header);
|
||||
|
||||
WiFiClient *stream(void);
|
||||
|
||||
ESP_Mail::ESP_Mail_WCS *_stream(void);
|
||||
|
||||
size_t _ns_print(const char *buf);
|
||||
|
||||
size_t _ns_println(const char *buf);
|
||||
|
||||
void setCACert(const char *caCert);
|
||||
void setCertFile(const char *caCertFile, esp_mail_file_storage_type storageType, uint8_t sdPin);
|
||||
bool connect(bool secured);
|
||||
|
||||
int _certType = -1;
|
||||
std::string _caCertFile = "";
|
||||
esp_mail_file_storage_type _caCertFileStoreageType = esp_mail_file_storage_type::esp_mail_file_storage_type_none;
|
||||
uint16_t tcpTimeout = 40000;
|
||||
|
||||
uint8_t _sdPin = 15;
|
||||
bool _clockReady = false;
|
||||
uint16_t _bsslRxSize = 1024;
|
||||
uint16_t _bsslTxSize = 1024;
|
||||
bool fragmentable = false;
|
||||
int chunkSize = 1024;
|
||||
int maxRXBufSize = 16384; //SSL full supported 16 kB
|
||||
int maxTXBufSize = 16384;
|
||||
bool mflnChecked = false;
|
||||
int rxBufDivider = maxRXBufSize / chunkSize;
|
||||
int txBufDivider = maxRXBufSize / chunkSize;
|
||||
;
|
||||
|
||||
private:
|
||||
std::unique_ptr<ESP_MAIL_SSL_CLIENT> _wcs = std::unique_ptr<ESP_MAIL_SSL_CLIENT>(new ESP_MAIL_SSL_CLIENT());
|
||||
std::unique_ptr<char> _cacert;
|
||||
std::string _host = "";
|
||||
uint16_t _port = 0;
|
||||
bool _secured = true;
|
||||
};
|
||||
|
||||
#endif /* ESP8266 */
|
||||
|
||||
#endif /* ESP_Mail_HTTPClient_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
Customized version of WiFiClientSecure.h
|
||||
|
||||
WiFiClientBearSSL- SSL client/server for esp8266 using BearSSL libraries
|
||||
- Mostly compatible with Arduino WiFi shield library and standard
|
||||
WiFiClient/ServerSecure (except for certificate handling).
|
||||
|
||||
Copyright (c) 2018 Earle F. Philhower, III
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ESP_Mail_WCS_H
|
||||
#define ESP_Mail_WCS_H
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
#include <vector>
|
||||
#include <WiFiClient.h>
|
||||
#include <bearssl/bearssl.h>
|
||||
#include "ESP_Mail_BearSSLHelpers.h"
|
||||
#include "ESP_Mail_CertStoreBearSSL.h"
|
||||
|
||||
|
||||
namespace ESP_Mail {
|
||||
|
||||
//#define DEBUG_ESP_SSL
|
||||
//#define DEBUG_ESP_PORT Serial
|
||||
|
||||
struct br_x509_insecure_context;
|
||||
|
||||
class ESP_Mail_WCS : public WiFiClient
|
||||
{
|
||||
public:
|
||||
ESP_Mail_WCS();
|
||||
ESP_Mail_WCS(const ESP_Mail_WCS &rhs);
|
||||
~ESP_Mail_WCS() override;
|
||||
|
||||
ESP_Mail_WCS& operator=(const ESP_Mail_WCS&) = default; // The shared-ptrs handle themselves automatically
|
||||
|
||||
int connect(IPAddress ip, uint16_t port) override;
|
||||
int connect(const String& host, uint16_t port) override;
|
||||
int connect(const char* name, uint16_t port) override;
|
||||
|
||||
uint8_t connected() override;
|
||||
size_t write(const uint8_t *buf, size_t size) override;
|
||||
size_t write_P(PGM_P buf, size_t size) override;
|
||||
size_t write(const char *buf) {
|
||||
return write((const uint8_t*)buf, strlen(buf));
|
||||
}
|
||||
size_t write_P(const char *buf) {
|
||||
return write_P((PGM_P)buf, strlen_P(buf));
|
||||
}
|
||||
size_t write(Stream& stream); // Note this is not virtual
|
||||
int read(uint8_t *buf, size_t size) override;
|
||||
int available() override;
|
||||
int read() override;
|
||||
int peek() override;
|
||||
size_t peekBytes(uint8_t *buffer, size_t length) override;
|
||||
bool flush(unsigned int maxWaitMs);
|
||||
bool stop(unsigned int maxWaitMs);
|
||||
void flush() override { (void)flush(0); }
|
||||
void stop() override { (void)stop(0); }
|
||||
|
||||
// Allow sessions to be saved/restored automatically to a memory area
|
||||
void setSession(Session *session) { _session = session; }
|
||||
|
||||
// Don't validate the chain, just accept whatever is given. VERY INSECURE!
|
||||
void setInsecure() {
|
||||
_clearAuthenticationSettings();
|
||||
_use_insecure = true;
|
||||
}
|
||||
// Assume a given public key, don't validate or use cert info at all
|
||||
void setKnownKey(const PublicKey *pk, unsigned usages = BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN) {
|
||||
_clearAuthenticationSettings();
|
||||
_knownkey = pk;
|
||||
_knownkey_usages = usages;
|
||||
}
|
||||
// Only check SHA1 fingerprint of certificate
|
||||
bool setFingerprint(const uint8_t fingerprint[20]) {
|
||||
_clearAuthenticationSettings();
|
||||
_use_fingerprint = true;
|
||||
memcpy_P(_fingerprint, fingerprint, 20);
|
||||
return true;
|
||||
}
|
||||
bool setFingerprint(const char *fpStr);
|
||||
// Accept any certificate that's self-signed
|
||||
void allowSelfSignedCerts() {
|
||||
_clearAuthenticationSettings();
|
||||
_use_self_signed = true;
|
||||
}
|
||||
// Install certificates of trusted CAs or specific site
|
||||
void setTrustAnchors(const ESP_Mail_X509List *ta) {
|
||||
_clearAuthenticationSettings();
|
||||
_ta = ta;
|
||||
}
|
||||
// In cases when NTP is not used, app must set a time manually to check cert validity
|
||||
void setX509Time(time_t now) {
|
||||
_now = now;
|
||||
}
|
||||
// Install a client certificate for this connection, in case the server requires it (i.e. MQTT)
|
||||
void setClientRSACert(const ESP_Mail_X509List *cert, const PrivateKey *sk);
|
||||
void setClientECCert(const ESP_Mail_X509List *cert, const PrivateKey *sk,
|
||||
unsigned allowed_usages, unsigned cert_issuer_key_type);
|
||||
|
||||
// Sets the requested buffer size for transmit and receive
|
||||
void setBufferSizes(int recv, int xmit);
|
||||
|
||||
// Returns whether MFLN negotiation for the above buffer sizes succeeded (after connection)
|
||||
int getMFLNStatus() {
|
||||
return connected() && br_ssl_engine_get_mfln_negotiated(_eng);
|
||||
}
|
||||
|
||||
// Return an error code and possibly a text string in a passed-in buffer with last SSL failure
|
||||
int getLastSSLError(char *dest = NULL, size_t len = 0);
|
||||
|
||||
// Attach a preconfigured certificate store
|
||||
void setCertStore(ESP_Mail_CertStore *certStore) {
|
||||
_certStore = certStore;
|
||||
}
|
||||
|
||||
// Select specific ciphers (i.e. optimize for speed over security)
|
||||
// These may be in PROGMEM or RAM, either will run properly
|
||||
bool setCiphers(const uint16_t *cipherAry, int cipherCount);
|
||||
bool setCiphers(std::vector<uint16_t> list);
|
||||
bool setCiphersLessSecure(); // Only use the limited set of RSA ciphers without EC
|
||||
|
||||
// Check for Maximum Fragment Length support for given len before connection (possibly insecure)
|
||||
static bool probeMaxFragmentLength(IPAddress ip, uint16_t port, uint16_t len);
|
||||
static bool probeMaxFragmentLength(const char *hostname, uint16_t port, uint16_t len);
|
||||
static bool probeMaxFragmentLength(const String& host, uint16_t port, uint16_t len);
|
||||
|
||||
void setStartTLS(bool enable);
|
||||
size_t _ns_write(uint8_t b);
|
||||
size_t _ns_write(const uint8_t *buf, size_t size);
|
||||
size_t _ns_write(Stream &stream, size_t unused);
|
||||
size_t _ns_write(Stream &stream);
|
||||
size_t _ns_write_P(PGM_P buf, size_t size);
|
||||
int _ns_available();
|
||||
int _ns_read();
|
||||
int _ns_read(uint8_t *buf, size_t size);
|
||||
int _ns_peek();
|
||||
size_t _ns_peekBytes(uint8_t *buffer, size_t length);
|
||||
uint8_t _ns_connected();
|
||||
bool _ns_connect_ssl();
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// AxTLS API deprecated warnings to help upgrading
|
||||
|
||||
bool setCACert(const uint8_t* pk, size_t size) ;
|
||||
bool setCertificate(const uint8_t* pk, size_t size) ;
|
||||
bool setPrivateKey(const uint8_t* pk, size_t size) ;
|
||||
|
||||
bool loadCACert(Stream& stream, size_t size) ;
|
||||
bool loadCertificate(Stream& stream, size_t size) ;
|
||||
bool loadPrivateKey(Stream& stream, size_t size) ;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
bool setCACert_P(PGM_VOID_P pk, size_t size) {
|
||||
return setCACert((const uint8_t *)pk, size);
|
||||
}
|
||||
|
||||
bool setCertificate_P(PGM_VOID_P pk, size_t size) {
|
||||
return setCertificate((const uint8_t *)pk, size);
|
||||
}
|
||||
|
||||
bool setPrivateKey_P(PGM_VOID_P pk, size_t size) {
|
||||
return setPrivateKey((const uint8_t *)pk, size);
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
template<typename TFile>
|
||||
bool loadCertificate(TFile& file) {
|
||||
return loadCertificate(file, file.size());
|
||||
}
|
||||
|
||||
template<typename TFile>
|
||||
bool loadPrivateKey(TFile& file) {
|
||||
return loadPrivateKey(file, file.size());
|
||||
}
|
||||
|
||||
template<typename TFile>
|
||||
bool loadCACert(TFile& file) {
|
||||
return loadCACert(file, file.size());
|
||||
}
|
||||
|
||||
bool verify(const char* fingerprint, const char* domain_name) {
|
||||
(void)fingerprint;
|
||||
(void)domain_name;
|
||||
return connected();
|
||||
}
|
||||
|
||||
bool verifyCertChain(const char* domain_name) {
|
||||
(void)domain_name;
|
||||
return connected();
|
||||
}
|
||||
|
||||
// AxTLS API deprecated section end
|
||||
/////////////////////////////////////
|
||||
|
||||
protected:
|
||||
bool _connectSSL(const char *hostName); // Do initial SSL handshake
|
||||
|
||||
private:
|
||||
void _clear();
|
||||
void _clearAuthenticationSettings();
|
||||
// Only one of the following two should ever be != nullptr!
|
||||
std::shared_ptr<br_ssl_client_context> _sc;
|
||||
std::shared_ptr<br_ssl_server_context> _sc_svr;
|
||||
inline bool ctx_present() {
|
||||
return (_sc != nullptr) || (_sc_svr != nullptr);
|
||||
}
|
||||
br_ssl_engine_context *_eng; // &_sc->eng, to allow for client or server contexts
|
||||
std::shared_ptr<br_x509_minimal_context> _x509_minimal;
|
||||
std::shared_ptr<struct br_x509_insecure_context> _x509_insecure;
|
||||
std::shared_ptr<br_x509_knownkey_context> _x509_knownkey;
|
||||
std::shared_ptr<unsigned char> _iobuf_in;
|
||||
std::shared_ptr<unsigned char> _iobuf_out;
|
||||
time_t _now;
|
||||
const ESP_Mail_X509List *_ta;
|
||||
ESP_Mail_CertStore *_certStore;
|
||||
int _iobuf_in_size;
|
||||
int _iobuf_out_size;
|
||||
bool _handshake_done;
|
||||
bool _oom_err;
|
||||
|
||||
bool _secured;
|
||||
std::string _host_name;
|
||||
|
||||
// AXTLS compatibility shim elements:
|
||||
// AXTLS managed memory for certs and keys, while BearSSL assumes
|
||||
// the app manages these. Use this local storage for holding the
|
||||
// BearSSL created objects in a shared form.
|
||||
std::shared_ptr<ESP_Mail_X509List> _axtls_ta;
|
||||
std::shared_ptr<ESP_Mail_X509List> _axtls_chain;
|
||||
std::shared_ptr<PrivateKey> _axtls_sk;
|
||||
|
||||
// Optional storage space pointer for session parameters
|
||||
// Will be used on connect and updated on close
|
||||
Session *_session;
|
||||
|
||||
bool _use_insecure;
|
||||
bool _use_fingerprint;
|
||||
uint8_t _fingerprint[20];
|
||||
bool _use_self_signed;
|
||||
const PublicKey *_knownkey;
|
||||
unsigned _knownkey_usages;
|
||||
|
||||
// Custom cipher list pointer or NULL if default
|
||||
std::shared_ptr<uint16_t> _cipher_list;
|
||||
uint8_t _cipher_cnt;
|
||||
|
||||
unsigned char *_recvapp_buf;
|
||||
size_t _recvapp_len;
|
||||
|
||||
bool _clientConnected(); // Is the underlying socket alive?
|
||||
void _freeSSL();
|
||||
int _run_until(unsigned target, bool blocking = true);
|
||||
size_t _write(const uint8_t *buf, size_t size, bool pmem);
|
||||
bool _wait_for_handshake(); // Sets and return the _handshake_done after connecting
|
||||
|
||||
// Optional client certificate
|
||||
const ESP_Mail_X509List *_chain;
|
||||
const PrivateKey *_sk;
|
||||
unsigned _allowed_usages;
|
||||
unsigned _cert_issuer_key_type;
|
||||
|
||||
// Methods for handling server.available() call which returns a client connection.
|
||||
friend class WiFiServerSecure; // Server needs to access these constructors
|
||||
ESP_Mail_WCS(ClientContext *client, const ESP_Mail_X509List *chain, unsigned cert_issuer_key_type,
|
||||
const PrivateKey *sk, int iobuf_in_size, int iobuf_out_size, const ESP_Mail_X509List *client_CA_ta);
|
||||
ESP_Mail_WCS(ClientContext* client, const ESP_Mail_X509List *chain, const PrivateKey *sk,
|
||||
int iobuf_in_size, int iobuf_out_size, const ESP_Mail_X509List *client_CA_ta);
|
||||
|
||||
// RSA keyed server
|
||||
bool _connectSSLServerRSA(const ESP_Mail_X509List *chain, const PrivateKey *sk, const ESP_Mail_X509List *client_CA_ta);
|
||||
// EC keyed server
|
||||
bool _connectSSLServerEC(const ESP_Mail_X509List *chain, unsigned cert_issuer_key_type, const PrivateKey *sk,
|
||||
const ESP_Mail_X509List *client_CA_ta);
|
||||
|
||||
// X.509 validators differ from server to client
|
||||
bool _installClientX509Validator(); // Set up X509 validator for a client conn.
|
||||
bool _installServerX509Validator(const ESP_Mail_X509List *client_CA_ta); // Setup X509 client cert validation, if supplied
|
||||
|
||||
uint8_t *_streamLoad(Stream& stream, size_t size);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* ESP8266 */
|
||||
|
||||
#endif /* ESP_Mail_WCS_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,278 +0,0 @@
|
|||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 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
|
||||
|
||||
//To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
|
||||
/*
|
||||
===========================================================================================================================
|
||||
To prevent stack overrun in case of you want to download email attachments in IMAP readMail,
|
||||
increase the stack size in app_main() in esp32 main.cpp will help by change the stack size from 8192 to any more value
|
||||
as following
|
||||
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||
to
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 16384, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||
|
||||
For Arduino, file esp32's main.cpp is at C:\Users\USER_NAME\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\cores\esp32\main.cpp
|
||||
And for platformIO, that file is at C:\Users\USER_NAME\.platformio\packages\framework-arduinoespressif32\cores\esp32\main.cpp
|
||||
===========================================================================================================================
|
||||
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
#include "SD.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
|
||||
|
||||
//The Email Reading data object contains config and data that received
|
||||
IMAPData imapData;
|
||||
|
||||
//Callback function to get the Email reading status
|
||||
void readCallback(ReadStatus info);
|
||||
|
||||
//List all files in SD card
|
||||
void printDirectory(File &dir, int depth);
|
||||
|
||||
void readEmail();
|
||||
|
||||
unsigned long lastTime = 0;
|
||||
|
||||
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();
|
||||
|
||||
MailClient.sdBegin();
|
||||
//MailClient.sdBegin(14,2,15,13); //SCK, MISO, MOSI,SS for TTGO T8 v1.7 or 1.8
|
||||
|
||||
File dir = SD.open("/");
|
||||
|
||||
printDirectory(dir, 0);
|
||||
|
||||
Serial.println();
|
||||
|
||||
imapData.setLogin("imap.gmail.com", 993, "YOUR_EMAIL_ACCOUNT@gmail.com", "YOUR_EMAIL_PASSWORD");
|
||||
imapData.setFolder("INBOX");
|
||||
|
||||
//Clear fetch UID
|
||||
//If fetch UID was set, no search is perform.
|
||||
imapData.setFetchUID("");
|
||||
|
||||
//imapData.setSearchCriteria("UID SINCE 10-Feb-2019");
|
||||
//imapData.setSearchCriteria("UID 700:*");
|
||||
//imapData.setSearchCriteria("UID SEARCH NOT SEEN");
|
||||
//imapData.setSearchCriteria("UID SEARCH UNSEEN");
|
||||
imapData.setSearchCriteria("UID SEARCH ALL");
|
||||
|
||||
//To fetch or read one message UID = 320
|
||||
//imapData.setFechUID("320");
|
||||
|
||||
//Set SD folder to save download messages and attachments
|
||||
imapData.setSaveFilePath("/email_data");
|
||||
|
||||
//Save attachament
|
||||
imapData.setDownloadAttachment(true);
|
||||
|
||||
//Set fetch/search result to return html message
|
||||
imapData.setHTMLMessage(true);
|
||||
|
||||
//Set fetch/search result to return text message
|
||||
imapData.setTextMessage(true);
|
||||
|
||||
//Set to save html message in SD card with decoded content.
|
||||
imapData.saveHTMLMessage(true, true);
|
||||
|
||||
//Set to save text message in SD card with decoded content.
|
||||
imapData.saveTextMessage(true, true);
|
||||
|
||||
//Set the maximum result when search criteria was set.
|
||||
imapData.setSearchLimit(10);
|
||||
|
||||
//Set the sort order of returning message upon most recent received email.
|
||||
imapData.setRecentSort(true);
|
||||
|
||||
//Set the return tex/html message size in byte.
|
||||
imapData.setMessageBufferSize(200);
|
||||
|
||||
//Set the maximum attachment size 5 MB (each file)
|
||||
imapData.setAttachmentSizeLimit(1024 * 1024 * 5);
|
||||
|
||||
//Set the Email receive callback function.
|
||||
imapData.setReadCallback(readCallback);
|
||||
|
||||
//Set to get attachment downloading progress status.
|
||||
imapData.setDownloadReport(true);
|
||||
|
||||
//Set the storage types to save download attachments or messages (SD is default)
|
||||
//imapData.setFileStorageType(MailClientStorageType::SPIFFS)
|
||||
imapData.setFileStorageType(MailClientStorageType::SD);
|
||||
|
||||
MailClient.readMail(imapData);
|
||||
}
|
||||
|
||||
void readEmail()
|
||||
{
|
||||
|
||||
Serial.println();
|
||||
Serial.println("Read Email...");
|
||||
|
||||
imapData.setFetchUID("10");
|
||||
imapData.setSearchCriteria("");
|
||||
MailClient.readMail(imapData);
|
||||
|
||||
imapData.setFetchUID("11");
|
||||
imapData.setSearchCriteria("");
|
||||
MailClient.readMail(imapData);
|
||||
|
||||
imapData.setFetchUID("12");
|
||||
imapData.setSearchCriteria("");
|
||||
MailClient.readMail(imapData);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (millis() - lastTime > 1000 * 60 * 3)
|
||||
{
|
||||
|
||||
lastTime = millis();
|
||||
Serial.println(ESP.getFreeHeap());
|
||||
|
||||
readEmail();
|
||||
}
|
||||
}
|
||||
|
||||
//Callback function to get the Email reading status
|
||||
void readCallback(ReadStatus msg)
|
||||
{
|
||||
//Print the current status
|
||||
Serial.println("INFO: " + msg.info());
|
||||
|
||||
if (msg.status() != "")
|
||||
Serial.println("STATUS: " + msg.status());
|
||||
|
||||
//Show the result when reading finished
|
||||
if (msg.success())
|
||||
{
|
||||
|
||||
for (int i = 0; i < imapData.availableMessages(); i++)
|
||||
{
|
||||
Serial.println("=================");
|
||||
|
||||
//Search result number which varied upon search crieria
|
||||
Serial.println("Messsage Number: " + imapData.getNumber(i));
|
||||
|
||||
//UID only available when assigned UID keyword in setSearchCriteria
|
||||
//e.g. imapData.setSearchCriteria("UID SEARCH ALL");
|
||||
Serial.println("Messsage UID: " + imapData.getUID(i));
|
||||
Serial.println("Messsage ID: " + imapData.getMessageID(i));
|
||||
Serial.println("Accept Language: " + imapData.getAcceptLanguage(i));
|
||||
Serial.println("Content Language: " + imapData.getContentLanguage(i));
|
||||
Serial.println("From: " + imapData.getFrom(i));
|
||||
Serial.println("From Charset: " + imapData.getFromCharset(i));
|
||||
Serial.println("To: " + imapData.getTo(i));
|
||||
Serial.println("To Charset: " + imapData.getToCharset(i));
|
||||
Serial.println("CC: " + imapData.getCC(i));
|
||||
Serial.println("CC Charset: " + imapData.getCCCharset(i));
|
||||
Serial.println("Date: " + imapData.getDate(i));
|
||||
Serial.println("Subject: " + imapData.getSubject(i));
|
||||
Serial.println("Subject Charset: " + imapData.getSubjectCharset(i));
|
||||
|
||||
//If setHeaderOnly to false;
|
||||
if (!imapData.isHeaderOnly())
|
||||
{
|
||||
Serial.println("Text Message: " + imapData.getTextMessage(i));
|
||||
Serial.println("Text Message Charset: " + imapData.getTextMessgaeCharset(i));
|
||||
Serial.println("HTML Message: " + imapData.getHTMLMessage(i));
|
||||
Serial.println("HTML Message Charset: " + imapData.getHTMLMessgaeCharset(i));
|
||||
if (imapData.isFetchMessageFailed(i))
|
||||
Serial.println("Fetch Error: " + imapData.getFetchMessageFailedReason(i));
|
||||
|
||||
if (imapData.isDownloadMessageFailed(i))
|
||||
Serial.println("Save Content Error: " + imapData.getDownloadMessageFailedReason(i));
|
||||
|
||||
if (imapData.getAttachmentCount(i) > 0)
|
||||
{
|
||||
|
||||
Serial.println("**************");
|
||||
Serial.println("Attachment: " + String(imapData.getAttachmentCount(i)) + " file(s)");
|
||||
|
||||
for (int j = 0; j < imapData.getAttachmentCount(i); j++)
|
||||
{
|
||||
Serial.println("File Index: " + String(j + 1));
|
||||
Serial.println("Filename: " + imapData.getAttachmentFileName(i, j));
|
||||
Serial.println("Name: " + imapData.getAttachmentName(i, j));
|
||||
Serial.println("Size: " + String(imapData.getAttachmentFileSize(i, j)));
|
||||
Serial.println("Type: " + imapData.getAttachmentType(i, j));
|
||||
Serial.println("Creation Date: " + imapData.getAttachmentCreationDate(i, j));
|
||||
if (imapData.isDownloadAttachmentFailed(i, j))
|
||||
Serial.println("Download Attachment Error: " + imapData.getDownloadAttachmentFailedReason(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//List all files in SD card
|
||||
void printDirectory(File &dir, int depth)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
File entry = dir.openNextFile();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
for (uint8_t i = 0; i < depth; i++)
|
||||
Serial.print("| ");
|
||||
|
||||
std::string name = entry.name();
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
Serial.print("+----" + String(name.substr(name.find_last_of("/\\") + 1).c_str()) + "\r\n");
|
||||
printDirectory(entry, depth + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("+--" + String(name.substr(name.find_last_of("/\\") + 1).c_str()));
|
||||
Serial.print("\t\t\t(");
|
||||
Serial.print(entry.size(), DEC);
|
||||
Serial.println(")");
|
||||
}
|
||||
entry.close();
|
||||
}
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
|
||||
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 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
|
||||
|
||||
//To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
#include "SD.h"
|
||||
|
||||
//For demo only
|
||||
#include "image.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
|
||||
//The Email Sending data object contains config and data to send
|
||||
SMTPData smtpData;
|
||||
|
||||
//Callback function to get the Email sending status
|
||||
void sendCallback(SendStatus info);
|
||||
|
||||
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 SD Card...");
|
||||
|
||||
if (SD.begin()) // MailClient.sdBegin(14,2,15,13) for TTGO T8 v1.7 or 1.8
|
||||
{
|
||||
|
||||
Serial.println("Preparing attach file...");
|
||||
|
||||
File file = SD.open("/text_file.txt", FILE_WRITE);
|
||||
file.print("Hello World!\r\nHello World!");
|
||||
file.close();
|
||||
|
||||
file = SD.open("/binary_file.dat", FILE_WRITE);
|
||||
|
||||
static uint8_t buf[512];
|
||||
|
||||
buf[0] = 'H';
|
||||
buf[1] = 'E';
|
||||
buf[2] = 'A';
|
||||
buf[3] = 'D';
|
||||
file.write(buf, 4);
|
||||
|
||||
size_t i;
|
||||
memset(buf, 0xff, 512);
|
||||
for (i = 0; i < 2048; i++)
|
||||
{
|
||||
file.write(buf, 512);
|
||||
}
|
||||
|
||||
buf[0] = 'T';
|
||||
buf[1] = 'A';
|
||||
buf[2] = 'I';
|
||||
buf[3] = 'L';
|
||||
file.write(buf, 4);
|
||||
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("SD Card Monting Failed");
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
|
||||
Serial.println("Sending email...");
|
||||
|
||||
//Set the Email host, port, account and password
|
||||
smtpData.setLogin("outlook.office365.com", 587, "YOUR_EMAIL_ACCOUNT@outlook.com", "YOUR_EMAIL_PASSWORD");
|
||||
|
||||
//For library version 1.2.0 and later which STARTTLS protocol was supported,the STARTTLS will be
|
||||
//enabled automatically when port 587 was used, or enable it manually using setSTARTTLS function.
|
||||
//smtpData.setSTARTTLS(true);
|
||||
|
||||
//Set the sender name and Email
|
||||
smtpData.setSender("ESP32", "SOME_EMAIL_ACCOUNT@SOME_EMAIL.com");
|
||||
|
||||
//Set Email priority or importance High, Normal, Low or 1 to 5 (1 is highest)
|
||||
smtpData.setPriority("High");
|
||||
|
||||
//Set the subject
|
||||
smtpData.setSubject("ESP32 SMTP Mail Sending Test");
|
||||
|
||||
//Set the message - normal text or html format
|
||||
smtpData.setMessage("<div style=\"color:#ff0000;font-size:20px;\">Hello World! - From ESP32</div>", true);
|
||||
|
||||
//Add recipients, can add more than one recipient
|
||||
smtpData.addRecipient("SOME_RECIPIENT@SOME_MAIL.com");
|
||||
|
||||
|
||||
|
||||
//Add attachments, can add the file or binary data from flash memory, file in SD card
|
||||
//Data from internal memory
|
||||
smtpData.addAttachData("firebase_logo.png", "image/png", (uint8_t *)dummyImageData, sizeof dummyImageData);
|
||||
|
||||
//Add attach files from SD card
|
||||
//Comment these two lines, if no SD card connected
|
||||
//Two files that previousely created.
|
||||
smtpData.addAttachFile("/binary_file.dat");
|
||||
smtpData.addAttachFile("/text_file.txt");
|
||||
|
||||
|
||||
//Add some custom header to message
|
||||
//See https://tools.ietf.org/html/rfc822
|
||||
//These header fields can be read from raw or source of message when it received)
|
||||
smtpData.addCustomMessageHeader("Date: Sat, 10 Aug 2019 21:39:56 -0700 (PDT)");
|
||||
//Be careful when set Message-ID, it should be unique, otherwise message will not store
|
||||
//smtpData.addCustomMessageHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
//Set the storage types to read the attach files (SD is default)
|
||||
//smtpData.setFileStorageType(MailClientStorageType::SPIFFS);
|
||||
smtpData.setFileStorageType(MailClientStorageType::SD);
|
||||
|
||||
|
||||
|
||||
smtpData.setSendCallback(sendCallback);
|
||||
|
||||
//Start sending Email, can be set callback function to track the status
|
||||
if (!MailClient.sendMail(smtpData))
|
||||
Serial.println("Error sending Email, " + MailClient.smtpErrorReason());
|
||||
|
||||
//Clear all data from Email object to free memory
|
||||
smtpData.empty();
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
//Callback function to get the Email sending status
|
||||
void sendCallback(SendStatus msg)
|
||||
{
|
||||
//Print the current status
|
||||
Serial.println(msg.info());
|
||||
|
||||
//Do something when complete
|
||||
if (msg.success())
|
||||
{
|
||||
Serial.println("----------------");
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
//The Email Reading data object contains config and data that received
|
||||
IMAPData imapData;
|
||||
|
||||
void readEmail();
|
||||
|
||||
unsigned long lastTime = 0;
|
||||
|
||||
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();
|
||||
|
||||
imapData.setLogin("imap.gmail.com", 993, "YOUR_EMAIL_ACCOUNT@gmail.com", "YOUR_EMAIL_PASSWORD");
|
||||
imapData.setFolder("INBOX");
|
||||
imapData.setDebug(true);
|
||||
|
||||
//Set \Seen and \Answered to flags for message with UID 100
|
||||
MailClient.setFlag(imapData, 100, "\\Seen \\Answered");
|
||||
|
||||
//Add \Seen and \Answered to flags for message with UID 100
|
||||
//MailClient.addFlag(imapData, 100, "\\Seen \\Answered");
|
||||
|
||||
//Remove \Seen and \Answered from flags for message with UID 100
|
||||
//MailClient.removeFlag(imapData, 100, "\\Seen \\Answered");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 mobizt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "ESP32_MailClient.h"
|
||||
|
||||
#define WIFI_SSID "YOUR_WIFI_SSID"
|
||||
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
|
||||
|
||||
|
||||
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();
|
||||
|
||||
//Set Clock
|
||||
//GMT offset (3 Hrs), Daylight offset (0 Hrs)
|
||||
MailClient.Time.setClock(3, 0);
|
||||
|
||||
Serial.println("Number of Days This Year (since January): " + String(MailClient.Time.getNumberOfDayThisYear()));
|
||||
Serial.println("Day of Week Number: " + String(MailClient.Time.getDayOfWeek()));
|
||||
Serial.println("Day of Week String: : " + String(MailClient.Time.getDayOfWeekString()));
|
||||
Serial.println("Total seconds today: : " + String(MailClient.Time.getCurrentSecond()));
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
if (!MailClient.Time.clockReady)
|
||||
return;
|
||||
|
||||
//Print out current date and time
|
||||
int d = MailClient.Time.getDay();
|
||||
int m = MailClient.Time.getMonth();
|
||||
int y = MailClient.Time.getYear();
|
||||
int hr = MailClient.Time.getHour();
|
||||
int min = MailClient.Time.getMin();
|
||||
int sec = MailClient.Time.getSec();
|
||||
Serial.print("Current Time (GMT+3): ");
|
||||
Serial.print(d);
|
||||
Serial.print("/");
|
||||
Serial.print(m);
|
||||
Serial.print("/");
|
||||
Serial.print(y);
|
||||
Serial.print(" ");
|
||||
Serial.print(hr);
|
||||
Serial.print(":");
|
||||
Serial.print(min);
|
||||
Serial.print(":");
|
||||
Serial.println(sec);
|
||||
|
||||
uint32_t todayFromMidnightTimestamp = MailClient.Time.getTimestamp(y, m, d, 0, 0, 0);
|
||||
uint32_t currentTimestamp = MailClient.Time.getUnixTime();
|
||||
uint32_t totalSecondsFromMidnight = currentTimestamp - todayFromMidnightTimestamp;
|
||||
|
||||
//Assumed we countdown until 15:00:00 everyday
|
||||
uint8_t targetSec = 0;
|
||||
uint8_t targetMin = 0;
|
||||
uint8_t targetHr = 15;
|
||||
uint32_t targetSecondsFromMidnight = targetHr * 60 * 60 + targetMin * 60 + targetSec;
|
||||
|
||||
if (targetSecondsFromMidnight >= totalSecondsFromMidnight)
|
||||
{
|
||||
uint32_t diffSeconds = targetSecondsFromMidnight - totalSecondsFromMidnight;
|
||||
int remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec;
|
||||
MailClient.Time.getTimeFromSec(diffSeconds, remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec);
|
||||
Serial.print("Everyday countdown until 15:00:00 is ");
|
||||
Serial.print(remainHr);
|
||||
Serial.print(" Hr, ");
|
||||
Serial.print(remainMin);
|
||||
Serial.print(" Min and ");
|
||||
Serial.print(remainSec);
|
||||
Serial.println(" Sec to go.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Everyday countdown until 15:00:00 was passed.");
|
||||
}
|
||||
|
||||
//Assumed we countdown until 18/12/2019 8:30:45
|
||||
uint32_t targetTimestamp = MailClient.Time.getTimestamp(2019, 12, 18, 8, 30, 45);
|
||||
if (targetTimestamp >= currentTimestamp)
|
||||
{
|
||||
uint32_t diffSeconds = targetTimestamp - currentTimestamp;
|
||||
int remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec;
|
||||
MailClient.Time.getTimeFromSec(diffSeconds, remainYrs, remainMonths, remainDays, remainHr, remainMin, remainSec);
|
||||
Serial.print("One time countdown until 18/12/2019 8:30:45 is ");
|
||||
Serial.print(remainYrs);
|
||||
Serial.print(" Years, ");
|
||||
Serial.print(remainMonths);
|
||||
Serial.print(" Months, ");
|
||||
Serial.print(remainDays);
|
||||
Serial.print(" Days, ");
|
||||
Serial.print(remainHr);
|
||||
Serial.print(" Hr, ");
|
||||
Serial.print(remainMin);
|
||||
Serial.print(" Min and ");
|
||||
Serial.print(remainSec);
|
||||
Serial.println(" Sec to go.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("One time countdown until 18/12/2019 8:30:45 was finished.");
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map ESP32-Mail-Client
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Classes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
IMAPData KEYWORD1
|
||||
SMTPData KEYWORD1
|
||||
attachmentData KEYWORD1
|
||||
SendStatus KEYWORD1
|
||||
messageBodyData KEYWORD1
|
||||
DownloadProgress KEYWORD1
|
||||
MessageData KEYWORD1
|
||||
|
||||
TIME KEYWORD1
|
||||
|
||||
|
||||
##################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
##################################
|
||||
|
||||
sendMail KEYWORD2
|
||||
readMail KEYWORD2
|
||||
smtpErrorReason KEYWORD2
|
||||
imapErrorReason KEYWORD2
|
||||
sdBegin KEYWORD2
|
||||
setFlag KEYWORD2
|
||||
addFlag KEYWORD2
|
||||
removeFlag KEYWORD2
|
||||
|
||||
|
||||
setClock KEYWORD2
|
||||
getUnixTime KEYWORD2
|
||||
getTimestamp KEYWORD2
|
||||
getYear KEYWORD2
|
||||
getMonth KEYWORD2
|
||||
getDay KEYWORD2
|
||||
getDayOfWeek KEYWORD2
|
||||
getDayOfWeekString KEYWORD2
|
||||
getHour KEYWORD2
|
||||
getMin KEYWORD2
|
||||
getSec KEYWORD2
|
||||
getNumberOfDayThisYear KEYWORD2
|
||||
getTotalDays KEYWORD2
|
||||
dayofweek KEYWORD2
|
||||
getCurrentSecond KEYWORD2
|
||||
getCurrentTimestamp KEYWORD2
|
||||
getTimeFromSec KEYWORD2
|
||||
|
||||
#########################################
|
||||
# Methods for IMAP Data object (KEYWORD2)
|
||||
#########################################
|
||||
|
||||
setLogin KEYWORD2
|
||||
setSTARTTLS KEYWORD2
|
||||
setDebug KEYWORD2
|
||||
setFolder KEYWORD2
|
||||
setMessageBufferSize KEYWORD2
|
||||
setAttachmentSizeLimit KEYWORD2
|
||||
setSearchCriteria KEYWORD2
|
||||
setSaveFilePath KEYWORD2
|
||||
setFechUID KEYWORD2
|
||||
setDownloadAttachment KEYWORD2
|
||||
setHTMLMessage KEYWORD2
|
||||
setTextMessage KEYWORD2
|
||||
setSearchLimit KEYWORD2
|
||||
setRecentSort KEYWORD2
|
||||
setReadCallback KEYWORD2
|
||||
setDownloadReport KEYWORD2
|
||||
isHeaderOnly KEYWORD2
|
||||
getFrom KEYWORD2
|
||||
getFromCharset KEYWORD2
|
||||
getTo KEYWORD2
|
||||
getToCharset KEYWORD2
|
||||
getCC KEYWORD2
|
||||
getCCCharset KEYWORD2
|
||||
getSubject KEYWORD2
|
||||
getSubjectCharset KEYWORD2
|
||||
getHTMLMessage KEYWORD2
|
||||
getTextMessage KEYWORD2
|
||||
getHTMLMessgaeCharset KEYWORD2
|
||||
getTextMessgaeCharset KEYWORD2
|
||||
getDate KEYWORD2
|
||||
getUID KEYWORD2
|
||||
getNumber KEYWORD2
|
||||
getMessageID KEYWORD2
|
||||
getAcceptLanguage KEYWORD2
|
||||
getContentLanguage KEYWORD2
|
||||
isFetchMessageFailed KEYWORD2
|
||||
getFetchMessageFailedReason KEYWORD2
|
||||
isDownloadAttachmentFailed KEYWORD2
|
||||
getDownloadAttachmentFailedReason KEYWORD2
|
||||
isDownloadMessageFailed KEYWORD2
|
||||
getDownloadMessageFailedReason KEYWORD2
|
||||
saveHTMLMessage KEYWORD2
|
||||
saveTextMessage KEYWORD2
|
||||
getFolderCount KEYWORD2
|
||||
getFolder KEYWORD2
|
||||
getFlagCount KEYWORD2
|
||||
getFlag KEYWORD2
|
||||
totalMessages KEYWORD2
|
||||
searchCount KEYWORD2
|
||||
availableMessages KEYWORD2
|
||||
getAttachmentCount KEYWORD2
|
||||
getAttachmentFileName KEYWORD2
|
||||
getAttachmentName KEYWORD2
|
||||
getAttachmentFileSize KEYWORD2
|
||||
getAttachmentCreationDate KEYWORD2
|
||||
getAttachmentType KEYWORD2
|
||||
empty KEYWORD2
|
||||
clearMessageData KEYWORD2
|
||||
|
||||
#########################################
|
||||
# Methods for SMTP Data object (KEYWORD2)
|
||||
#########################################
|
||||
|
||||
setSender KEYWORD2
|
||||
getFromName KEYWORD2
|
||||
getSenderEmail KEYWORD2
|
||||
setPriority KEYWORD2
|
||||
getPriority KEYWORD2
|
||||
addRecipient KEYWORD2
|
||||
removeRecipient KEYWORD2
|
||||
clearRecipient KEYWORD2
|
||||
getRecipient KEYWORD2
|
||||
recipientCount KEYWORD2
|
||||
setSubject KEYWORD2
|
||||
getSubject KEYWORD2
|
||||
setMessage KEYWORD2
|
||||
getMessage KEYWORD2
|
||||
htmlFormat KEYWORD2
|
||||
addCC KEYWORD2
|
||||
removeCC KEYWORD2
|
||||
clearCC KEYWORD2
|
||||
getCC KEYWORD2
|
||||
ccCount KEYWORD2
|
||||
addBCC KEYWORD2
|
||||
removeBCC KEYWORD2
|
||||
clearBCC KEYWORD2
|
||||
getBCC KEYWORD2
|
||||
bccCount KEYWORD2
|
||||
addAttachData KEYWORD2
|
||||
removeAttachData KEYWORD2
|
||||
attachDataCount KEYWORD2
|
||||
addAttachFile KEYWORD2
|
||||
removeAttachFile KEYWORD2
|
||||
clearAttachData KEYWORD2
|
||||
clearAttachFile KEYWORD2
|
||||
clearAttachment KEYWORD2
|
||||
attachFileCount KEYWORD2
|
||||
setSendCallback KEYWORD2
|
||||
|
||||
|
||||
############################################################
|
||||
# Functions for ReadStatus and SendStatus classes (KEYWORD2)
|
||||
############################################################
|
||||
|
||||
SendStatus KEYWORD2
|
||||
info KEYWORD2
|
||||
success KEYWORD2
|
||||
ReadStatus KEYWORD2
|
||||
status KEYWORD2
|
||||
|
||||
clockReady KEYWORD3
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"name": "ESP32 Mail Client",
|
||||
"keywords": "esp32, mail, communication",
|
||||
"description": "Mail Client Arduino Library for ESP32",
|
||||
"version": "2.1.4",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif32"
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
name=ESP32 Mail Client
|
||||
version=2.1.4
|
||||
author=Mobizt
|
||||
maintainer=Mobizt <k_suwatchai@hotmail.com.com>
|
||||
sentence=Mail Client Arduino Library for ESP32
|
||||
paragraph=This library allows ESP32 to send Email with/without attachment and receive Email with/without attachment download through SMTP and IMAP servers.
|
||||
category=Communication
|
||||
url=https://github.com/mobizt/ESP32-Mail-Client
|
||||
architectures=esp32
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
|
@ -1,200 +0,0 @@
|
|||
/*
|
||||
* Customized version of ESP32 HTTPClient Library.
|
||||
* Allow custom header and payload with STARTTLS support
|
||||
*
|
||||
* v 1.0.0
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 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.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP32MailHTTPClient_CPP
|
||||
#define ESP32MailHTTPClient_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "ESP32MailHTTPClient.h"
|
||||
|
||||
class TransportTraits
|
||||
{
|
||||
public:
|
||||
virtual ~TransportTraits() {}
|
||||
|
||||
virtual std::unique_ptr<WiFiClient> create()
|
||||
{
|
||||
return std::unique_ptr<WiFiClient>(new WiFiClient());
|
||||
}
|
||||
|
||||
virtual bool
|
||||
verify(WiFiClient &client, const char *host, bool starttls, DebugMsgCallback cb)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TLSTraits : public TransportTraits
|
||||
{
|
||||
public:
|
||||
TLSTraits(const char *CAcert, const char *clicert = nullptr, const char *clikey = nullptr) : _cacert(CAcert), _clicert(clicert), _clikey(clikey) {}
|
||||
|
||||
std::unique_ptr<WiFiClient> create() override
|
||||
{
|
||||
return std::unique_ptr<WiFiClient>(new WiFiClientSecureESP32());
|
||||
}
|
||||
|
||||
bool verify(WiFiClient &client, const char *host, bool starttls, DebugMsgCallback cb) override
|
||||
{
|
||||
WiFiClientSecureESP32 &wcs = static_cast<WiFiClientSecureESP32 &>(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;
|
||||
};
|
||||
|
||||
ESP32MailHTTPClient::ESP32MailHTTPClient() {}
|
||||
|
||||
ESP32MailHTTPClient::~ESP32MailHTTPClient()
|
||||
{
|
||||
if (_client)
|
||||
_client->stop();
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::begin(const char *host, uint16_t port, const char *uri, const char *CAcert)
|
||||
{
|
||||
transportTraits.reset(nullptr);
|
||||
|
||||
_host = host;
|
||||
_port = port;
|
||||
_uri = uri;
|
||||
transportTraits = TransportTraitsPtr(new TLSTraits(CAcert));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::connected()
|
||||
{
|
||||
if (_client)
|
||||
return ((_client->available() > 0) || _client->connected());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::sendHeader(const char *header)
|
||||
{
|
||||
if (!connected())
|
||||
return false;
|
||||
return (_client->write(header, strlen(header)) == strlen(header));
|
||||
}
|
||||
|
||||
int ESP32MailHTTPClient::sendRequest(const char *header, const char *payload)
|
||||
{
|
||||
size_t size = strlen(payload);
|
||||
if (strlen(header) > 0)
|
||||
{
|
||||
if (!connect())
|
||||
return HTTPC_ERROR_CONNECTION_REFUSED;
|
||||
if (!sendHeader(header))
|
||||
return HTTPC_ERROR_SEND_HEADER_FAILED;
|
||||
}
|
||||
if (size > 0)
|
||||
if (_client->write(&payload[0], size) != size)
|
||||
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WiFiClient *ESP32MailHTTPClient::getStreamPtr(void)
|
||||
{
|
||||
if (connected())
|
||||
return _client.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::connect(void)
|
||||
{
|
||||
if (connected())
|
||||
{
|
||||
while (_client->available() > 0)
|
||||
_client->read();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transportTraits)
|
||||
return false;
|
||||
|
||||
_client = transportTraits->create();
|
||||
|
||||
if (!transportTraits->verify(*_client, _host.c_str(), false, _debugCallback))
|
||||
{
|
||||
_client->stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_client->connect(_host.c_str(), _port))
|
||||
return false;
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
bool ESP32MailHTTPClient::connect(bool starttls)
|
||||
{
|
||||
if (connected())
|
||||
{
|
||||
while (_client->available() > 0)
|
||||
_client->read();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!transportTraits)
|
||||
return false;
|
||||
|
||||
_client = transportTraits->create();
|
||||
|
||||
if (!transportTraits->verify(*_client, _host.c_str(), starttls, _debugCallback))
|
||||
{
|
||||
_client->stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_client->connect(_host.c_str(), _port))
|
||||
return false;
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
void ESP32MailHTTPClient::setDebugCallback(DebugMsgCallback cb)
|
||||
{
|
||||
_debugCallback = std::move(cb);
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32MailHTTPClient_CPP
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Customized version of ESP32 HTTPClient Library.
|
||||
* Allow custom header and payload with STARTTLS support
|
||||
*
|
||||
* v 1.0.0
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 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.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP32MailHTTPClient_H
|
||||
#define ESP32MailHTTPClient_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#include <WiFiClient.h>
|
||||
#include "WiFiClientSecureESP32.h"
|
||||
|
||||
class ESP32MailHTTPClient : public HTTPClient
|
||||
{
|
||||
public:
|
||||
ESP32MailHTTPClient();
|
||||
~ESP32MailHTTPClient();
|
||||
|
||||
/**
|
||||
* Initialization of new http connection.
|
||||
* \param host - Host name without protocols.
|
||||
* \param port - Server's port.
|
||||
* \param uri - The URI of resource.
|
||||
* \param CAcert - The Base64 encode root certificate string
|
||||
* \return True as default.
|
||||
* If no certificate string provided, use (const char*)NULL to CAcert param
|
||||
*/
|
||||
bool begin(const char *host, uint16_t port, const char *uri, const char *CAcert);
|
||||
|
||||
/**
|
||||
* Check the http connection status.
|
||||
* \return True if connected.
|
||||
*/
|
||||
bool connected();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* with no error or no header and payload provided. If obly payload provided, no new http connection was established.
|
||||
*/
|
||||
int sendRequest(const char *header, const char *payload);
|
||||
|
||||
/**
|
||||
* Send extra header without making new http connection (if sendRequest has been called)
|
||||
* \param header - The header string (constant chars array).
|
||||
* \return True if header sending success.
|
||||
* Need to call sendRequest with header first.
|
||||
*/
|
||||
bool sendHeader(const char *header);
|
||||
|
||||
/**
|
||||
* Get the WiFi client pointer.
|
||||
* \return WiFi client pointer.
|
||||
*/
|
||||
WiFiClient *getStreamPtr(void);
|
||||
|
||||
uint16_t tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool connect(void);
|
||||
bool connect(bool starttls);
|
||||
void setDebugCallback(DebugMsgCallback cb);
|
||||
|
||||
protected:
|
||||
TransportTraitsPtr transportTraits;
|
||||
std::unique_ptr<WiFiClient> _client;
|
||||
DebugMsgCallback _debugCallback = NULL;
|
||||
|
||||
std::string _host = "";
|
||||
std::string _uri = "";
|
||||
uint16_t _port = 0;
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32MailHTTPClient_H
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* ESP32 Internet Time Helper Arduino Library v 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person returning a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ESP32TimeHelper_CPP
|
||||
#define ESP32TimeHelper_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "ESP32TimeHelper.h"
|
||||
|
||||
ESP32TimeHelper::ESP32TimeHelper()
|
||||
{
|
||||
}
|
||||
uint32_t ESP32TimeHelper::getUnixTime()
|
||||
{
|
||||
uint32_t utime = (msec_time_diff + millis()) / 1000;
|
||||
return utime;
|
||||
}
|
||||
|
||||
time_t ESP32TimeHelper::getTimestamp(int year, int mon, int date, int hour, int mins, int sec)
|
||||
{
|
||||
struct tm timeinfo;
|
||||
timeinfo.tm_year = year - 1900;
|
||||
timeinfo.tm_mon = mon - 1;
|
||||
timeinfo.tm_mday = date;
|
||||
timeinfo.tm_hour = hour;
|
||||
timeinfo.tm_min = mins;
|
||||
timeinfo.tm_sec = sec;
|
||||
time_t ts = mktime(&timeinfo);
|
||||
return ts;
|
||||
}
|
||||
|
||||
bool ESP32TimeHelper::setClock(float gmtOffset, float daylightOffset)
|
||||
{
|
||||
TZ = gmtOffset;
|
||||
DST_MN = daylightOffset;
|
||||
configTime((TZ)*3600, (DST_MN)*60, "pool.ntp.org", "time.nist.gov", NULL);
|
||||
|
||||
now = time(nullptr);
|
||||
int cnt = 0;
|
||||
while (now < 8 * 3600 * 2 && cnt < 20)
|
||||
{
|
||||
delay(50);
|
||||
now = time(nullptr);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
uint64_t tmp = now;
|
||||
tmp = tmp * 1000;
|
||||
msec_time_diff = tmp - millis();
|
||||
|
||||
getLocalTime(&timeinfo);
|
||||
|
||||
clockReady = now > 8 * 3600 * 2;
|
||||
return clockReady;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getYear()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_year + 1900;
|
||||
}
|
||||
int ESP32TimeHelper::getMonth()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_mon + 1;
|
||||
}
|
||||
int ESP32TimeHelper::getDay()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_mday;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getDayOfWeek()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_wday;
|
||||
}
|
||||
String ESP32TimeHelper::getDayOfWeekString()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return dow[timeinfo.tm_wday];
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getHour()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_hour;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getMin()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_min;
|
||||
}
|
||||
int ESP32TimeHelper::getSec()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_sec;
|
||||
}
|
||||
int ESP32TimeHelper::getNumberOfDayThisYear()
|
||||
{
|
||||
getLocalTime(&timeinfo);
|
||||
return timeinfo.tm_yday + 1;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::totalDays(int y, int m, int d)
|
||||
{
|
||||
static char daytab[2][13] =
|
||||
{
|
||||
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||
int daystotal = d;
|
||||
for (int year = 1; year <= y; year++)
|
||||
{
|
||||
int max_month = (year < y ? 12 : m - 1);
|
||||
int leap = (year % 4 == 0);
|
||||
if (year % 100 == 0 && year % 400 != 0)
|
||||
leap = 0;
|
||||
for (int month = 1; month <= max_month; month++)
|
||||
{
|
||||
daystotal += daytab[leap][month];
|
||||
}
|
||||
}
|
||||
return daystotal;
|
||||
}
|
||||
int ESP32TimeHelper::getTotalDays(int year, int month, int day)
|
||||
{
|
||||
return totalDays(year, month, day) - totalDays(1970, 1, 1);
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::dayofWeek(int year, int month, int day) /* 1 <= m <= 12, y > 1752 (in the U.K.) */
|
||||
{
|
||||
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||
year -= month < 3;
|
||||
return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
|
||||
}
|
||||
|
||||
int ESP32TimeHelper::getCurrentSecond()
|
||||
{
|
||||
return (timeinfo.tm_hour * 3600) + (timeinfo.tm_min * 60) + timeinfo.tm_sec;
|
||||
}
|
||||
uint64_t ESP32TimeHelper::getCurrentTimestamp()
|
||||
{
|
||||
return now;
|
||||
}
|
||||
void ESP32TimeHelper::getTimeFromSec(int secCount, int &yrs, int &months, int &days, int &hr, int &min, int &sec)
|
||||
{
|
||||
int _yrs = secCount / (365 * 24 * 3600);
|
||||
secCount = secCount - _yrs * (365 * 24 * 3600);
|
||||
yrs = _yrs;
|
||||
int _months = secCount / (30* 24 * 3600);
|
||||
secCount = secCount - _months * (30 * 24 * 3600);
|
||||
months = _months;
|
||||
int _days = secCount / (24 * 3600);
|
||||
secCount = secCount - _days * (24 * 3600);
|
||||
days = _days;
|
||||
int _hr = secCount / 3600;
|
||||
secCount = secCount - _hr * 3600;
|
||||
hr = _hr;
|
||||
int _min = secCount / 60;
|
||||
secCount = secCount - _min * 60;
|
||||
min = _min;
|
||||
sec = secCount;
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32TimeHelper_CPP
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* ESP32 Internet Time Helper Arduino Library v 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 K. Suwatchai (Mobizt)
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person returning a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ESP32TimeHelper_H
|
||||
#define ESP32TimeHelper_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
class ESP32TimeHelper
|
||||
{
|
||||
public:
|
||||
ESP32TimeHelper();
|
||||
bool clockReady = false;
|
||||
bool setClock(float gmtOffset, float daylightOffset);
|
||||
uint32_t getUnixTime();
|
||||
time_t getTimestamp(int year, int mon, int date, int hour, int mins, int sec);
|
||||
int getYear();
|
||||
int getMonth();
|
||||
int getDay();
|
||||
int getDayOfWeek();
|
||||
String getDayOfWeekString();
|
||||
int getHour();
|
||||
int getMin();
|
||||
int getSec();
|
||||
int getNumberOfDayThisYear();
|
||||
int getTotalDays(int year, int month, int day);
|
||||
int dayofWeek(int year, int month, int day);
|
||||
int getCurrentSecond();
|
||||
uint64_t getCurrentTimestamp();
|
||||
void getTimeFromSec(int secCount, int &yrs, int &months, int &days, int &hr, int &min, int &sec);
|
||||
|
||||
private:
|
||||
time_t now;
|
||||
uint64_t msec_time_diff = 0;
|
||||
struct tm timeinfo;
|
||||
float TZ = 0.0;
|
||||
float DST_MN = 0.0;
|
||||
|
||||
bool setClock();
|
||||
int totalDays(int y, int m, int d);
|
||||
const char *dow[20] = {"sunday", "monday", "tuesday", "wednesday", "thurseday", "friday", "saturday"};
|
||||
};
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //ESP32TimeHelper_H
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,397 +0,0 @@
|
|||
/*
|
||||
*Customized WiFiClientSecure.cpp to support STARTTLS protocol, version 1.0.1
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
WiFiClientSecureESP32.cpp - Client Secure class for ESP32
|
||||
Copyright (c) 2016 Hristo Gochkov All right reserved.
|
||||
Additions Copyright (C) 2017 Evandro Luis Copercini.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WiFiClientSecureESP32_CPP
|
||||
#define WiFiClientSecureESP32_CPP
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#include "WiFiClientSecureESP32.h"
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#undef connect
|
||||
#undef write
|
||||
#undef read
|
||||
|
||||
|
||||
WiFiClientSecureESP32::WiFiClientSecureESP32()
|
||||
{
|
||||
_connected = false;
|
||||
|
||||
sslclient = new sslclient_context32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = -1;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
|
||||
WiFiClientSecureESP32::WiFiClientSecureESP32(int sock)
|
||||
{
|
||||
_connected = false;
|
||||
_timeout = 0;
|
||||
|
||||
sslclient = new sslclient_context32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = sock;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
|
||||
if (sock >= 0) {
|
||||
_connected = true;
|
||||
}
|
||||
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
WiFiClientSecureESP32::WiFiClientSecureESP32(bool starttls)
|
||||
{
|
||||
_connected = false;
|
||||
|
||||
sslclient = new sslclient_context32;
|
||||
ssl_init(sslclient);
|
||||
sslclient->socket = -1;
|
||||
sslclient->handshake_timeout = 120000;
|
||||
sslclient->starttls = true;
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
WiFiClientSecureESP32::~WiFiClientSecureESP32()
|
||||
{
|
||||
stop();
|
||||
delete sslclient;
|
||||
}
|
||||
|
||||
WiFiClientSecureESP32 &WiFiClientSecureESP32::operator=(const WiFiClientSecureESP32 &other)
|
||||
{
|
||||
stop();
|
||||
sslclient->socket = other.sslclient->socket;
|
||||
_connected = other._connected;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::stop()
|
||||
{
|
||||
if (sslclient->socket >= 0) {
|
||||
close(sslclient->socket);
|
||||
sslclient->socket = -1;
|
||||
_connected = false;
|
||||
_peek = -1;
|
||||
}
|
||||
stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(ip, port, _pskIdent, _psKey);
|
||||
return connect(ip, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port, int32_t timeout){
|
||||
_timeout = timeout;
|
||||
return connect(ip, port);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(host, port, _pskIdent, _psKey);
|
||||
return connect(host, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port, int32_t timeout){
|
||||
_timeout = timeout;
|
||||
return connect(host, port);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::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);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key)
|
||||
{
|
||||
if(_timeout > 0){
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_ssl_client(sslclient, host, port, _timeout, _CA_cert, _cert, _private_key, NULL, NULL);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
return connect(ip.toString().c_str(), port,_pskIdent, _psKey);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
log_v("start_ssl_client with PSK");
|
||||
if(_timeout > 0){
|
||||
sslclient->handshake_timeout = _timeout;
|
||||
}
|
||||
int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, _pskIdent, _psKey);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::peek(){
|
||||
if(_peek >= 0){
|
||||
return _peek;
|
||||
}
|
||||
_peek = timedRead();
|
||||
return _peek;
|
||||
}
|
||||
|
||||
size_t WiFiClientSecureESP32::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::read()
|
||||
{
|
||||
uint8_t data = -1;
|
||||
int res = read(&data, 1);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t WiFiClientSecureESP32::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_connected) {
|
||||
return 0;
|
||||
}
|
||||
int res = send_ssl_data(sslclient, buf, size);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
res = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
int peeked = 0;
|
||||
int avail = available();
|
||||
if ((!buf && size) || avail <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if(!size){
|
||||
return 0;
|
||||
}
|
||||
if(_peek >= 0){
|
||||
buf[0] = _peek;
|
||||
_peek = -1;
|
||||
size--;
|
||||
avail--;
|
||||
if(!size || !avail){
|
||||
return 1;
|
||||
}
|
||||
buf++;
|
||||
peeked = 1;
|
||||
}
|
||||
|
||||
int res = get_ssl_receive(sslclient, buf, size);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
return peeked?peeked:res;
|
||||
}
|
||||
return res + peeked;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::available()
|
||||
{
|
||||
int peeked = (_peek >= 0);
|
||||
if (!_connected) {
|
||||
return peeked;
|
||||
}
|
||||
int res = data_to_read(sslclient);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
return peeked?peeked:res;
|
||||
}
|
||||
return res+peeked;
|
||||
}
|
||||
|
||||
uint8_t WiFiClientSecureESP32::connected()
|
||||
{
|
||||
uint8_t dummy = 0;
|
||||
read(&dummy, 0);
|
||||
|
||||
return _connected;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setCACert (const char *rootCA)
|
||||
{
|
||||
_CA_cert = rootCA;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setCertificate (const char *client_ca)
|
||||
{
|
||||
_cert = client_ca;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setPrivateKey (const char *private_key)
|
||||
{
|
||||
_private_key = private_key;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setPreSharedKey(const char *pskIdent, const char *psKey) {
|
||||
_pskIdent = pskIdent;
|
||||
_psKey = psKey;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::verify(const char* fp, const char* domain_name)
|
||||
{
|
||||
if (!sslclient)
|
||||
return false;
|
||||
|
||||
return verify_ssl_fingerprint(sslclient, fp, domain_name);
|
||||
}
|
||||
|
||||
char *WiFiClientSecureESP32::_streamLoad(Stream& stream, size_t size) {
|
||||
static char *dest = nullptr;
|
||||
if(dest) {
|
||||
free(dest);
|
||||
}
|
||||
dest = (char*)malloc(size);
|
||||
if (!dest) {
|
||||
return nullptr;
|
||||
}
|
||||
if (size != stream.readBytes(dest, size)) {
|
||||
free(dest);
|
||||
dest = nullptr;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::loadCACert(Stream& stream, size_t size) {
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
setCACert(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::loadCertificate(Stream& stream, size_t size) {
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
setCertificate(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WiFiClientSecureESP32::loadPrivateKey(Stream& stream, size_t size) {
|
||||
char *dest = _streamLoad(stream, size);
|
||||
bool ret = false;
|
||||
if (dest) {
|
||||
setPrivateKey(dest);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WiFiClientSecureESP32::lastError(char *buf, const size_t size)
|
||||
{
|
||||
if (!_lastError) {
|
||||
return 0;
|
||||
}
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(_lastError, error_buf, 100);
|
||||
snprintf(buf, size, "%s", error_buf);
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setHandshakeTimeout(unsigned long handshake_timeout)
|
||||
{
|
||||
sslclient->handshake_timeout = handshake_timeout * 1000;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setSTARTTLS(bool starttls)
|
||||
{
|
||||
sslclient->starttls = starttls;
|
||||
}
|
||||
|
||||
void WiFiClientSecureESP32::setDebugCB(DebugMsgCallback cb)
|
||||
{
|
||||
sslclient->_debugCallback = std::move(cb);
|
||||
}
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //WiFiClientSecureESP32_CPP
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
*Customized ssl_client.h to support STARTTLS protocol, version 1.0.3
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2019 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Provide SSL/TLS functions to ESP32 with Arduino IDE
|
||||
* by Evandro Copercini - 2017 - Apache 2.0 License
|
||||
*/
|
||||
|
||||
#ifndef SSL_CLIENT32_H
|
||||
#define SSL_CLIENT32_H
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#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 ESP32_SSL_CLIENT_STR_1[] PROGMEM = "ERROR: ";
|
||||
static const char ESP32_SSL_CLIENT_STR_2[] PROGMEM = "INFO: starting socket";
|
||||
static const char ESP32_SSL_CLIENT_STR_3[] PROGMEM = "ERROR: opening socket";
|
||||
static const char ESP32_SSL_CLIENT_STR_4[] PROGMEM = "ERROR: could not get ip from host";
|
||||
static const char ESP32_SSL_CLIENT_STR_5[] PROGMEM = "INFO: connecting to Server...";
|
||||
static const char ESP32_SSL_CLIENT_STR_6[] PROGMEM = "INFO: server connected";
|
||||
static const char ESP32_SSL_CLIENT_STR_7[] PROGMEM = "ERROR: connect to Server failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_8[] PROGMEM = "INFO: begin STARTTLS handshake";
|
||||
static const char ESP32_SSL_CLIENT_STR_9[] PROGMEM = "INFO: seeding the random number generator";
|
||||
static const char ESP32_SSL_CLIENT_STR_10[] PROGMEM = "INFO: setting up the SSL/TLS structure...";
|
||||
static const char ESP32_SSL_CLIENT_STR_11[] PROGMEM = "INFO: loading CA cert";
|
||||
static const char ESP32_SSL_CLIENT_STR_12[] PROGMEM = "INFO: setting up PSK";
|
||||
static const char ESP32_SSL_CLIENT_STR_13[] PROGMEM = "ERROR: pre-shared key not valid hex or too long";
|
||||
static const char ESP32_SSL_CLIENT_STR_14[] PROGMEM = "INFO: set mbedtls config";
|
||||
static const char ESP32_SSL_CLIENT_STR_15[] PROGMEM = "INFO: loading CRT cert";
|
||||
static const char ESP32_SSL_CLIENT_STR_16[] PROGMEM = "INFO: loading private key";
|
||||
static const char ESP32_SSL_CLIENT_STR_17[] PROGMEM = "INFO: setting hostname for TLS session...";
|
||||
static const char ESP32_SSL_CLIENT_STR_18[] PROGMEM = "INFO: performing the SSL/TLS handshake...";
|
||||
static const char ESP32_SSL_CLIENT_STR_19[] PROGMEM = "INFO: verifying peer X.509 certificate...";
|
||||
static const char ESP32_SSL_CLIENT_STR_20[] PROGMEM = "ERROR: failed to verify peer certificate!";
|
||||
static const char ESP32_SSL_CLIENT_STR_21[] PROGMEM = "INFO: certificate verified";
|
||||
static const char ESP32_SSL_CLIENT_STR_22[] PROGMEM = "INFO: cleaning SSL connection";
|
||||
static const char ESP32_SSL_CLIENT_STR_23[] PROGMEM = "ERROR: fingerprint too short";
|
||||
static const char ESP32_SSL_CLIENT_STR_24[] PROGMEM = "ERROR: invalid hex sequence";
|
||||
static const char ESP32_SSL_CLIENT_STR_25[] PROGMEM = "ERROR: could not fetch peer certificate";
|
||||
static const char ESP32_SSL_CLIENT_STR_26[] PROGMEM = "ERROR: fingerprint doesn't match";
|
||||
static const char ESP32_SSL_CLIENT_STR_27[] PROGMEM = "ERROR: waiting incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_28[] PROGMEM = "ERROR: reading incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_29[] PROGMEM = "EHLO DUDE\r\n";
|
||||
static const char ESP32_SSL_CLIENT_STR_30[] PROGMEM = "INFO: send SMTP command extended HELO";
|
||||
static const char ESP32_SSL_CLIENT_STR_31[] PROGMEM = "ERROR: send SMTP command failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_32[] PROGMEM = "ERROR: waiting incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_33[] PROGMEM = "ERROR: reading incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_34[] PROGMEM = "STARTTLS\r\n";
|
||||
static const char ESP32_SSL_CLIENT_STR_35[] PROGMEM = "INFO: send STARTTLS protocol command";
|
||||
static const char ESP32_SSL_CLIENT_STR_36[] PROGMEM = "ERROR: send STARTTLS protocol command failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_37[] PROGMEM = "ERROR: waiting incoming data failed!";
|
||||
static const char ESP32_SSL_CLIENT_STR_38[] PROGMEM = "ERROR: reading incoming data failed!";
|
||||
|
||||
typedef void (*DebugMsgCallback)(const char *msg);
|
||||
|
||||
typedef struct sslclient_context32 {
|
||||
int socket;
|
||||
bool starttls;
|
||||
mbedtls_ssl_context ssl_ctx;
|
||||
mbedtls_ssl_config ssl_conf;
|
||||
mbedtls_net_context server_fd;
|
||||
|
||||
mbedtls_ctr_drbg_context drbg_ctx;
|
||||
mbedtls_entropy_context entropy_ctx;
|
||||
|
||||
mbedtls_x509_crt ca_cert;
|
||||
mbedtls_x509_crt client_cert;
|
||||
mbedtls_pk_context client_key;
|
||||
DebugMsgCallback _debugCallback;
|
||||
|
||||
unsigned long handshake_timeout;
|
||||
} sslclient_context32;
|
||||
|
||||
|
||||
void ssl_init(sslclient_context32 *ssl_client);
|
||||
int start_ssl_client(sslclient_context32 *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(sslclient_context32 *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int data_to_read(sslclient_context32 *ssl_client);
|
||||
int send_ssl_data(sslclient_context32 *ssl_client, const uint8_t *data, uint16_t len);
|
||||
int get_ssl_receive(sslclient_context32 *ssl_client, uint8_t *data, int length);
|
||||
bool verify_ssl_fingerprint(sslclient_context32 *ssl_client, const char* fp, const char* domain_name);
|
||||
bool verify_ssl_dn(sslclient_context32 *ssl_client, const char* domain_name);
|
||||
int starttlsHandshake(sslclient_context32 *ssl_client, int port);
|
||||
void ESP32SSLClientDebugInfo(PGM_P info, sslclient_context32 *ssl_client);
|
||||
|
||||
#endif //ESP32
|
||||
|
||||
#endif //SSL_CLIENT32_H
|
|
@ -0,0 +1,325 @@
|
|||
#ifdef USE_ESP32MAIL
|
||||
|
||||
|
||||
#include <ESP_Mail_Client.h>
|
||||
|
||||
#ifndef SEND_MAIL32_MINRAM
|
||||
#define SEND_MAIL32_MINRAM 30*1024
|
||||
#endif
|
||||
#define xPSTR(a) a
|
||||
#define MAX_ATTCHMENTS 8
|
||||
char *attachments[MAX_ATTCHMENTS];
|
||||
uint8_t num_attachments;
|
||||
void script_send_email_body(void(*func)(char *));
|
||||
String html_content = "";
|
||||
SMTP_Message *email_mptr;
|
||||
|
||||
//#define DEBUG_EMAIL_PORT
|
||||
|
||||
uint16_t SendMail(char *buffer) {
|
||||
char *params,*oparams = 0;
|
||||
const char *mserv;
|
||||
uint16_t port;
|
||||
const char *user;
|
||||
const char *pstr;
|
||||
const char *passwd;
|
||||
const char *from;
|
||||
const char *to;
|
||||
const char *subject;
|
||||
const char *cmd;
|
||||
uint16_t status = 0;
|
||||
uint16_t blen;
|
||||
char *endcmd;
|
||||
SMTPSession smtp;
|
||||
ESP_Mail_Session session;
|
||||
SMTP_Message message;
|
||||
email_mptr = &message;
|
||||
|
||||
// return if not enough memory
|
||||
uint32_t mem = ESP.getFreeHeap();
|
||||
//AddLog(LOG_LEVEL_INFO, PSTR("heap: %d"),mem);
|
||||
if (mem < SEND_MAIL32_MINRAM) {
|
||||
// return 4;
|
||||
}
|
||||
|
||||
while (*buffer==' ') buffer++;
|
||||
|
||||
if (*buffer != '[') {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
buffer++;
|
||||
|
||||
endcmd = strchr(buffer, ']');
|
||||
if (!endcmd) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// copy params
|
||||
blen = (uint32_t)endcmd - (uint32_t)buffer;
|
||||
oparams = (char*)calloc(blen+2, 1);
|
||||
if (!oparams) return 4;
|
||||
params = oparams;
|
||||
strncpy(oparams, buffer, blen+2);
|
||||
oparams[blen] = 0;
|
||||
|
||||
cmd = endcmd + 1;
|
||||
|
||||
|
||||
for (uint32_t cnt = 0; cnt < MAX_ATTCHMENTS; cnt++) {
|
||||
attachments[cnt] = 0;
|
||||
}
|
||||
num_attachments = 0;
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("mailsize: %d"),blen);
|
||||
#endif
|
||||
|
||||
mserv = strtok(params, ":");
|
||||
if (!mserv) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// port
|
||||
pstr = strtok(NULL, ":");
|
||||
if (!pstr) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef EMAIL_PORT
|
||||
if (*pstr == '*') {
|
||||
port = EMAIL_PORT;
|
||||
} else {
|
||||
port = atoi(pstr);
|
||||
}
|
||||
#else
|
||||
port = atoi(pstr);
|
||||
#endif
|
||||
|
||||
user = strtok(NULL, ":");
|
||||
if (!user) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
passwd = strtok(NULL, ":");
|
||||
if (!passwd) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
from = strtok(NULL, ":");
|
||||
if (!from) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
to = strtok(NULL, ":");
|
||||
if (!to) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
subject = strtok(NULL, "]");
|
||||
if (!subject) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef EMAIL_USER
|
||||
if (*user == '*') {
|
||||
user = xPSTR(EMAIL_USER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EMAIL_PASSWORD
|
||||
if (*passwd == '*') {
|
||||
passwd = xPSTR(EMAIL_PASSWORD);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EMAIL_SERVER
|
||||
if (*mserv == '*') {
|
||||
mserv = xPSTR(EMAIL_SERVER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("%s - %d - %s - %s"), mserv, port, user, passwd);
|
||||
#endif
|
||||
|
||||
#ifdef EMAIL_FROM
|
||||
if (*from == '*') {
|
||||
from = xPSTR(EMAIL_FROM);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("%s - %s - %s - %s"), from, to, subject, cmd);
|
||||
#endif
|
||||
|
||||
|
||||
smtp.debug(true);
|
||||
//smtp.debug(false);
|
||||
|
||||
message.clearRecipients();
|
||||
message.clearCc();
|
||||
message.clearBcc();
|
||||
|
||||
//smtp.callback(smtpCallback);
|
||||
|
||||
session.server.host_name = mserv;
|
||||
session.server.port = port;
|
||||
session.login.email = user;
|
||||
session.login.password = passwd;
|
||||
session.login.user_domain = "googlemail.com";
|
||||
|
||||
|
||||
message.enable.chunking = true;
|
||||
char sname[32];
|
||||
strlcpy(sname, SettingsText(SET_FRIENDLYNAME1), sizeof(sname));
|
||||
message.sender.name = sname;
|
||||
message.sender.email = from;
|
||||
message.subject = subject;
|
||||
message.addRecipient("user1", to);
|
||||
message.html.charSet = "utf-8";
|
||||
message.text.charSet = "utf-8";
|
||||
message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
|
||||
//message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
|
||||
message.response.notify = esp_mail_smtp_notify_failure;
|
||||
message.html.charSet = "us-ascii";
|
||||
message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
|
||||
message.addHeader("Message-ID: <user1@gmail.com>");
|
||||
|
||||
#ifdef USE_SCRIPT
|
||||
if (*cmd == '*' && *(cmd + 1) == 0) {
|
||||
script_send_email_body(send_message_txt);
|
||||
} else {
|
||||
html_content += cmd;
|
||||
message.html.content = html_content.c_str();
|
||||
}
|
||||
#else
|
||||
html_content += cmd;
|
||||
message.html.content = html_content.c_str();
|
||||
#endif
|
||||
|
||||
/* Connect to server with the session config */
|
||||
delay(0);
|
||||
if (!smtp.connect(&session))
|
||||
goto exit;
|
||||
|
||||
/* Start sending the Email and close the session */
|
||||
delay(0);
|
||||
|
||||
if (!MailClient.sendMail(&smtp, &message, true)) {
|
||||
Serial.println("Error sending Email, " + smtp.errorReason());
|
||||
}
|
||||
|
||||
exit:
|
||||
for (uint32_t cnt = 0; cnt < MAX_ATTCHMENTS; cnt++) {
|
||||
if (attachments[cnt]) {
|
||||
free(attachments[cnt]);
|
||||
attachments[cnt] = 0;
|
||||
}
|
||||
}
|
||||
html_content = "";
|
||||
if (oparams) free(oparams);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void send_message_txt(char *txt) {
|
||||
if (*txt == '@') {
|
||||
txt++;
|
||||
attach_File(txt);
|
||||
} else if (*txt == '&') {
|
||||
txt++;
|
||||
attach_Array(txt);
|
||||
} else if (*txt == '$') {
|
||||
txt++;
|
||||
#if defined(ESP32) && defined(USE_WEBCAM)
|
||||
if (num_attachments < MAX_ATTCHMENTS) {
|
||||
attachments[num_attachments] = (char*)malloc(32);
|
||||
uint32_t cnt;
|
||||
uint8_t *buff;
|
||||
uint32_t len, picmax;
|
||||
picmax = WcGetPicstore(-1, 0);
|
||||
cnt = *txt&7;
|
||||
if (cnt < 1 || cnt > picmax) cnt = 1;
|
||||
len = WcGetPicstore(cnt - 1, &buff);
|
||||
if (len) {
|
||||
sprintf(attachments[num_attachments], "img_%1d.jpg", cnt);
|
||||
attach_Data(attachments[num_attachments], buff, len);
|
||||
}
|
||||
num_attachments++;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
html_content += txt;
|
||||
email_mptr->html.content = html_content.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
void attach_File(char *path) {
|
||||
SMTP_Attachment att;
|
||||
if (num_attachments < MAX_ATTCHMENTS) {
|
||||
attachments[num_attachments] = (char*)malloc(32);
|
||||
strcpy(attachments[num_attachments], path);
|
||||
|
||||
char *cp = attachments[num_attachments];
|
||||
att.file.path = cp;
|
||||
if (*cp == '/') {
|
||||
cp++;
|
||||
}
|
||||
att.descr.filename = cp;
|
||||
att.descr.mime = "application/octet-stream"; //binary data
|
||||
att.file.storage_type = esp_mail_file_storage_type_univ;
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
email_mptr->addAttachment(att);
|
||||
email_mptr->resetAttachItem(att);
|
||||
num_attachments++;
|
||||
}
|
||||
}
|
||||
|
||||
float *get_array_by_name(char *name, uint16_t *alen);
|
||||
void flt2char(float num, char *nbuff);
|
||||
|
||||
void attach_Array(char *aname) {
|
||||
float *array = 0;
|
||||
uint16_t alen;
|
||||
String ttstr = "";
|
||||
array = get_array_by_name(aname, &alen);
|
||||
if (array && alen) {
|
||||
float *fp = array;
|
||||
for (uint32_t cnt = 0; cnt < alen; cnt++) {
|
||||
// export array as tab gelimited text
|
||||
char nbuff[16];
|
||||
flt2char(*fp++, nbuff);
|
||||
if (cnt < (alen - 1)) {
|
||||
strcat(nbuff, "\t");
|
||||
} else {
|
||||
strcat(nbuff, "\n");
|
||||
}
|
||||
ttstr += nbuff;
|
||||
}
|
||||
|
||||
if (num_attachments < MAX_ATTCHMENTS) {
|
||||
attachments[num_attachments] = (char*)malloc(ttstr.length() + 1 + 32);
|
||||
strcpy(attachments[num_attachments] + 32, ttstr.c_str());
|
||||
sprintf(attachments[num_attachments], "%s.txt", aname);
|
||||
attach_Data(attachments[num_attachments], (uint8_t*)attachments[num_attachments]+32, ttstr.length());
|
||||
num_attachments++;
|
||||
}
|
||||
} else {
|
||||
//g_client->print(F("\r\n\r\narray not found!\r\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void attach_Data(char *name, uint8_t *buff, uint32_t len) {
|
||||
SMTP_Attachment att;
|
||||
att.descr.filename = name;
|
||||
att.descr.mime = "application/octet-stream";
|
||||
att.blob.data = buff;
|
||||
att.blob.size = len;
|
||||
att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
|
||||
email_mptr->addAttachment(att);
|
||||
email_mptr->resetAttachItem(att);
|
||||
}
|
||||
|
||||
#endif // USE_ESP32MAIL
|
|
@ -3,17 +3,8 @@
|
|||
|
||||
//#define DEBUG_EMAIL_PORT
|
||||
|
||||
//#include <WiFiClient.h>
|
||||
//#include <WiFiClientSecure.h>
|
||||
#include <base64.h>
|
||||
//#include <core_version.h>
|
||||
|
||||
#ifdef ESP8266
|
||||
#include "WiFiClientSecureLightBearSSL.h"
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
#include <WiFiClientSecure.h>
|
||||
#endif // ESP32
|
||||
|
||||
class SendEmail
|
||||
{
|
||||
|
@ -25,13 +16,8 @@ class SendEmail
|
|||
const int timeout;
|
||||
const bool ssl;
|
||||
const int auth_used;
|
||||
#ifdef ESP8266
|
||||
// use bear ssl
|
||||
BearSSL::WiFiClientSecure_light *client;
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
WiFiClient *client;
|
||||
#endif // ESP32
|
||||
|
||||
String readClient();
|
||||
void a3_to_a4(unsigned char * a4, unsigned char * a3);
|
|
@ -1,8 +1,6 @@
|
|||
#ifdef USE_SENDMAIL
|
||||
|
||||
#ifndef USE_ESP32MAIL
|
||||
|
||||
#include "sendemail.h"
|
||||
#include "sendemail_ESP8266.h"
|
||||
|
||||
// enable serial debugging
|
||||
//#define DEBUG_EMAIL_PORT
|
||||
|
@ -179,19 +177,10 @@ exit:
|
|||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ESP8266
|
||||
WiFiClient *g_client;
|
||||
SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) :
|
||||
host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) {
|
||||
}
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
WiFiClient *g_client;
|
||||
SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) :
|
||||
host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new WiFiClientSecure()) {
|
||||
}
|
||||
#endif // ESP32
|
||||
|
||||
String SendEmail::readClient() {
|
||||
delay(0);
|
||||
|
@ -385,11 +374,14 @@ exit:
|
|||
return status;
|
||||
}
|
||||
|
||||
#ifdef USE_SCRIPT
|
||||
void xsend_message_txt(char *msg) {
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("%s"),msg);
|
||||
#endif
|
||||
#if (defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT)) || defined(USE_UFILESYS)
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
if (*msg=='@') {
|
||||
msg++;
|
||||
attach_File(msg);
|
||||
|
@ -415,43 +407,6 @@ void xsend_message_txt(char *msg) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#if (defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT)) || defined(USE_UFILESYS)
|
||||
#ifdef ESP8266
|
||||
#include <LittleFS.h>
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
#include <LITTLEFS.h>
|
||||
#endif // ESP32
|
||||
extern FS *ufsp;
|
||||
|
||||
void attach_File(char *path) {
|
||||
g_client->print(F("--frontier\r\n"));
|
||||
g_client->print(F("Content-Type: text/plain\r\n"));
|
||||
char buff[64];
|
||||
char *cp = path;
|
||||
while (*cp=='/') cp++;
|
||||
File file = ufsp->open(path, "r");
|
||||
if (file) {
|
||||
sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n"), cp);
|
||||
g_client->write(buff);
|
||||
uint16_t flen = file.size();
|
||||
uint8_t fbuff[64];
|
||||
uint16_t blen = sizeof(fbuff);
|
||||
while (flen>0) {
|
||||
file.read(fbuff, blen);
|
||||
flen -= blen;
|
||||
g_client->write(fbuff, blen);
|
||||
if (flen<blen) blen = flen;
|
||||
}
|
||||
file.close();
|
||||
} else {
|
||||
g_client->print(F("\r\n\r\nfile not found!\r\n"));
|
||||
}
|
||||
g_client->print(F("\r\n--frontier\r\n"));
|
||||
}
|
||||
|
||||
#endif // defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT)
|
||||
|
||||
float *get_array_by_name(char *name, uint16_t *alen);
|
||||
void flt2char(float num, char *nbuff);
|
||||
|
||||
|
@ -490,353 +445,41 @@ void attach_Array(char *aname) {
|
|||
}
|
||||
g_client->print(F("\r\n--frontier\r\n"));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
/*
|
||||
* Created by K. Suwatchai (Mobizt)
|
||||
*
|
||||
* Email: k_suwatchai@hotmail.com
|
||||
*
|
||||
* Github: https://github.com/mobizt
|
||||
*
|
||||
* Copyright (c) 2019 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
|
||||
|
||||
//To receive Email for Gmail, IMAP option should be enabled. https://support.google.com/mail/answer/7126229?hl=en
|
||||
|
||||
#include "ESP32_MailClient.h"
|
||||
#include "SD.h"
|
||||
|
||||
//For demo only
|
||||
//#include "image.h"
|
||||
|
||||
#ifndef SEND_MAIL32_MINRAM
|
||||
#define SEND_MAIL32_MINRAM 30*1024
|
||||
#endif
|
||||
|
||||
void script_send_email_body(void(*func)(char *));
|
||||
|
||||
#define xPSTR(a) a
|
||||
//The Email Sending data object contains config and data to send
|
||||
SMTPData smtpData;
|
||||
#define MAX_ATTCHMENTS 8
|
||||
char *attachments[MAX_ATTCHMENTS];
|
||||
uint8_t num_attachments;
|
||||
#ifdef USE_UFILESYS
|
||||
|
||||
//Callback function to get the Email sending status
|
||||
//void sendCallback(SendStatus info);
|
||||
//#define DEBUG_EMAIL_PORT
|
||||
#include <LittleFS.h>
|
||||
extern FS *ufsp;
|
||||
|
||||
uint16_t SendMail(char *buffer) {
|
||||
char *params,*oparams;
|
||||
const char *mserv;
|
||||
uint16_t port;
|
||||
const char *user;
|
||||
const char *pstr;
|
||||
const char *passwd;
|
||||
const char *from;
|
||||
const char *to;
|
||||
const char *subject;
|
||||
const char *cmd;
|
||||
uint16_t status=1;
|
||||
uint16_t blen;
|
||||
char *endcmd;
|
||||
|
||||
// return if not enough memory
|
||||
uint32_t mem=ESP.getFreeHeap();
|
||||
//AddLog(LOG_LEVEL_INFO, PSTR("heap: %d"),mem);
|
||||
if (mem<SEND_MAIL32_MINRAM) {
|
||||
return 4;
|
||||
void attach_File(char *path) {
|
||||
g_client->print(F("--frontier\r\n"));
|
||||
g_client->print(F("Content-Type: text/plain\r\n"));
|
||||
char buff[64];
|
||||
char *cp = path;
|
||||
while (*cp=='/') cp++;
|
||||
File file = ufsp->open(path, "r");
|
||||
if (file) {
|
||||
sprintf_P(buff,PSTR("Content-Disposition: attachment; filename=\"%s\"\r\n\r\n"), cp);
|
||||
g_client->write(buff);
|
||||
uint16_t flen = file.size();
|
||||
uint8_t fbuff[64];
|
||||
uint16_t blen = sizeof(fbuff);
|
||||
while (flen>0) {
|
||||
file.read(fbuff, blen);
|
||||
flen -= blen;
|
||||
g_client->write(fbuff, blen);
|
||||
if (flen<blen) blen = flen;
|
||||
}
|
||||
|
||||
while (*buffer==' ') buffer++;
|
||||
|
||||
if (*buffer!='[') {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
buffer++;
|
||||
|
||||
endcmd=strchr(buffer,']');
|
||||
if (!endcmd) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// copy params
|
||||
blen=(uint32_t)endcmd-(uint32_t)buffer;
|
||||
oparams=(char*)calloc(blen+2,1);
|
||||
if (!oparams) return 4;
|
||||
params=oparams;
|
||||
strncpy(oparams,buffer,blen+2);
|
||||
oparams[blen]=0;
|
||||
|
||||
cmd=endcmd+1;
|
||||
|
||||
|
||||
for (uint32_t cnt=0; cnt<MAX_ATTCHMENTS; cnt++) {
|
||||
attachments[cnt]=0;
|
||||
}
|
||||
num_attachments=0;
|
||||
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("mailsize: %d"),blen);
|
||||
#endif
|
||||
|
||||
mserv=strtok(params,":");
|
||||
if (!mserv) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// port
|
||||
pstr=strtok(NULL,":");
|
||||
if (!pstr) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef EMAIL_PORT
|
||||
if (*pstr=='*') {
|
||||
port=EMAIL_PORT;
|
||||
file.close();
|
||||
} else {
|
||||
port=atoi(pstr);
|
||||
g_client->print(F("\r\n\r\nfile not found!\r\n"));
|
||||
}
|
||||
#else
|
||||
port=atoi(pstr);
|
||||
#endif
|
||||
|
||||
user=strtok(NULL,":");
|
||||
if (!user) {
|
||||
goto exit;
|
||||
g_client->print(F("\r\n--frontier\r\n"));
|
||||
}
|
||||
|
||||
passwd=strtok(NULL,":");
|
||||
if (!passwd) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
from=strtok(NULL,":");
|
||||
if (!from) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
to=strtok(NULL,":");
|
||||
if (!to) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
subject=strtok(NULL,"]");
|
||||
if (!subject) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
#ifdef EMAIL_USER
|
||||
if (*user=='*') {
|
||||
user=xPSTR(EMAIL_USER);
|
||||
}
|
||||
#endif
|
||||
#ifdef EMAIL_PASSWORD
|
||||
if (*passwd=='*') {
|
||||
passwd=xPSTR(EMAIL_PASSWORD);
|
||||
}
|
||||
#endif
|
||||
#ifdef EMAIL_SERVER
|
||||
if (*mserv=='*') {
|
||||
mserv=xPSTR(EMAIL_SERVER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("%s - %d - %s - %s"),mserv,port,user,passwd);
|
||||
#endif
|
||||
|
||||
#ifdef EMAIL_FROM
|
||||
if (*from=='*') {
|
||||
from=xPSTR(EMAIL_FROM);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EMAIL_PORT
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("%s - %s - %s - %s"),from,to,subject,cmd);
|
||||
#endif
|
||||
|
||||
|
||||
smtpData.setDebug(true);
|
||||
|
||||
//Set the Email host, port, account and password
|
||||
smtpData.setLogin(mserv, port, user, passwd);
|
||||
|
||||
//For library version 1.2.0 and later which STARTTLS protocol was supported,the STARTTLS will be
|
||||
//enabled automatically when port 587 was used, or enable it manually using setSTARTTLS function.
|
||||
//smtpData.setSTARTTLS(true);
|
||||
|
||||
//Set the sender name and Email
|
||||
smtpData.setSender("ESP32",from);
|
||||
|
||||
//Set Email priority or importance High, Normal, Low or 1 to 5 (1 is highest)
|
||||
smtpData.setPriority("High");
|
||||
|
||||
//Set the subject
|
||||
smtpData.setSubject(subject);
|
||||
|
||||
#ifdef USE_SCRIPT
|
||||
if (*cmd=='*' && *(cmd+1)==0) {
|
||||
smtpData.clrMessage(true);
|
||||
script_send_email_body(send_message_txt);
|
||||
} else {
|
||||
smtpData.setMessage(cmd, true);
|
||||
}
|
||||
#else
|
||||
//Set the message - normal text or html format
|
||||
smtpData.setMessage(cmd, true);
|
||||
#endif
|
||||
|
||||
|
||||
//Add recipients, can add more than one recipient
|
||||
smtpData.addRecipient(to);
|
||||
|
||||
//Add attachments, can add the file or binary data from flash memory, file in SD card
|
||||
//Data from internal memory
|
||||
//smtpData.addAttachData("firebase_logo.png", "image/png", (uint8_t *)dummyImageData, sizeof dummyImageData);
|
||||
|
||||
//Add attach files from SD card
|
||||
//Comment these two lines, if no SD card connected
|
||||
//Two files that previousely created.
|
||||
//smtpData.addAttachFile("/binary_file.dat");
|
||||
//smtpData.addAttachFile("/text_file.txt");
|
||||
|
||||
|
||||
//Add some custom header to message
|
||||
//See https://tools.ietf.org/html/rfc822
|
||||
//These header fields can be read from raw or source of message when it received)
|
||||
//smtpData.addCustomMessageHeader("Date: Sat, 10 Aug 2019 21:39:56 -0700 (PDT)");
|
||||
//Be careful when set Message-ID, it should be unique, otherwise message will not store
|
||||
//smtpData.addCustomMessageHeader("Message-ID: <abcde.fghij@gmail.com>");
|
||||
|
||||
//Set the storage types to read the attach files (SD is default)
|
||||
//smtpData.setFileStorageType(MailClientStorageType::SPIFFS);
|
||||
|
||||
|
||||
/*
|
||||
#ifdef USE_SCRIPT_FATFS
|
||||
#if USE_SCRIPT_FATFS<0
|
||||
smtpData.setFileStorageType(MailClientStorageType::FFat);
|
||||
#else
|
||||
smtpData.setFileStorageType(MailClientStorageType::SD);
|
||||
#endif
|
||||
#endif
|
||||
*/
|
||||
|
||||
smtpData.setFileStorageType(MailClientStorageType::Univ);
|
||||
|
||||
|
||||
//smtpData.setSendCallback(sendCallback);
|
||||
|
||||
//Start sending Email, can be set callback function to track the status
|
||||
if (!MailClient.sendMail(smtpData)) {
|
||||
//Serial.println("Error sending Email, " + MailClient.smtpErrorReason());
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("Error sending Email, %s"), MailClient.smtpErrorReason().c_str());
|
||||
|
||||
} else {
|
||||
status=0;
|
||||
}
|
||||
//Clear all data from Email object to free memory
|
||||
smtpData.empty();
|
||||
for (uint32_t cnt=0; cnt<MAX_ATTCHMENTS; cnt++) {
|
||||
if (attachments[cnt]) {
|
||||
free(attachments[cnt]);
|
||||
attachments[cnt]=0;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
if (oparams) free(oparams);
|
||||
return status;
|
||||
}
|
||||
|
||||
float *get_array_by_name(char *name, uint16_t *alen);
|
||||
void flt2char(float num, char *nbuff);
|
||||
|
||||
void attach_Array(char *aname) {
|
||||
float *array = 0;
|
||||
uint16_t alen;
|
||||
String ttstr = "";
|
||||
array = get_array_by_name(aname, &alen);
|
||||
if (array && alen) {
|
||||
float *fp=array;
|
||||
for (uint32_t cnt = 0; cnt<alen; cnt++) {
|
||||
// export array as tab gelimited text
|
||||
char nbuff[16];
|
||||
flt2char(*fp++, nbuff);
|
||||
if (cnt < (alen - 1)) {
|
||||
strcat(nbuff,"\t");
|
||||
} else {
|
||||
strcat(nbuff,"\n");
|
||||
}
|
||||
ttstr += nbuff;
|
||||
}
|
||||
|
||||
if (num_attachments<MAX_ATTCHMENTS) {
|
||||
attachments[num_attachments] = (char*)malloc(ttstr.length()+1);
|
||||
strcpy(attachments[num_attachments],ttstr.c_str());
|
||||
char name[32];
|
||||
sprintf(name,"%s.txt",aname);
|
||||
smtpData.addAttachData(name, "text/plain",(uint8_t*)attachments[num_attachments],ttstr.length());
|
||||
num_attachments++;
|
||||
}
|
||||
} else {
|
||||
//g_client->print(F("\r\n\r\narray not found!\r\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void send_message_txt(char *txt) {
|
||||
if (*txt=='@') {
|
||||
txt++;
|
||||
smtpData.addAttachFile(txt);
|
||||
} else if (*txt=='&') {
|
||||
txt++;
|
||||
attach_Array(txt);
|
||||
} else if (*txt=='$') {
|
||||
txt++;
|
||||
#if defined(ESP32) && defined(USE_WEBCAM)
|
||||
uint32_t cnt;
|
||||
uint8_t *buff;
|
||||
uint32_t len,picmax;
|
||||
picmax=WcGetPicstore(-1,0);
|
||||
cnt=*txt&7;
|
||||
if (cnt<1 || cnt>picmax) cnt=1;
|
||||
len=WcGetPicstore(cnt-1,&buff);
|
||||
if (len) {
|
||||
char str[12];
|
||||
sprintf(str,"img_%1d.jpg",cnt+1);
|
||||
smtpData.addAttachData(str, "image/jpg",buff,len);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
smtpData.addMessage(txt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
//Callback function to get the Email sending status
|
||||
void sendCallback(SendStatus msg)
|
||||
{
|
||||
//Print the current status
|
||||
Serial.println(msg.info());
|
||||
|
||||
//Do something when complete
|
||||
if (msg.success())
|
||||
{
|
||||
Serial.println("----------------");
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
|
||||
#endif // USE_SENDMAIL
|
Loading…
Reference in New Issue