Inviare email con allegati (libreria v2.x): Arduino Ethernet – 1

Spread the love

Vado ad introdurre la versione 2 della mia libreria EMailSender, una grande evoluzione rispetto alla versione 1, con supporto per Arduino con dispositivi ethernet w5100, w5200 e w5500 e dispositivi clone enc28J60, supporto per esp32 ed esp8266 ed infine (dalla versione 2.2.0) supporto per tutti i dispositivi Arduino (SAMD) che utilizzano la libreria WiFiNINA (Arduino UNO WiFi Rev.2, Arduino NANO 33 IoT, Arduino MKR 1010 and Arduino MKR VIDOR 4000 WiFi ecc.).
Ora puoi anche aggiungere allegati , caricati da un dispositivo di archiviazione come SD o SPIFFS.

Puoi fare riferimento alla versione 1 in questo articolo Invia email con esp8266 e Arduino

Introduzione

Un metodo semplice per notificare un problema è utilizzare la posta elettronica, quindi ho creato una libreria per farlo.

Send email with attachments Arduino library
Send email with attachments Arduino library

Questa libreria utilizza il protocollo SMTP:

Simple Mail Transfer Protocol (SMTP) è un protocollo standard per la trasmissione di email. Inizialmente proposto nella RFC 778 nel 1981, poi aggiornato con RFC 821 nel 1982 ed ulteriormente modificato nel 2008 con l’introduzione di extended SMTP (RFC 1869 e RFC 5321), che è il protocollo attualmente in uso.
Anche se i 
server di posta elettronica utilizzano SMTP per inviare e ricevere mail, i client mail a livello utente utilizzano SMTP solo per inviare il messaggio al server mail, il quale si occupa dell’invio del messaggio stesso. Per recuperare i messaggi, le applicazioni client usano solitamente protocolli come IMAP o POP3.
La comunicazione tra i server mail utilizza il protocollo 
TCP sulla porta 25. I client mail, tuttavia, spesso inviano le mail in uscita al server sulla porta 587. Anche se deprecata, i provider mail e alcuni produttori come Apple, permettono ancora l’uso della porta non standard 465 per questa operazione. (Cit. Wiki)

Libreria

Puoi trovare la mia libreria qui, oppure basta che cerchi EMailSender sul gestore delle librerie dell’Arduino IDE.

Per scaricare.

Clicca il bottone DOWNLOADS sull’angolo in alto a destra, e rinomina la cartella decompressa EMailSender.

Controlla che la cartella EMailSender contenga EMailSender.cpp e EMailSender.h.

Posizione la libreria EMailSender nella tua cartella /libraries/.

Potresti dover creare la sottocartella libraries se è la tua prima libreria.

Riavvia l’IDE.

Uso

Costruttore: il valore predefinito è abbastanza semplice e usa GMail come server smtp.

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

Se si desidera utilizzare un altro fornitore, è possibile utilizzare un costruttore più complesso (ma comunque semplice)

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 account smtp
  • email_password: password account smtp
  • email_from: email del mittente
  • name_from: nome utente del mittente
  • smtp_server: server SMTP
  • smtp_port: porta SMTP

Questi parametri sono modificabili anche in realtime con questi metodi:

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

Ora rispetto alla libreria v1.x puoi notare che il flag isSecure non esiste più

  • isSecure = false: if false BearSSL permette una connessione insicura TLS

ma puoi continuare a gestirlo con

void setIsSecure(bool isSecure = false);

Altri parametri che è possibile impostare post costruttore sono

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

Il primo permette di escludere l’handshake di autenticazione, il secondo modifica l’identificazione del messaggio HELO.

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

Altre due configurazioni aggiuntive sono

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

Il primo comando modifica HELO in EHLO, è necessario per i server SMTP Postfix.

Il secondo attiva la login SASL, quindi il login e la password vengono inviati tutti in una unica riga.

È necessario connettersi a ad internet :P.

Esempio di base con GMail smtp

Devi fare riferimento alla Parte 2 per configurare il tuo account GMail e controllare tutti i parametri.

Crea un messaggio con la struttura EMailMessage

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

Invia messaggio:

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

Quindi controlla la risposta:

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

Esempio di output:

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

Puoi inviare a un elenco di email e selezionare un CC o CCn, ad esempio invia a 3 email

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

oppure a 3 email, la prima come A e le ultime come CC

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

o il primo come A, il secondo come CC e il terzo come CCn

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

Arduino

Arduino, normalmente, gestisce la rete con un dispositivo esterno, uno dei dispositivi “standard” come w5100 utilizza la libreria Ethernet i cloni ENC28J60 ha varie librerie da selezionare.

