Send email with attachments (EMailSender v2.x library): esp32 and esp8266 – Part 2

Spread the love
  •  
  •  
  •  
  • 1
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    1
    Share

Here I’d like to explain the version 2 of the EMailSender library, a big evolution respect to version 1, with support for Arduino with w5100, w5200 and w5500 ethernet shield and enc28J60 clone devices, and support for esp32 and esp8266.
Now you can add attachments also, loaded from storage device like SD or SPIFFS.

You can refer at the version 1 on this library Send email with esp8266 and Arduino

Introduction

A simple method to notify a problem is to use email, so I created a library to do It.

Send email with attachments esp8266 esp32 library
Send email with attachments esp8266 esp32 library

This library use the SMTP:

The Simple Mail Transfer Protocol (SMTP) is a communication protocol for electronic mail transmission. As an Internet standard, SMTP was first defined in 1982 by RFC 821, and updated in 2008 by RFC 5321 to Extended SMTP additions, which is the protocol variety in widespread use today. Mail servers and other message transfer agents use SMTP to send and receive mail messages. Proprietary systems such as Microsoft Exchange and IBM Notes and webmail systems such as Outlook.com, Gmail and Yahoo! Mail may use non-standard protocols internally, but all use SMTP when sending to or receiving email from outside their own systems. SMTP servers commonly use the Transmission Control Protocol on port number 25. (cit WiKi)

For the examples I use a gmail dedicated account, I create a new one account because you must reduce security to use It with an external program.

Library

You can find my library here.

To download.

Click the DOWNLOADS button in the top right corner, rename the uncompressed folder EMailSender.

Check that the EMailSender folder contains EMailSender.cpp and EMailSender.h.

Place the EMailSender library folder your /libraries/ folder.

You may need to create the libraries subfolder if its your first library.

Restart the IDE.

Usage

Constructor: Default value is quite simple and use GMail as smtp server.

EMailSender emailSend("smtp.account@gmail.com", "password");

If you want use onother provider you can use more complex (but simple) contructor

EMailSender(const char* email_login, const char* email_password);

EMailSender(const char* email_login, const char* email_password, const char* email_from);

EMailSender(const char* email_login, const char* email_password, const char* email_from, const char* smtp_server, uint16_t smtp_port);
  • email_login: login to account smtp
  • email_password: password account smtp
  • email_from: email of sender
  • smtp_server: server SMTP
  • smtp_port: SMTP port

Now respect to the v1.x library you can note that isSecure flag no more exist

  • isSecure = false: if false BearSSL allows for ‘insecure’ TLS connections (only for >2.4.2 esp8266 core)

but you can manage It with

void setIsSecure(bool isSecure = false);

Other parameter that you can set post constructor is

void setUseAuth(bool useAuth = true);
void setPublicIpDescriptor(const char *publicIpDescriptor = "mischianti");

The first permit to exclude the authentication handshake, the second change the HELO message identification.

You must connect to WIFI :P.

Basic example with GMail smtp

You must refert to Part 2 to setup your GMail account and to check all parameter.

Create a message with the structure EMailMessage

    EMailSender::EMailMessage message;
    message.subject = "Subject";
    message.message = "Hi, How are you<br>Fine.";

Send message:

    EMailSender::Response resp = emailSend.send("account_to_send@gmail.com", message);

Then check the response:

    Serial.println("Sending status: ");
    Serial.println(resp.code);
    Serial.println(resp.desc);
    Serial.println(resp.status);

Example output:

Connection: ESTABLISHED
Got IP address: 192.168.1.104
Sending status: 
1
0
Message sent!

esp8266

Normally I use WeMos D1 mini for my test

You can find WeMos D1 mini here AliExpress

To send email with esp8266 with builtin WiFi is quite simple, but you must pay attention of you core version, because if you have a core versione lesser or equal to 2.4.2 you must select a specified #define.

To select your device you must go on EMailSenderKey.h library file and replace this line

#define DEFAULT_EMAIL_NETWORK_TYPE_ESP8266 	NETWORK_ESP8266

in

#define DEFAULT_EMAIL_NETWORK_TYPE_ESP8266 	NETWORK_ESP8266_242

Backward compatibility with library v1.x

To grant backward compatibility with library version 1.x you can also uncomment the same define of old library.

So if you have a esp8266 core 2.4.2 or less you must uncomment this line

// Uncomment if you use esp8266 core <= 2.4.2
#define ARDUINO_ESP8266_RELEASE_2_4_2

Send simple email

So here an example of simple EMail send with GMail provider (configure GMail like described at the end of article).

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * Simple esp8266 Gmail send example
 *
 * https://www.mischianti.org
 *
 */

#include "Arduino.h"
#include <EMailSender.h>
#include <ESP8266WiFi.h>

const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";

uint8_t connection_state = 0;
uint16_t reconnect_interval = 10000;

EMailSender emailSend("smtp.account@gmail.com", "password");

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
    static uint16_t attempt = 0;
    Serial.print("Connecting to ");
    if(nSSID) {
        WiFi.begin(nSSID, nPassword);
        Serial.println(nSSID);
    }

    uint8_t i = 0;
    while(WiFi.status()!= WL_CONNECTED &amp;&amp; i++ < 50)
    {
        delay(200);
        Serial.print(".");
    }
    ++attempt;
    Serial.println("");
    if(i == 51) {
        Serial.print("Connection: TIMEOUT on attempt: ");
        Serial.println(attempt);
        if(attempt % 2 == 0)
            Serial.println("Check if access point available or SSID and Password\r\n");
        return false;
    }
    Serial.println("Connection: ESTABLISHED");
    Serial.print("Got IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}

void Awaits()
{
    uint32_t ts = millis();
    while(!connection_state)
    {
        delay(50);
        if(millis() > (ts + reconnect_interval) &amp;&amp; !connection_state){
            connection_state = WiFiConnect();
            ts = millis();
        }
    }
}

void setup()
{
    Serial.begin(115200);

    connection_state = WiFiConnect(ssid, password);
    if(!connection_state)  // if not connected to WIFI
        Awaits();          // constantly trying to connect

    EMailSender::EMailMessage message;
    message.subject = "Soggetto";
    message.message = "Ciao come stai<br>io bene.<br>www.mischianti.org";

    EMailSender::Response resp = emailSend.send("account_to_send@gmail.com", message);

    Serial.println("Sending status: ");

    Serial.println(resp.status);
    Serial.println(resp.code);
    Serial.println(resp.desc);
}

void loop()
{

}

Send email with attachments

Send email with attachments Arduino esp8266 esp32 test with image and txt
Send email with attachments Arduino esp8266 esp32 test with image and txt

To send attachments you must select a storage device, to simplify the management we are going to use SPIFFS integrated filesystem, refer to this article on how to put data on SPIFFS “WeMos D1 mini (esp8266), integrated SPIFFS Filesystem“.

The core of the code is the generation of structure to pass the information to load and stream the files.

    EMailSender::FileDescriptior fileDescriptor[2];
    fileDescriptor[1].filename = F("test.txt");
    fileDescriptor[1].url = F("/test.txt");
    fileDescriptor[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    fileDescriptor[0].filename = F("logo.jpg");
    fileDescriptor[0].url = F("/logo.jpg");
    fileDescriptor[0].mime = "image/jpg";
    fileDescriptor[0].encode64 = true;
    fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    EMailSender::Attachments attachs = {2, fileDescriptor};

    EMailSender::Response resp = emailSend.send("<receipe@gmail.com>", message, attachs);

The fields of EMailSender::FileDescriptior are quite comprehensive, but pay attention to encode64 that specify if you want encode all the content, this is usefully if there are some special character non supported.
For image if you don’t specify the encode64 probably they arrive with artefact.

But pay attention, the encoding af big file request a bit of time.

The field mime that specify the mime type of the file you want attach. Here some examples of existing mime type.

Than you must specify the storageType, in genera we only support SD and SPIFFS, for Arduino only SD.

The filename and url the filename is the name that appear to the receiver, the url is where is the file located in the FS selected.

Than in the EMailSender::Attachments you must specify the number of attachments and set the array of EMailSender::FileDescriptior.

The resulting code is this

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * esp8266 Gmail send example with 2 attach loaded in SPIFFS
 *
 * The base64 encoding of the image is slow, so be patient
 *
 * https://www.mischianti.org
 *
 */

#include "Arduino.h"
#include <EMailSender.h>
#include <ESP8266WiFi.h>

uint8_t connection_state = 0;
uint16_t reconnect_interval = 10000;

const char* ssid = "<YOUR_SSID>";
const char* password = "<YOUR_PASSWD>";

EMailSender emailSend("<smtp_account@gmail.com>", "<PASSWORD>");

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
    static uint16_t attempt = 0;
    Serial.print("Connecting to ");
    if(nSSID) {
        WiFi.begin(nSSID, nPassword);
        Serial.println(nSSID);
    }

    uint8_t i = 0;
    while(WiFi.status()!= WL_CONNECTED &amp;&amp; i++ < 50)
    {
        delay(200);
        Serial.print(".");
    }
    ++attempt;
    Serial.println("");
    if(i == 51) {
        Serial.print("Connection: TIMEOUT on attempt: ");
        Serial.println(attempt);
        if(attempt % 2 == 0)
            Serial.println("Check if access point available or SSID and Password\r\n");
        return false;
    }
    Serial.println("Connection: ESTABLISHED");
    Serial.print("Got IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}

void Awaits()
{
    uint32_t ts = millis();
    while(!connection_state)
    {
        delay(50);
        if(millis() > (ts + reconnect_interval) &amp;&amp; !connection_state){
            connection_state = WiFiConnect();
            ts = millis();
        }
    }
}

void setup()
{
    Serial.begin(115200);

    if(!SPIFFS.begin()){
          Serial.println("An Error has occurred while mounting SPIFFS");
          return;
    }

    Serial.println("ReadDir");
    Dir dir = SPIFFS.openDir("/");
    while (dir.next()) {
        Serial.print(dir.fileName());
        if(dir.fileSize()) {
            File f = dir.openFile("r");
            Serial.println(f.size());
        }
    }

    connection_state = WiFiConnect(ssid, password);
    if(!connection_state)  // if not connected to WIFI
        Awaits();          // constantly trying to connect

    EMailSender::EMailMessage message;
    message.subject = "Soggetto";
    message.message = "Ciao come stai<br>io bene.<br>www.mischianti.org";

    EMailSender::FileDescriptior fileDescriptor[2];
    fileDescriptor[1].filename = F("test.txt");
    fileDescriptor[1].url = F("/test.txt");
    fileDescriptor[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    fileDescriptor[0].filename = F("logo.jpg");
    fileDescriptor[0].url = F("/logo.jpg");
    fileDescriptor[0].mime = "image/jpg";
    fileDescriptor[0].encode64 = true;
    fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    EMailSender::Attachments attachs = {2, fileDescriptor};

    EMailSender::Response resp = emailSend.send("<receipe@gmail.com>", message, attachs);

    Serial.println("Sending status: ");

    Serial.println(resp.status);
    Serial.println(resp.code);
    Serial.println(resp.desc);
}

void loop()
{

}

ESP32

You can find some model of esp32 I use for my test AliExpress ESP32 Dev Kit v1 - AliExpress selectable - AliExpress TTGO T-Display 1.14 ESP32 - AliExpress NodeMCU V3 V2 ESP8266 Lolin32
Send email with attachments Arduino esp8266 esp32 test with image and txt
Send email with attachments Arduino esp8266 esp32 test with image and txt

ESP32 is very similar to esp8266, and SD and SPIFFS without FS_NO_GLOBALS work correctly because use the same FS.h File structure.

So we can now repeat the consideration of esp8266 implementation.

Send simple mail

So here an example of simple EMail send with GMail provider (configure GMail like described at the end of article).

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * Simple esp32 Gmail send example
 *
 * https://www.mischianti.org
 *
 */

#include "Arduino.h"
#include <EMailSender.h>
#include <WiFi.h>

const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";

uint8_t connection_state = 0;
uint16_t reconnect_interval = 10000;

EMailSender emailSend("account_login@gmail.com", "<YOUR-GMAIL-PASSWD>");

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
    static uint16_t attempt = 0;
    Serial.print("Connecting to ");
    if(nSSID) {
        WiFi.begin(nSSID, nPassword);
        Serial.println(nSSID);
    }

    uint8_t i = 0;
    while(WiFi.status()!= WL_CONNECTED &amp;&amp; i++ < 50)
    {
        delay(200);
        Serial.print(".");
    }
    ++attempt;
    Serial.println("");
    if(i == 51) {
        Serial.print("Connection: TIMEOUT on attempt: ");
        Serial.println(attempt);
        if(attempt % 2 == 0)
            Serial.println("Check if access point available or SSID and Password\r\n");
        return false;
    }
    Serial.println("Connection: ESTABLISHED");
    Serial.print("Got IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}

void Awaits()
{
    uint32_t ts = millis();
    while(!connection_state)
    {
        delay(50);
        if(millis() > (ts + reconnect_interval) &amp;&amp; !connection_state){
            connection_state = WiFiConnect();
            ts = millis();
        }
    }
}

void setup()
{
    Serial.begin(115200);

    connection_state = WiFiConnect(ssid, password);
    if(!connection_state)  // if not connected to WIFI
        Awaits();          // constantly trying to connect

    EMailSender::EMailMessage message;
    message.subject = "Soggetto";
    message.message = "Ciao come stai<br>io bene.<br>www.mischianti.org";

    EMailSender::Response resp = emailSend.send("receive_email@gmail.com", message);

    Serial.println("Sending status: ");

    Serial.println(resp.status);
    Serial.println(resp.code);
    Serial.println(resp.desc);
}

void loop()
{

}

Send email with attachments

To send attachments you must select a storage device, to simplify the management we are going to use SPIFFS integrated filesystem, refer to this article on how to put data on SPIFFS “ESP32: integrated SPIFFS FileSystem“.

The core of the code is the generation of structure to pass the information to load and stream the files.

    EMailSender::FileDescriptior fileDescriptor[2];
    fileDescriptor[1].filename = F("test.txt");
    fileDescriptor[1].url = F("/test.txt");
    fileDescriptor[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    fileDescriptor[0].filename = F("logo.jpg");
    fileDescriptor[0].url = F("/logo.jpg");
    fileDescriptor[0].mime = "image/jpg";
    fileDescriptor[0].encode64 = true;
    fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    EMailSender::Attachments attachs = {2, fileDescriptor};

    EMailSender::Response resp = emailSend.send("<receipe@gmail.com>", message, attachs);

The field of EMailSender::FileDescriptior is quite comprehensive, but pay attention to encode64 that specify if you want encode all the content, this is usefully if there are some special character non supported.
For image if you don’t specify the encode64 probably they arrive with artefact.

But pay attention, the encoding af big file request a bit of time.

The filed mime that specify the mime type of the file you want attach. Here some examples of existing mime type.

Than you must specify the storageType, in genera we only support SD and SPIFFS, for Arduino only SD.

The filename and url the filename is the name that appear to the receiver, the url is where is the file located in the FS selected.

Than in the EMailSender::Attachments you must specify the number of attachments and set the array of EMailSender::FileDescriptior.

The resulting code is this

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * esp32 Gmail send example with 2 attach loaded in SPIFFS
 *
 * The base64 encoding of the image is slow, so be patient
 *
 * https://www.mischianti.org
 *
 */

#include "Arduino.h"
#include <EMailSender.h>
#include <WiFi.h>

#include <SPIFFS.h>

const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";

uint8_t connection_state = 0;
uint16_t reconnect_interval = 10000;

EMailSender emailSend("account_gmail@gmail.com", "<YOUR-GMAIL-PASSWD>");

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
    static uint16_t attempt = 0;
    Serial.print("Connecting to ");
    if(nSSID) {
        WiFi.begin(nSSID, nPassword);
        Serial.println(nSSID);
    }

    uint8_t i = 0;
    while(WiFi.status()!= WL_CONNECTED &amp;&amp; i++ < 50)
    {
        delay(200);
        Serial.print(".");
    }
    ++attempt;
    Serial.println("");
    if(i == 51) {
        Serial.print("Connection: TIMEOUT on attempt: ");
        Serial.println(attempt);
        if(attempt % 2 == 0)
            Serial.println("Check if access point available or SSID and Password\r\n");
        return false;
    }
    Serial.println("Connection: ESTABLISHED");
    Serial.print("Got IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}

void Awaits()
{
    uint32_t ts = millis();
    while(!connection_state)
    {
        delay(50);
        if(millis() > (ts + reconnect_interval) &amp;&amp; !connection_state){
            connection_state = WiFiConnect();
            ts = millis();
        }
    }
}

void setup()
{
    Serial.begin(115200);

    if(!SPIFFS.begin()){
          Serial.println("An Error has occurred while mounting SPIFFS");
          return;
    }

    Serial.println("ReadDir");
    File dir = SPIFFS.open("/");
    File file = dir.openNextFile();
    while (file) {
        Serial.print(file.name());
        Serial.println(file.size());

        file = dir.openNextFile();
    }

    connection_state = WiFiConnect(ssid, password);
    if(!connection_state)  // if not connected to WIFI
        Awaits();          // constantly trying to connect

    EMailSender::EMailMessage message;
    message.subject = "Soggetto";
    message.message = "Ciao come stai<br>io bene.<br>www.mischianti.org";

    EMailSender::FileDescriptior fileDescriptor[2];
    fileDescriptor[1].filename = F("test.txt");
    fileDescriptor[1].url = F("/test.txt");
    fileDescriptor[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    fileDescriptor[0].filename = F("logo.jpg");
    fileDescriptor[0].url = F("/logo.jpg");
    fileDescriptor[0].mime = "image/jpg";
    fileDescriptor[0].encode64 = true;
    fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;

    EMailSender::Attachments attachs = {2, fileDescriptor};

    EMailSender::Response resp = emailSend.send("email_to_receive@gmail.com", message, attachs);

    Serial.println("Sending status: ");

    Serial.println(resp.status);
    Serial.println(resp.code);
    Serial.println(resp.desc);
}

void loop()
{

}

How to use GMail account

Allow less secure apps in Gmail

Allow less secure apps to access your Gmail account

Google may block sign-in attempts from some apps or devices that do not use modern security standards. Since these apps and devices are easier to break into, blocking them helps keep your account safe.

To disable this security feature:

  1. Sign in to Gmail
  2. Click here to access Less Secure App Access in My Account.
  3. Next to “Allow less secure apps: OFF,” select the toggle switch to turn ON.

This setting may not be available for:

For G-Suite users: Enabling less secure apps to access accounts

  1. Sign in to your Google Admin console (Sign in using an administrator account, not your current account.
  2. Click Security > Basic settings.
  3. Under Less secure apps, select Go to settings for less secure apps.
  4. In the subwindow, select the Allow users to manage their access to less secure apps radio button.

Once you’ve set Allow users to manage their access to less secure apps to on, affected users within the selected group or Organizational Unit will be able to toggle access for less secure apps on or off themselves.

G-Suite admins: Enforcing access to less secure apps for all users

Use this setting when you want to ensure that access by a less secure app is available to all for a limited time, such as for upgrades.

  1. Sign in to your Google Admin console.Sign in using an administrator account
  2. Click Security > Basic settings.
  3. Under Less secure apps, select Go to settings for less secure apps.
  4. In the subwindow, select the Enforce access to less secure apps for all users radio button.

Once you’ve set Enforce access to less secure apps for all users to on, affected users within the selected group or Organizational Unit will not be able to toggle access for less secure apps off themselves. You will have to set the setting back to Allow users to manage their access to less secure apps to allow them to toggle access for less secure apps on or off themselves.

Thanks

  1. Send email with attachments (EMailSender v2.x library): Arduino Ethernet
  2. Send email with attachments (EMailSender v2.x library): esp32 and esp8266

GitHub library


Spread the love
  •  
  •  
  •  
  • 1
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
    1
    Share

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *