Send emails with attachments: Arduino SAMD boards (WiFiNINA) – 3

Spread the love

I want to introduce version 2 of the EMailSender library, a great evolution compared to version 1, with support for Arduino with w5100, w5200, and w5500 ethernet devices and enc28J60 clone devices, support for esp32 and esp8266 and finally (from version 2.2.0) support for all Arduino (SAMD) devices using the WiFiNINA library (Arduino UNO WiFi Rev.2, Arduino NANO 33 IoT, Arduino MKR 1010 and Arduino MKR VIDOR 4000 WiFi, etc.). Now you can add attachments also loaded from a storage device like SD or SPIFFS.

Send email with attachments Arduino SAMD boards
Send an email with attachments to Arduino SAMD boards.

You can refer to version 1 of this library. Send emails with esp8266 and Arduino.

Introduction

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

This library uses 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 or receiving email from outside their systems. SMTP servers commonly use the Transmission Control Protocol on port number 25. (cit WiKi)

Library

You can find my library here, or search for EMailSender on the Arduino IDE library manager.

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 in your /libraries/ folder.

You may need to create the libraries subfolder if it’s your first library.

Restart the IDE.

Usage

Constructor: The default value is quite simple and uses Gmail as an SMTP server.

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

If you want to use another provider, you can use a more complex (but simple) constructor

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

You can also manage di parameter in realtime with these commands:

	void setSMTPPort(uint16_t smtp_port);
	void setSMTPServer(const char* smtp_server);
	void setEMailLogin(const char* email_login);
	void setEMailFrom(const char* email_from);
	void setNameFrom(const char* name_from);
	void setEMailPassword(const char* email_password);

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

  • 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);

Another parameter that you can set post constructor is

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

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

Updated: 02/01/2021 (v2.1.5)

The other two additional configurations are

	void setEHLOCommand(bool useEHLO = false)
	void setSASLLogin(bool isSASLLogin = false)

The first change HELO command in EHLO is needed by Postfix SMTP servers.

The second activates SASL login, so the login and password are sent all in one line.

You must connect to WIFI :P.

Basic example with Gmail SMTP

Remember to add google.com:433 to the list of the trusted domain.

I must publish an article about that, but for now, you must upload

File –> Examples –> WiFiNINA –> Tools –> FirmwareUpdater

Arduino IDE WiFiNINA sketch aggiornamento firmware
Arduino IDE WiFiNINA sketch aggiornamento firmware

then click on WiFiNINA firmware updater

Arduino IDE menu aggiornamento firmware NINA-W101
Arduino IDE menu aggiornamento firmware NINA-W101

Select the correct COM port.

And add google.com to the list of domains (Add domain).

Arduino IDE WiFiNINA programma aggiornamento firmware
Arduino IDE WiFiNINA programma aggiornamento firmware

And click on Upload Certificates to WiFi module .

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!

You can send to a list of emails and send like A, CC, or CCn; here is the example code to send to 3 email addresses

    const char* arrayOfEmail[] = {"<FIRST>@gmail.com", "<SECOND>@yahoo.com", "<THIRD>@hotmail.com"};
    EMailSender::Response resp = emailSend.send(arrayOfEmail, 3, message);

or to 3 email addresses, the first as To and the last as CC

    const char* arrayOfEmail[] = {"<FIRST>@gmail.com", "<SECOND>@yahoo.com", "<THIRD>@hotmail.com"};
    EMailSender::Response resp = emailSend.send(arrayOfEmail, 1, 2, message);

or first as To, second as CC, and third as CCn

    const char* arrayOfEmail[] = {"<FIRST>@gmail.com", "<SECOND>@yahoo.com", "<THIRD>@hotmail.com"};
    EMailSender::Response resp = emailSend.send(arrayOfEmail, 1,1,1, message);

Arduino MKR WiFi 1010 (WiFiNINA Library)

This is a fantastic device with excellent documentation and support, available in various stores.

You can find It here Amazon Arduino MKR WiFi 1010

Send simple email

So here is an example of a simple EMail sent with a GMail provider (configure GMail as described at the end of the article).

/*
 * EMailSender library for Arduino, Arduino SAMD boards (WiFiNINA), esp8266 and esp32
 * Simple Arduino SAMD boards (WiFiNINA) Gmail send 
 *
 * https://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */

#include "Arduino.h"
#include <EMailSender.h>
#include <WiFiNINA.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 && 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) && !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 an email with attachments.

The Arduino MKR WiFi 1010 does not have an internal flash and its younger brothers, and we have to go and connect an SD card to save the attachments to be sent.

Here is the connection diagram using a standard adapter; if you want to learn more about the topic, you can refer to this article “How to use the SD card with esp8266 and Arduino“.

Arduino MKR WiFi 1010 SD Card connection EMailSender
Arduino MKR WiFi 1010 SD Card connection EMailSender

The core of the code is the generation of the structure to upload and transmit 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 EMailSender::FileDescriptior are pretty comprehensive but pay attention to encode64, which specifies if you want to encode all the content, this is useful if some special character is not supported.
For images, if you don’t specify the encode64 probably, they arrive with an artifact.

But beware, encoding large files takes some time, but much less time than with an esp8266 or esp32.

The field mime specifies the mime type of the file you want to attach. Here are some examples of existing mime types.

Then you will need to select the storageType, usually SD and SPIFFS, for Arduino SD only.

The filename and url the filename is the name that appears to the receiver, and the URL is where the file is 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, Arduino SAMD boards (WiFiNINA), esp8266 and esp32
 * Simple Arduino SAMD boards (WiFiNINA) Gmail send attachments
 * to a single email 
 *
 * https://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */

#include "Arduino.h"
#include <EMailSender.h>
#include <WiFiNINA.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 && 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) && !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::FileDescriptior fileDescriptor[2];
    fileDescriptor[1].filename = F("test.txt");
    fileDescriptor[1].url = F("/test.txt");

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

    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()
{

}

Here you can see the result of the sketch just seen.

Send email with attachments Arduino esp8266 esp32 test with image and txt
Send an email with attachments Arduino esp8266 esp32 test with image and text.

Email to a distribution list

From version 2.1.1 distribution list is supported, so you can send emails to multiple accounts and select if you want to send as To, CC or CCn.

Here an example

/*
 * EMailSender library for Arduino, Arduino SAMD boards (WiFiNINA), esp8266 and esp32
 * Simple Arduino SAMD boards (WiFiNINA) Gmail send
 * to distribution lists
 *
 * https://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */

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


uint8_t connection_state = 0;
uint16_t reconnect_interval = 10000;

EMailSender emailSend("<YOUR-SMTP>", "<YOUR-SMTP-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 && 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) && !connection_state){
            connection_state = WiFiConnect();
            ts = millis();
        }
    }
}

void setup()
{
    Serial.begin(115200);
    const char* ssid = "<YOUR-SSID>";
    const char* password = "<YOUR-PASSWD>";

    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";

    // Send to 3 different email
    const char* arrayOfEmail[] = {"<FIRST>@gmail.com", "<SECOND>@yahoo.com", "<THIRD>@hotmail.com"};
    EMailSender::Response resp = emailSend.send(arrayOfEmail, 3, message);

//    // Send to 3 different email, 2 in C and 1 in CC
//    const char* arrayOfEmail[] = {"<FIRST>@gmail.com", "<SECOND>@yahoo.com", "<THIRD>@hotmail.com"};
//    EMailSender::Response resp = emailSend.send(arrayOfEmail, 2, 1, message);
//
//    // Send to 3 different email first to C second to CC and third to CCn
//    const char* arrayOfEmail[] = {"<FIRST>@gmail.com", "<SECOND>@yahoo.com", "<THIRD>@hotmail.com"};
//    EMailSender::Response resp = emailSend.send(arrayOfEmail, 1,1,1, message);


    Serial.println("Sending status: ");

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

void loop()
{

}

How to use a Gmail account

By default, you can’t use a Gmail SMTP account, and there are two ways to activate these features.

Allow less secure apps to access your Gmail account (deprecated)

Allow less secure apps in Gmail

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:

  • Accounts with 2-Step Verification enabled: For less secure app access, such accounts require an application-specific password.
  • G Suite users: This setting is hidden if your administrator has locked less secure app account access.

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. Select the Allow users to manage their access to a less secure apps radio button in the subwindow.

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.

Create an application password

Google account security 2 Step verification and application password
Google account security 2 Step verification and application password
  1. Go to the Gmail security settings page: https://myaccount.google.com/security
  2. First, you must enable 2-factor identification.
  3. Then you need to create a password for this application. The password is a 16-character string, copy it and use it as your standard SMTP Gmail account password!
Send email with attachments GMail application password
Send an email with attachments GMail application password

Thanks

  1. Send emails with attachments (EMailSender v2.x library): Arduino Ethernet
  2. Send emails with attachments (EMailSender v2.x library): esp32 and esp8266
  3. Send emails with attachments (EMailSender v2.x library): Arduino SAMD boards (WiFiNINA)
  4. Send emails with attachments and SSL (like Gmail): STM32, w5500, enc28j60, SD, and SPI Fash


Spread the love

17 Responses

  1. Stijn says:

    Hi,

    My gmail will not connect it says, I use a Arduino MKR WIFI 1010 with IOT cloud.

    • Hi,
      please decomment the EMAIL_DEBUG define and send me the output.
      Bye Renzo

      • shaunybean says:

        Hi Renzo,

        I am also getting the ‘Could not connect to mail server’ error – I have uncommented DEBUG – this is the output:

        I am using a Gmail account and I think I have set up everything in Gmail correctly (app password etc.)?

        11:14:08.030 -> Paddocks End
        11:14:08.030 ->
        11:14:08.030 -> Connection: ESTABLISHED
        11:14:08.030 -> Got IP address: 192.168.1.248
        11:14:08.030 -> ONLY ONE RECIPIENTmiltiple destination and attachments
        11:14:08.030 -> Insecure client:0
        11:14:08.030 -> smtp.gmail.com
        11:14:08.030 -> 465
        11:14:18.239 -> Sending status:
        11:14:18.239 -> 0
        11:14:18.239 -> 2
        11:14:18.239 -> Could not connect to mail server

        Can you help?

  2. albam says:

    Hola,
    Aún desactivando el firewall, el mensaje recibido al ejecutar el código es:

    Sending status:
    0
    2
    Could not connect to mail server

    Estamos usando ARDUINO UNO WIFI REV2, con WIFININA.

  3. sunrise says:

    Hi,
    I use a Arduino UNO wifi rev2. And said:
    Sending status:
    0
    2
    Could not connect to mail server
    Please, i need help. I stoped the firewalld too.

  4. Paul says:

    I use a MKR1010 WiFi, code will send email correctly two times but on the third and subsequent attempts will not connect to mail server. Any ideas?

    ONLY ONE RECIPIENTmiltiple destination and attachments
    Insecure client:0
    smtp.gmail.com
    465
    Sending status:
    0
    2
    Could not connect to mail server

Leave a Reply

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