Per selezionare il tuo dispositivo devi andare sul file EMailSenderKey.h nella libreria e impostare quello corretto

#define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_ENC28J60 // Default

La libreria caricata per gestire questo tipo di dispositivo è UIPEthernet, è possibile trovare la libreria sul gestore librerie dell’IDE Arduino

o puoi selezionare

#define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_W5100

Questa è l’implementazione standard e usa la libreria Ethernet.

Una cosa importante da considerare è che gli shield Ethernet non supporta SSL o TLS, quindi è necessario trovare un provider SMTP che offre una connessione SMTP senza questo tipo di codifica.

Creo un argomento sul forum in cui sarà possibile aggiungere il provider che si utilizza, e sarà possibile trovare anche quelli che utilizzo io.

SMTP server da usare con la libreria EMailSender

Come ho già detto, utilizzo un ENC28J60 con Arduino Mega 2560, qui lo schema di connessione:

Arduino Mega And Enc28j60 Ethernet connection schema
Arduino Mega And Enc28j60 Ethernet connection schema

Inviare una semplice email

Ecco qui un semplice esempio di invio email con il provider SendGrid.

  • “apikey” indica che stiamo per inviare un codice relativo a un modulo API.
  • “your_password_apikey” è la password fornita da Sendgrid quando si richiede una chiave SMTP Relay.
  • “your_mail” è l’indirizzo di accesso di Sendgrid.
  • Devi usare 587 come porta.
/*
 * EMailSender library for Arduino, esp8266 and esp32
 * Arduino Mega and UIPEthernet send example with Sendgrid provider
 *
 * Pay attention you must set in the library
 * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_ENC28J60
 * for UIPEthernet
 *
 * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_W5100
 * for standard Ethernet
 *
 *
 * https://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */

#include "Arduino.h"
#include <SPI.h>
#include <UIPEthernet.h>

#include <EMailSender.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

EMailSender emailSend("<YOUR-SENDGRID-API-KEY>", "<YOUR-SENDGRID-PASSWD>", "<FROM-EMAIL>", "smtp.sendgrid.net", 25);

void setup()
{
    // Open serial communications and wait for port to open:
    Serial.begin(115200);
//    while (!Serial) {}

    delay(2000);

    Serial.println("Starting!");

    // start the Ethernet connection:
    if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed to configure Ethernet using DHCP");
      while(1);
    }
    Serial.print("IP address ");
    Serial.println(Ethernet.localIP());


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

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

    Serial.println("Sending status: ");

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

void loop()
{

}

Inviare email con allegati

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

Aggiungerò questo esempio solo per spiegare come fare, non ho trovato un provider SMTP senza SSL e TLS che supportano gli allegati, perciò andrà testato sul campo.

Naturalmente hai bisogno di un dispositivo di archiviazione in cui inserire i dati da allegare, io uso un normale adattatore SD collegato al pin CS 4.

Puoi trovare tutte le informazioni sul collegamento di una scheda SD su quest’articolo “Come usare la scheda SD con esp8266 e Arduino“.

Arduino Mega Enc28j60 SD connection schema EMailSender
Arduino Mega Enc28j60 SD connection schema EMailSender

Il core del codice è la generazione della struttura per trasmettere le informazioni relative agli allegati.

    EMailSender::FileDescriptior fileDescriptor[1];
    fileDescriptor[0].filename = F("test.txt");
    fileDescriptor[0].url = F("/test.txt");
    fileDescriptor[0].mime = MIME_TEXT_PLAIN;
    fileDescriptor[0].encode64 = false;
    fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

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

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

Il campi del EMailSender::FileDescriptiorsono abbastanza comprensibili, ma presta attenzione a encode64che specifica se vuoi codificare tutto il contenuto, questo è utile se ci sono alcuni caratteri speciali non supportati.
Per l’immagine se non specifichi encode64 probabilmente arriverà artefatta.

Ma attenzione, la codifica di file di grandi dimensioni richiede un po’ di tempo.

Il fiel mime specifica il tipo mime del file che si desidera allegare. Ecco alcuni esempi di tipi MIME esistenti.

Poi devi specificare lo storageType, in genere supportiamo solo SD e SPIFFS, ma per Arduino solo SD.

Il filenameurl sono rispettivamente il nome del file è il nome che apparirà al destinatario, l’URL è dove si trova il file nell’FS selezionato.

Poi in EMailSender::Attachmentssarà necessario specificare il numero di allegati e impostare l’array di EMailSender::FileDescriptior.

Il codice risultante sarà

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * Arduino Mega and UIPEthernet send example with attach
 * this example is not tested for all, I can't find a provider
 * that manage attach without SSL and TLS
 *
 * Pay attention you must set in the library
 * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_ENC28J60
 * for UIPEthernet
 *
 * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_W5100
 * for standard Ethernet
 *
 * The base64 encoding of the image is slow, so be patient
 *
 *
 * https://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */

#include "Arduino.h"
#include <SPI.h>
#include <UIPEthernet.h>
#include <SD.h>

#include <EMailSender.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

//	EMailSender(const char* email_login, const char* email_password, const char* email_from, const char* smtp_server, uint16_t smtp_port, bool isSecure = false);
EMailSender emailSend("<LOGIN>", "<PASSWD>", "<EMAIL-FROM>", "<SMTP-SERVER>", "<SMTP-SERVER-PORT>");

void printDirectory(File dir, int numTabs);

//The setup function is called once at startup of the sketch
void setup()
{
    Serial.begin(115200);

    delay(2000);

    Serial.println("Starting!");

    Serial.print("Initializing SD card...");

    if (!SD.begin(4)) {
      Serial.println("initialization failed!");
      while (1);
    }
    Serial.println("initialization done.");

    File root = SD.open("/");

    printDirectory(root, 0);

    Serial.println("done!");

//	File myFile = SD.open("/TEST.TXT", "r");
//	  if(myFile) {
//		  myFile.seek(0);
//		  DEBUG_PRINTLN(F("OK"));
//		myFile.close();
//	  }
//	  else {
//		  DEBUG_PRINTLN(F("KO"));
//	  }
//
//
    // start the Ethernet connection:
    if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed to configure Ethernet using DHCP");
      while(1);
    }
    Serial.print("IP address ");
    Serial.println(Ethernet.localIP());


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

// 		Two file
//    EMailSender::FileDescriptior fileDescriptor[2];
//    fileDescriptor[1].filename = F("test.txt");
//    fileDescriptor[1].url = F("/test.txt");
//    fileDescriptor[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
//
//    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_SD;
//
//    EMailSender::Attachments attachs = {2, fileDescriptor};

// 		One file
    EMailSender::FileDescriptior fileDescriptor[1];
    fileDescriptor[0].filename = F("test.txt");
    fileDescriptor[0].url = F("/test.txt");
    fileDescriptor[0].mime = MIME_TEXT_PLAIN;
    fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

    // Pay attention base64 encoding is quite slow
//	EMailSender::FileDescriptior fileDescriptor[2];
//	fileDescriptor[0].filename = F("logo.jpg");
//	fileDescriptor[0].url = F("/logo.jpg");
//	fileDescriptor[0].mime = "image/jpg";
//	fileDescriptor[0].encode64 = false;
//	fileDescriptor[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;

    EMailSender::Attachments attachs = {1, 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);

    File root2 = SD.open("/");

    printDirectory(root2, 0);

    Serial.println("done!");
    SD.end();
}

void loop()
{

}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

Inviare EMail a liste di distribuzione

Dalla versione 2.1.1 sono supportate le liste di distribuzione, quindi è possibile inviare e-mail a più account se si desidera inviare come A, CC o Cn.

Ecco un esempio

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * Arduino Mega and UIPEthernet send example with Sendgrid provider
 * to a distribution list
 *
 * Pay attention you must set in the library
 * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_ENC28J60
 * for UIPEthernet
 *
 * #define DEFAULT_EMAIL_NETWORK_TYPE_ARDUINO 	NETWORK_W5100
 * for standard Ethernet
 *
 *
 * https://mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */

#include "Arduino.h"
#include <SPI.h>
#include <UIPEthernet.h>

#include <EMailSender.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

EMailSender emailSend("<YOUR-SENDGRID-API-KEY>", "<YOUR-SENDGRID-PASSWD>", "<FROM-EMAIL>", "smtp.sendgrid.net", 25);

void setup()
{
    // Open serial communications and wait for port to open:
    Serial.begin(115200);
//    while (!Serial) {}

    delay(2000);

    Serial.println("Starting!");

    // start the Ethernet connection:
    if (Ethernet.begin(mac) == 0) {
      Serial.println("Failed to configure Ethernet using DHCP");
      while(1);
    }
    Serial.print("IP address ");
    Serial.println(Ethernet.localIP());


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

}

Grazie

  1. Inviare email con allegati (libreria v2.x): Arduino Ethernet
  2. Inviare email con allegati (libreria v2.x): esp32 e esp8266
  3. Inviare email con allegati (libreria v2.x): schede Arduino SAMD (WiFiNINA)

GitHub library


Spread the love

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *