Come Inviare Email con Allegati da ESP32 e ESP8266 (Guida EMailSender 4.x.x e STARTTLS)
E finalmente, la guida aggiornata per utilizzare EMailSender v4.0.0 su ESP32 e ESP8266! Questo tutorial copre tutto ciò che devi sapere sull’invio di email sicure dalla tua scheda ESP32 utilizzando il nuovo supporto STARTTLS sulla porta 587.

Dopo mesi di sviluppo e test, la versione 4.0.0 introduce il supporto nativo a STARTTLS (porta 587) accanto al supporto esistente per SSL/TLS implicito (porta 465), offrendoti maggiore flessibilità e compatibilità con vari provider di posta elettronica.
Perché STARTTLS è Importante
Negli ultimi anni, i provider di servizi di posta elettronica hanno rafforzato i requisiti di sicurezza. Gmail, ad esempio, ha spinto gli utenti verso la porta 587 con STARTTLS come metodo preferito per l’invio di email.
Il Problema
Le versioni precedenti di EMailSender supportavano:
- ✅ Porta 465 con SSL/TLS implicito (connessione crittografata dall’inizio)
- ❌ Porta 587 con STARTTLS (la connessione inizia in chiaro, poi passa a SSL)
Questa limitazione significava che alcune configurazioni raccomandate dai moderni provider di posta elettronica non potevano essere utilizzate efficacemente.
La Soluzione
La versione 4.0.0 introduce il supporto completo a STARTTLS, consentendo alla libreria di:
- Connettersi al server SMTP sulla porta 587 con una connessione in chiaro
- Inviare il comando STARTTLS
- Aggiornare automaticamente la connessione a SSL/TLS
- Continuare la comunicazione sicura per l’autenticazione e la trasmissione dell’email
Questo rende EMailSender pienamente compatibile con le attuali raccomandazioni di Gmail e i requisiti dei moderni server SMTP.
Il Consiglio
Ricorda che l’uso di STARTTLS richiede librerie e risorse aggiuntive. Se possibile, e se non si tratta di un’applicazione critica per la sicurezza, continua a utilizzare la porta 465 per SSL/TLS.
Novità della Versione 4.0.0
Funzionalità Principali
Supporto STARTTLS (Porta 587)
La funzionalità di punta! La libreria ora supporta il protocollo STARTTLS, che è lo standard per le connessioni sulla porta 587.
// Abilita STARTTLS in EMailSenderKey.h
#define EMAIL_ENABLE_INTERNAL_SSLCLIENT
EMailSender emailSend("tua.email@gmail.com", "password_app",
"tua.email@gmail.com", "Tuo Nome",
"smtp.gmail.com", 587); // Porta 587!
emailSend.setEHLOCommand(true); // Richiesto per STARTTLS
Integrazione di SSLClient Interno
Per ESP32 ed ESP8266, ho integrato un’implementazione personalizzata di SSLClient che gestisce l’aggiornamento a STARTTLS in modo trasparente. Ciò significa:
- Nessuna libreria esterna richiesta per STARTTLS su ESP32/ESP8266
- Handshake SSL automatico dopo il comando STARTTLS
- Crittografia trasparente per tutte le comunicazioni successive
Metodi di Autenticazione Migliorati
La libreria ora supporta più metodi di autenticazione:
- AUTH LOGIN (predefinito) – Metodo più comune
- AUTH PLAIN (SASL) – Autenticazione alternativa
- CRAM-MD5 (solo ESP32) – Autenticazione challenge-response
// Usa diversi metodi di autenticazione
emailSend.setSASLLogin(true); // AUTH PLAIN
emailSend.setCramMD5Login(true); // CRAM-MD5 (ESP32)
Gestione degli Errori Migliorata
Messaggi di errore e codici di risposta migliori rendono il debug più facile:
EMailSender::Response resp = emailSend.send("destinatario@example.com", message);
if (!resp.status) {
Serial.print("Codice Errore: ");
Serial.println(resp.code);
Serial.print("Descrizione: ");
Serial.println(resp.desc); // Messaggio di errore dettagliato
}
Migliore Gestione di EHLO/HELO
I server SMTP moderni spesso restituiscono risposte su più righe ai comandi EHLO. La nuova versione le gestisce correttamente con il metodo awaitSMTPResponseDrain().
Comprendere STARTTLS vs SSL/TLS
Chiariamo la differenza tra i due metodi di crittografia:
Porta 465 – SSL/TLS Implicito

Caratteristiche:
- ✅ Connessione crittografata fin dall’inizio
- ✅ Semplice da implementare
- ✅ Molto sicuro
- ❌ Utilizza una porta SSL dedicata (465)
Porta 587 – STARTTLS

Caratteristiche:
- ✅ Porta di invio standard (587)
- ✅ Ampiamente supportato dai server moderni
- ✅ Flessibile – può tornare a non crittografato se necessario
- ✅ Raccomandato da Gmail e dalla maggior parte dei provider
- ⚠️ Più complesso da implementare (ora risolto!)
Quale Dovresti Usare?
Per Gmail e la maggior parte dei provider moderni:
- Porta 587 con STARTTLS è raccomandato
- Migliore compatibilità con i firewall
- Porta di invio SMTP standard
Per la massima compatibilità:
- Entrambe le porte funzionano con EMailSender v4.0.0!
- Scegli in base alle raccomandazioni del tuo provider di posta elettronica
Non per prestazioni e risorse
Tuttavia, ricorda che per usare STARTTLS avrai bisogno di più risorse in termini di RAM e Flash, quindi tienine conto.
Hardware
Qui per acquistare la mia selezione di ESP32 ESP32 Dev Kit v1 - TTGO T-Display 1.14 ESP32 - NodeMCU V3 V2 ESP8266 Lolin32 - NodeMCU ESP-32S - WeMos Lolin32 - WeMos Lolin32 mini - ESP32-CAM programmer - ESP32-CAM bundle - ESP32-WROOM-32 - ESP32-S
Qui per acquistare la mia selezione di ESP32-C3 LuatOS esp32c3 Core - ESP32-C3-DevKitC-02 - ESP32-C3-MINI-1 - WeMos LOLIN C3 PICO - WeMos LOLIN C3 Mini v2.1 - WeMos LOLIN C3 Mini v1.0 - ESP32 S3 Purlple AI-S3 - ESP32 C3 Zero - ESP32 C3 SuperMini
Qui per acquistare la mia selezione di ESP32-S3 ESP32 S3 Purlple AI-S3 - YD-ESP32-S3 - ESP32-S3-DevKitC-1 - ESP32-S3-DevKitC-1 - ESP32-S3 Board 5-inch/7-inch screen - ESP32-S3 Zero
Per archiviare log e una grande quantità di dati, è utile utilizzare una scheda SD.

Anche per esp8266.

Qui per acquistare la mia selezione di moduli per schede SD AliExpress
Configurazione Software e Librerie
Installa le Librerie
IDE Arduino

- Apri l’IDE Arduino
- Vai su Sketch > Includi Libreria > Gestisci Librerie
- Cerca “EMailSender“
- Fai clic su Installa
PlatformIO
Aggiungi al tuo platformio.ini:
lib_deps =
xreef/EMailSender@^4.0.0
Installazione Manuale
- Scarica la libreria da GitHub
- Estrai nella cartella delle librerie di Arduino
- Riavvia l’IDE Arduino
Supporto Piattaforme
EMailSender v4.0.0 supporta una vasta gamma di piattaforme di microcontrollori:
| Piattaforma | WiFi | Ethernet | SSL/TLS | STARTTLS | Stato |
|---|---|---|---|---|---|
| ESP32 | ✅ | ✅ | ✅ | ✅ | Supporto Completo |
| ESP8266 | ✅ | ✅ | ✅ | ✅ | Supporto Completo |
| Arduino Mega | ❌ | ✅ | ❌ | ❌ | Memoria Limitata |
| Arduino Uno | ❌ | ✅ | ❌ | ❌ | Memoria Limitata |
| Arduino SAMD | ✅ | ✅ | ✅ | ✅ | Supporto Completo |
| STM32 | ❌ | ✅ | ✅* | ❌ | Con Ethernet |
| Raspberry Pi Pico W | ✅ | ✅ | ✅ | ✅ | Supporto Completo |
* Necessita di una buona quantità di RAM
Interfacce di Rete
- WiFi: ESP32, ESP8266, SAMD (WiFiNINA), Raspberry Pi Pico W
- Ethernet W5100/W5200/W5500: Tutte le piattaforme
- Ethernet ENC28J60: Tutte le piattaforme (con UIPEthernet)
- Ethernet con SSL: Wrapper SSLClient per connessioni sicure
Guida Rapida per GMail
Inviamo la tua prima email con STARTTLS!
Ottieni la Password per le App di Gmail
Gmail non accetta più le password normali. Hai bisogno di una Password per le App:
- Vai al tuo Account Google
- Seleziona Sicurezza
- Abilita la Verifica in 2 passaggi (se non è già abilitata)
- Vai su Password per le app: https://myaccount.google.com/apppasswords
- Genera una nuova password per “Posta” sul tuo dispositivo
- Copia la password di 16 caratteri (senza spazi)
Configura EMailSenderKey.h per STARTTLS
Apri EMailSenderKey.h e abilita il supporto a STARTTLS:
// Abilita il supporto STARTTLS per ESP32/ESP8266
#define EMAIL_ENABLE_INTERNAL_SSLCLIENT
// Abilita il debug (opzionale)
// #define EMAIL_SENDER_DEBUG
// #define DEBUG_PRINTER Serial
Esempio Base con STARTTLS
/*
* EMailSender v4.0.0 - STARTTLS Test for ESP32
*
* Simple example demonstrating email sending using STARTTLS on port 587
* Tests the EMailSender library with Gmail SMTP authentication
*
* Author: Renzo Mischianti
* Website: https://www.mischianti.org
*
* Tutorial and documentation available at:
* https://www.mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
*
* EMailSender Library: https://github.com/xreef/EMailSender
*
* This example requires:
* - ESP32 board
* - WiFi connection
* - Gmail account with App Password enabled
*/
#include <WiFi.h>
#include <EMailSender.h>
// WiFi credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// Gmail configuration
const char* emailAddress = "your.email@gmail.com";
const char* emailPassword = "your 16-char app password"; // No spaces!
// Create EMailSender with Gmail SMTP settings
EMailSender emailSend(emailAddress, emailPassword,
emailAddress, "Your Name",
"smtp.gmail.com", 587); // Port 587 for STARTTLS
void setup() {
Serial.begin(115200);
Serial.println("EMailSender v4.0.0 - STARTTLS Test");
// Connect to WiFi
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Enable EHLO (required for STARTTLS)
emailSend.setEHLOCommand(true);
// Prepare email message
EMailSender::EMailMessage message;
message.subject = "Test from EMailSender v4.0.0";
message.message = "Hello! This email was sent using STARTTLS on port 587.";
message.mime = MIME_TEXT_PLAIN;
// Send email
Serial.println("\nSending email via STARTTLS (port 587)...");
EMailSender::Response resp = emailSend.send("recipient@example.com", message);
// Check result
Serial.println("Response Status:");
Serial.print(" Code: ");
Serial.println(resp.code);
Serial.print(" Description: ");
Serial.println(resp.desc);
Serial.print(" Success: ");
Serial.println(resp.status ? "YES" : "NO");
if (resp.status) {
Serial.println("\n Email sent successfully!");
} else {
Serial.println("\n Email sending failed!");
}
}
void loop() {
// Nothing here
}
Output Atteso
EMailSender v4.0.0 - STARTTLS Test
Connecting to WiFi.....
WiFi Connected!
IP Address: 192.168.1.66
Sending email via STARTTLS (port 587)...
Response Status:
Code: 0
Description: Message sent!
Success: YES
Email sent successfully!
Ottimizzazione della Memoria, specialmente per ESP8266
Prima di tutto, non usare STARTTLS sulla porta 587, ma SSL/TLS implicito sulla porta 465
Controlla la Memoria Disponibile
Monitora sempre la memoria durante lo sviluppo:
void printMemoryStats() {
Serial.println("\n=== Statistiche Memoria ===");
Serial.printf("Heap Libero: %d byte\n", ESP.getFreeHeap());
Serial.printf("Frammentazione Heap: %d%%\n", ESP.getHeapFragmentation());
Serial.printf("Blocco Libero Massimo: %d byte\n", ESP.getMaxFreeBlockSize());
Serial.printf("Dimensione Chip Flash: %d byte\n", ESP.getFlashChipSize());
Serial.printf("Spazio Sketch Libero: %d byte\n", ESP.getFreeSketchSpace());
}
void setup() {
Serial.begin(115200);
delay(100);
printMemoryStats(); // Controlla all'avvio
}
Usa PROGMEM per le Stringhe Statiche
// Sbagliato - usa RAM
const char* subject = "Allarme Temperatura da ESP8266";
// Giusto - usa Flash
const char subject[] PROGMEM = "Allarme Temperatura da ESP8266";
// Usa con:
String subjectStr = FPSTR(subject);
Riduci la Concatenazione di Stringhe
// Sbagliato - crea molte stringhe temporanee
String html = "<html><body>";
html += "<h1>Stato</h1>";
html += "<p>Temperatura: " + String(temp) + "</p>";
html += "</body></html>";
// Meglio - pre-calcola la dimensione
String html;
html.reserve(200); // Riserva spazio in anticipo
html = "<html><body><h1>Stato</h1>";
html += "<p>Temperatura: ";
html += temp;
html += "</p></body></html>";
// Ottimo - usa la macro F()
String html = F("<html><body><h1>Stato</h1><p>Temperatura: ");
html += temp;
html += F("</p></body></html>");
Limita la Complessità dell’HTML
// HTML semplice e a basso consumo di memoria
void createSimpleHTML(float temp, float humidity) {
String html = F("<!DOCTYPE html><html><body>");
html += F("<h2>Rapporto Sensori</h2>");
html += F("<p>Temp: ");
html += String(temp, 1);
html += F("C</p><p>Umidità: ");
html += String(humidity, 1);
html += F("%</p></body></html>");
return html;
}
Usa lo Streaming per Dati Voluminosi
// Invece di costruire l'intera email in memoria
void sendStreamedData() {
// Apri file
File dataFile = LittleFS.open("/data.txt", "r");
// Invia in blocchi
EMailSender::FileDescriptior fileDesc;
fileDesc.filename = "data.txt";
fileDesc.url = "/data.txt";
fileDesc.storageType = EMailSender::EMAIL_STORAGE_TYPE_LITTLE_FS;
// EMailSender gestisce lo streaming automaticamente
}
Esempio base SSL/TLS
/*
* EMailSender v4.0.0 - Simple Email Test for ESP32 (No STARTTLS)
*
* Basic example demonstrating email sending without STARTTLS
* Uses standard SMTP connection (typically port 25, 465, or custom ports)
* Suitable for local mail servers or services that don't require encryption
*
* Author: Renzo Mischianti
* Website: https://www.mischianti.org
*
* Tutorial and documentation available at:
* https://www.mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
*
* EMailSender Library: https://github.com/xreef/EMailSender
*
* This example requires:
* - ESP32 board
* - WiFi connection
* - SMTP server that accepts non-encrypted connections
*
* Note: This method is less secure than STARTTLS and should only be used
* with trusted local networks or mail servers that explicitly support it.
*/
#include <WiFi.h>
#include <EMailSender.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
EMailSender emailSend("alert@gmail.com", "app_password",
"alert@gmail.com", "ESP32 Sensor",
"smtp.gmail.com", 465);
// Alternative: Using default constructor (Gmail defaults, but without STARTTLS)
// EMailSender emailSend("your@email.com", "your_password");
void setup() {
Serial.begin(115200);
Serial.println("EMailSender v4.0.0 - Simple Email Test (No STARTTLS)");
// Connect to WiFi
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// DO NOT enable EHLO for non-STARTTLS connections
// emailSend.setEHLOCommand(false); // This is default
// Prepare email message
EMailSender::EMailMessage message;
message.subject = "Test from EMailSender v4.0.0 (No STARTTLS)";
message.message = "Hello! This email was sent using a simple SMTP connection without STARTTLS encryption.";
message.mime = MIME_TEXT_PLAIN;
// Send email
Serial.println("\nSending email via simple SMTP...");
EMailSender::Response resp = emailSend.send("recipient@example.com", message);
// Check result
Serial.println("Response Status:");
Serial.print(" Code: ");
Serial.println(resp.code);
Serial.print(" Description: ");
Serial.println(resp.desc);
Serial.print(" Success: ");
Serial.println(resp.status ? "YES" : "NO");
if (resp.status) {
Serial.println("\n Email sent successfully!");
} else {
Serial.println("\n Email sending failed!");
Serial.println("\nTroubleshooting:");
Serial.println("- Check if your SMTP server accepts non-encrypted connections");
Serial.println("- Verify port number (25 for standard SMTP, or server-specific)");
Serial.println("- Ensure firewall allows outgoing SMTP traffic");
Serial.println("- Some providers block port 25 - try alternative ports");
}
}
void loop() {
// Nothing here
}
Il risultato diventa così.
EMailSender v4.0.0 - Simple Email Test (No STARTTLS)
Connecting to WiFi...
WiFi Connected!
IP Address: 192.168.1.66
Sending email via simple SMTP...
Response Status:
Code: 0
Description: Message sent!
Success: YES
Email sent successfully!
Esempi Avanzati
Email HTML con Stile
void sendHTMLEmail() {
EMailSender::EMailMessage message;
message.subject = "Rapporto di Stato ESP32";
// Crea contenuto HTML
String html = "<!DOCTYPE html><html><head>"
"<style>"
"body { font-family: Arial, sans-serif; }"
".header { background: #4CAF50; color: white; padding: 20px; }"
".content { padding: 20px; }"
".footer { background: #f1f1f1; padding: 10px; font-size: 12px; }"
"</style></head><body>"
"<div class='header'><h1>Rapporto di Stato ESP32</h1></div>"
"<div class='content'>"
"<h2>Informazioni Dispositivo</h2>"
"<p><strong>Indirizzo IP:</strong> " + WiFi.localIP().toString() + "</p>"
"<p><strong>Segnale WiFi:</strong> " + String(WiFi.RSSI()) + " dBm</p>"
"<p><strong>Heap Libero:</strong> " + String(ESP.getFreeHeap()) + " byte</p>"
"<p><strong>Uptime:</strong> " + String(millis() / 1000) + " secondi</p>"
"</div>"
"<div class='footer'>Inviato dal Dispositivo ESP32</div>"
"</body></html>";
message.message = html;
message.mime = MIME_TEXT_HTML;
EMailSender::Response resp = emailSend.send("destinatario@example.com", message);
Serial.println(resp.status ? "Email inviata!" : "Fallito: " + resp.desc);
}
Sistema di Allarme con Sensore di Temperatura
#include <WiFi.h>
#include <EMailSender.h>
// Sensore DHT (installa la libreria per sensori DHT)
#include <DHT.h>
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
const char* ssid = "TUA_SSID";
const char* password = "TUA_PASSWORD";
EMailSender emailSend("allarme@gmail.com", "password_app",
"allarme@gmail.com", "Sensore ESP32",
"smtp.gmail.com", 587);
const float TEMP_ALTA = 30.0; // Soglia temperatura alta
const float TEMP_BASSA = 15.0; // Soglia temperatura bassa
const float UMIDITA_ALTA = 80.0; // Soglia umidità alta
unsigned long ultimoInvioEmail = 0;
const unsigned long INTERVALLO_EMAIL = 300000; // 5 minuti tra le email
void inviaAllarme(String tipoAllarme, float temp, float hum);
void setup() {
Serial.begin(115200);
dht.begin();
// Connetti WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi Connesso!");
emailSend.setEHLOCommand(true);
}
void loop() {
float temperatura = dht.readTemperature();
float umidita = dht.readHumidity();
if (isnan(temperatura) || isnan(umidita)) {
Serial.println("Lettura sensore fallita!");
Serial.println("Imposto dati fittizi!");
// Genera dati fittizi realistici che possono attivare allarmi
// Temperatura: casuale tra 10°C e 35°C
temperatura = 10.0 + (float)(rand() % 250) / 10.0; // da 10.0 a 35.0
// Umidità: casuale tra 40% e 90%
umidita = 40.0 + (float)(rand() % 510) / 10.0; // da 40.0 a 90.0
}
Serial.printf("Temp: %.1f°C, Umidità: %.1f%%\n", temperatura, umidita);
// Controlla le soglie
bool serveAllarme = false;
String tipoAllarme = "";
if (temperatura > TEMP_ALTA) {
serveAllarme = true;
tipoAllarme = "TEMPERATURA ALTA";
} else if (temperatura < TEMP_BASSA) {
serveAllarme = true;
tipoAllarme = "TEMPERATURA BASSA";
} else if (umidita > UMIDITA_ALTA) {
serveAllarme = true;
tipoAllarme = "UMIDITÀ ALTA";
}
// Invia allarme se necessario e non inviato di recente
if (serveAllarme && (millis() - ultimoInvioEmail > INTERVALLO_EMAIL || ultimoInvioEmail == 0)) {
Serial.println("Allarme Email!");
inviaAllarme(tipoAllarme, temperatura, umidita);
ultimoInvioEmail = millis();
}
// Leggi il sensore ogni 10 secondi
delay(10000);
}
void inviaAllarme(String tipoAllarme, float temp, float hum) {
Serial.println("Invio email di allarme...");
EMailSender::EMailMessage message;
message.subject = "⚠️ " + tipoAllarme + " ALLARME";
String html = "<html><body style='font-family: Arial;'>"
"<h2 style='color: #d32f2f;'>🚨 " + tipoAllarme + "</h2>"
"<div style='background: #fff3e0; padding: 15px; border-left: 4px solid #ff9800;'>"
"<p><strong>Temperatura:</strong> " + String(temp, 1) + "°C</p>"
"<p><strong>Umidità:</strong> " + String(hum, 1) + "%</p>"
"<p><strong>Ora:</strong> " + String(millis() / 1000) + " secondi dall'avvio</p>"
"</div>"
"<p style='color: #666; font-size: 12px; margin-top: 20px;'>Inviato dal Sistema di Monitoraggio ESP32</p>"
"<p style='color: #999; font-size: 11px;'>Realizzato con la libreria EMailSender di Renzo Mischianti - "
"<a href='https://www.mischianti.org' style='color: #1976d2;'>www.mischianti.org</a></p>"
"</body></html>";
message.message = html;
message.mime = MIME_TEXT_HTML;
EMailSender::Response resp = emailSend.send("smtp.mischianti@gmail.com", message);
if (resp.status) {
Serial.println("✅ Allarme inviato con successo!");
} else {
Serial.println("❌ Invio allarme fallito: " + resp.desc);
}
}
Un sistema di monitoraggio basato su ESP32 che invia allarmi email automatici quando le soglie ambientali vengono superate.
Configurazione Hardware
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
Sensore DHT22 collegato al GPIO 4 per le letture di temperatura e umidità.
Configurazione Email
EMailSender emailSend("tua@gmail.com", "password_app",
"tua@gmail.com", "Sensore ESP32",
"smtp.gmail.com", 587);
Configurazione SMTP di Gmail con autenticazione. Richiede una password per le app di Gmail (non la password normale).
Configurazione Soglie
const float TEMP_ALTA = 30.0;
const float TEMP_BASSA = 15.0;
const float UMIDITA_ALTA = 80.0;
const unsigned long INTERVALLO_EMAIL = 300000; // 5 minuti
Definisce le soglie di allarme e l’intervallo minimo tra le email per prevenire lo spam.
Lettura Sensore con Fallback
float temperatura = dht.readTemperature();
float umidita = dht.readHumidity();
if (isnan(temperatura) || isnan(umidita)) {
// Genera dati fittizi realistici
temperatura = 10.0 + (float)(rand() % 250) / 10.0; // 10.0-35.0°C
umidita = 40.0 + (float)(rand() % 510) / 10.0; // 40.0-90.0%
}
Legge i dati del sensore ogni 10 secondi. Se la lettura fallisce, genera valori fittizi realistici per i test.
Logica di Allarme
if (temperatura > TEMP_ALTA) {
tipoAllarme = "TEMPERATURA ALTA";
} else if (temperatura < TEMP_BASSA) {
tipoAllarme = "TEMPERATURA BASSA";
} else if (umidita > UMIDITA_ALTA) {
tipoAllarme = "UMIDITÀ ALTA";
}
if (serveAllarme && (millis() - ultimoInvioEmail > INTERVALLO_EMAIL || ultimoInvioEmail == 0)) {
inviaAllarme(tipoAllarme, temperatura, umidita);
ultimoInvioEmail = millis();
}
Controlla le soglie e invia un allarme immediatamente al primo superamento, poi rispetta un tempo di attesa di 5 minuti.
Formato Email HTML

EMailSender::EMailMessage message;
message.subject = "⚠️ " + tipoAllarme + " ALLARME";
message.mime = MIME_TEXT_HTML;
String html = "<html><body style='font-family: Arial;'>"
"<h2 style='color: #d32f2f;'>🚨 " + tipoAllarme + "</h2>"
"<div style='background: #fff3e0; padding: 15px;'>"
"<p><strong>Temperatura:</strong> " + String(temp, 1) + "°C</p>"
"<p><strong>Umidità:</strong> " + String(hum, 1) + "%</p>"
"</div></body></html>";
EMailSender::Response resp = emailSend.send("destinatario@example.com", message);
Invia un’email HTML con stile, con allarmi colorati e dati dei sensori formattati.
Se il sensore non funziona correttamente, il sistema genera automaticamente dati fittizi realistici per consentire test e sviluppo senza hardware funzionante.
Generatore di Rapporti Giornalieri
#include <WiFi.h>
#include <EMailSender.h>
#include <time.h>
const char* ssid = "TUA_SSID";
const char* password = "TUA_PASSWORD";
// Impostazioni NTP
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0;
const int daylightOffset_sec = 3600;
// Programmazione rapporto (invia alle 08:00)
const int REPORT_HOUR = 17;
const int REPORT_MINUTE = 32;
bool reportSentToday = false;
void setup() {
Serial.begin(115200);
delay(1000); // Stabilizzazione iniziale
// Connetti WiFi
Serial.print("Connessione a WiFi");
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\nConnessione fallita!");
ESP.restart();
return;
}
Serial.println("\nConnesso!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
delay(1000); // Attendi stabilizzazione WiFi
// Configura l'ora con tentativi
Serial.println("Sincronizzazione ora...");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// Attendi la sincronizzazione NTP
struct tm timeinfo;
int retry = 0;
while (!getLocalTime(&timeinfo) && retry < 10) {
Serial.print(".");
delay(1000);
retry++;
}
if (retry >= 10) {
Serial.println("\nSincronizzazione NTP fallita!");
} else {
Serial.println("\nOra sincronizzata!");
Serial.println(&timeinfo, "%Y-%m-%d %H:%M:%S");
}
emailSend.setEHLOCommand(true);
Serial.println("Setup completo");
}
void sendDailyReport(struct tm timeinfo);
void loop() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Ottenimento ora fallito");
delay(60000);
return;
}
// Stampa ora e stato correnti
char timeStr[30];
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
Serial.print("Ora corrente: ");
Serial.print(timeStr);
Serial.print(" | Prossimo rapporto alle: ");
Serial.print(REPORT_HOUR);
Serial.print(":");
Serial.print(REPORT_MINUTE < 10 ? "0" : "");
Serial.println(REPORT_MINUTE);
// Controlla se è ora di inviare il rapporto
if (timeinfo.tm_hour == REPORT_HOUR &&
timeinfo.tm_min == REPORT_MINUTE &&
!reportSentToday) {
sendDailyReport(timeinfo);
reportSentToday = true;
}
// Resetta il flag a mezzanotte
if (timeinfo.tm_hour == 0 && timeinfo.tm_min == 0) {
reportSentToday = false;
Serial.println("Flag rapporto resettato per nuovo giorno");
}
delay(60000); // Controlla ogni minuto
}
void sendDailyReport(struct tm timeinfo) {
Serial.println("Generazione rapporto giornaliero...");
char dateStr[30];
strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", &timeinfo);
EMailSender::EMailMessage message;
message.subject = String("Rapporto Giornaliero - ") + dateStr;
// Raccogli statistiche di sistema
String html = "<html><body style='font-family: Arial;'>"
"<h1>Rapporto Giornaliero ESP32</h1>"
"<h3>" + String(dateStr) + "</h3>"
"<table style='border-collapse: collapse; width: 100%;'>"
"<tr style='background: #4CAF50; color: white;'>"
"<th style='padding: 10px; border: 1px solid #ddd;'>Metrica</th>"
"<th style='padding: 10px; border: 1px solid #ddd;'>Valore</th>"
"</tr>"
"<tr><td style='padding: 8px; border: 1px solid #ddd;'>Uptime</td>"
"<td style='padding: 8px; border: 1px solid #ddd;'>" +
String(millis() / 86400000) + " giorni</td></tr>"
"<tr><td style='padding: 8px; border: 1px solid #ddd;'>Heap Libero</td>"
"<td style='padding: 8px; border: 1px solid #ddd;'>" +
String(ESP.getFreeHeap()) + " byte</td></tr>"
"<tr><td style='padding: 8px; border: 1px solid #ddd;'>Segnale WiFi</td>"
"<td style='padding: 8px; border: 1px solid #ddd;'>" +
String(WiFi.RSSI()) + " dBm</td></tr>"
"<tr><td style='padding: 8px; border: 1px solid #ddd;'>Indirizzo IP</td>"
"<td style='padding: 8px; border: 1px solid #ddd;'>" +
WiFi.localIP().toString() + "</td></tr>"
"</table>"
"<p style='color: #666; font-size: 12px; margin-top: 20px;'>"
"Rapporto automatico da ESP32</p>"
"</body></html>";
message.message = html;
message.mime = MIME_TEXT_HTML;
EMailSender::Response resp = emailSend.send("manager@example.com", message);
if (resp.status) {
Serial.println("✅ Rapporto giornaliero inviato!");
} else {
Serial.println("❌ Invio rapporto fallito: " + resp.desc);
}
}
Intestazioni e Dichiarazioni Globali
Questa sezione iniziale include le librerie necessarie e definisce costanti e variabili globali.
#include <WiFi.h>
#include <EMailSender.h>
#include <time.h>
#include <WiFi.h>: Include la libreria per la gestione della connessione Wi-Fi dell’ESP32.#include <EMailSender.h>: Include una libreria personalizzata per l’invio di email.#include <time.h>: Include la libreria per la gestione delle funzioni relative al tempo.
const char* ssid = "TUA_SSID";
const char* password = "TUA_PASSWORD";
ssidepassword: Queste costanti contengono le credenziali (nome e password) per la tua rete Wi-Fi. Devi sostituire i valori segnaposto.
// Impostazioni NTP
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0;
const int daylightOffset_sec = 3600;
- Impostazioni NTP: Queste costanti configurano il Network Time Protocol (NTP), utilizzato per ottenere l’ora corretta da internet.
ntpServer: L’indirizzo del server NTP.gmtOffset_sec: L’offset dal Greenwich Mean Time (GMT) in secondi.daylightOffset_sec: L’offset per l’ora legale (3600 secondi = 1 ora).
// Programmazione rapporto (invia alle 08:00)
const int REPORT_HOUR = 17;
const int REPORT_MINUTE = 32;
bool reportSentToday = false;
REPORT_HOUReREPORT_MINUTE: Queste costanti definiscono l’ora esatta (ora e minuto in formato 24 ore) in cui deve essere inviato il rapporto email giornaliero.reportSentToday: Questo è un flag booleano utilizzato per garantire che il rapporto venga inviato solo una volta al giorno. Viene impostato sutruedopo l’invio e resettato afalsea mezzanotte.

Funzione sendDailyReport()
Questa funzione è responsabile della creazione del contenuto dell’email e del suo invio.
- Genera Oggetto: Crea una riga di oggetto per l’email, come “Rapporto Giornaliero – 2025-10-09”.
- Crea Corpo HTML: Costruisce una stringa formattata in HTML per il corpo dell’email. Ciò consente un rapporto visivamente più accattivante con un titolo, una data e una tabella.
- Raccogli Dati di Sistema: La tabella nell’email contiene metriche chiave del sistema:
- Uptime: Da quanto tempo l’ESP32 è in esecuzione.
- Heap Libero: La quantità di memoria disponibile (RAM).
- Segnale WiFi: La potenza del segnale Wi-Fi (RSSI).
- Indirizzo IP: L’indirizzo IP corrente del dispositivo sulla rete.
- Invia Email: Utilizza il metodo
emailSend.send()della libreria per inviare l’email composta a un destinatario predefinito ("manager@example.com"). - Registra Stato: Stampa un messaggio di successo o fallimento sul monitor seriale in base al risultato del tentativo di invio.
Allegati Multipli

Ricorda di usare FFAT (Per File di Grandi Dimensioni).
EMailSender::FileDescriptior files[3];
files[0].filename = "documento.pdf";
files[0].url = "/docs/documento.pdf";
files[0].mime = "application/pdf";
files[0].encode64 = true;
files[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
files[1].filename = "immagine.png";
files[1].url = "/images/immagine.png";
files[1].mime = MIME_IMAGE_PNG;
files[1].encode64 = true;
files[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
files[2].filename = "dati.txt";
files[2].url = "/dati.txt";
files[2].mime = MIME_TEXT_PLAIN;
files[2].encode64 = false;
files[2].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
EMailSender::Attachments attachments;
attachments.number = 3;
attachments.fileDescriptor = files;
EMailSender::Response resp = emailSend.send("destinatario@example.com",
message,
attachments);
Allegati da SPIFFS/LittleFS/FFat (ESP32/ESP8266)
#include <SPIFFS.h>
// Inizializza SPIFFS
SPIFFS.begin();
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "config.json";
fileDescriptor.url = "/config.json";
fileDescriptor.mime = "application/json";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;
// O usa LittleFS
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_LITTLE_FS;
// O usa FFAT
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_FFAT;
Allegati da Stream
Puoi allegare dati da qualsiasi sorgente Stream (ad es. dati generati, stream di rete o implementazioni personalizzate di Stream). Questo è utile quando vuoi inviare contenuto dinamico senza salvarlo prima su un file system.
// Esempio: Crea uno Stream da dati dinamici
Stream* myDataStream = ...; // La tua implementazione di Stream
size_t dataSize = 1024; // Dimensione dei dati in byte
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "dati_sensore.csv";
fileDescriptor.mime = "text/csv";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_STREAM;
fileDescriptor.stream = myDataStream; // Puntatore allo Stream
fileDescriptor.streamSize = dataSize; // La dimensione è richiesta!
EMailSender::Attachments attachments;
attachments.number = 1;
attachments.fileDescriptor = &fileDescriptor;
EMailSender::Response resp = emailSend.send("destinatario@example.com",
message,
attachments);
Allegati da Stringa (Raccomandato per Contenuto Dinamico)
Il modo più semplice per allegare contenuto generato dinamicamente. Passa semplicemente una Stringa direttamente – non c’è bisogno di file system o wrapper di Stream!
// Esempio 1: allegato JSON
String jsonData = "{\"device\":\"ESP32\",\"temperature\":22.5,\"humidity\":65.3}";
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "dati_sensore.json";
fileDescriptor.mime = "application/json";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
fileDescriptor.content = jsonData; // ✅ Assegna semplicemente la Stringa!
EMailSender::Attachments attachments;
attachments.number = 1;
attachments.fileDescriptor = &fileDescriptor;
EMailSender::Response resp = emailSend.send("destinatario@example.com",
message,
attachments);
// Esempio 2: allegato CSV (compatibile con Excel)
String csvData = "Ora,Temperatura,Umidità\n";
csvData += "12:00,22.5,65.3\n";
csvData += "13:00,23.1,64.8\n";
csvData += "14:00,22.8,66.1\n";
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "letture.csv";
fileDescriptor.mime = "text/csv";
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
fileDescriptor.content = csvData; // ✅ Assegna semplicemente la Stringa!
// Esempio 3: allegati multipli da Stringa con diversi tipi MIME
String jsonData = "{\"device\":\"ESP32\",\"temp\":22.5,\"hum\":65.3}";
String csvData = "Sensore,Valore,Unità\nTemperatura,22.5,°C\nUmidità,65.3,%\n";
String xmlData = "<?xml version=\"1.0\"?><sensors><temp>22.5</temp><hum>65.3</hum></sensors>";
String txtData = "Dispositivo: ESP32\nTemperatura: 22.5°C\nUmidità: 65.3%\nStato: OK\n";
EMailSender::FileDescriptior files[4];
// Allegato JSON
files[0].filename = "dati.json";
files[0].mime = "application/json";
files[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
files[0].content = jsonData;
// Allegato CSV (compatibile con Excel)
files[1].filename = "dati.csv";
files[1].mime = "text/csv";
files[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
files[1].content = csvData;
// Allegato XML
files[2].filename = "config.xml";
files[2].mime = "application/xml";
files[2].storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
files[2].content = xmlData;
// Allegato di testo
files[3].filename = "rapporto.txt";
files[3].mime = "text/plain";
files[3].storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
files[3].content = txtData;
EMailSender::Attachments attachments;
attachments.number = 4;
attachments.fileDescriptor = files;
EMailSender::Response resp = emailSend.send("destinatario@example.com",
message,
attachments);
Migliori Pratiche per Allegati da Stringa
- Gestione della Memoria: Per contenuti di grandi dimensioni (>10KB), considera l’uso di Stream o archiviazione basata su file
- Tipi MIME: Specifica sempre il tipo MIME corretto per una gestione adeguata da parte dei client di posta elettronica
- Nomi dei File: Usa nomi di file descrittivi con estensioni appropriate (.json, .csv, .xml, .txt)
- Validazione del Contenuto: Assicurati che il contenuto della tua Stringa sia valido (JSON valido, formato CSV corretto, ecc.)
- Codifica Base64: Solitamente non necessaria per contenuti di testo; imposta
encode64 = false
Risoluzione dei Problemi Comuni
- “Errore: 220 -> …” o Timeout:
- Verifica che il cavo Ethernet sia collegato correttamente.
- Controlla che il server SMTP (
smtp-relay.brevo.com) e la porta (587) siano corretti. - Assicurati che il firewall della tua rete non blocchi la porta 587.
- “Errore: 535 -> Authentication failed”:
- Le tue credenziali (Login o Chiave SMTP) sono errate. Controlla due volte la chiave SMTP dalla tua dashboard di Brevo.
- Assicurati che il tuo indirizzo email mittente sia stato verificato in Brevo.
- Inizializzazione della Scheda SD Fallita:
- Controlla il cablaggio del tuo modulo per schede SD.
- Assicurati che il
SD_CS_PINsia corretto e non entri in conflitto con il pin CS dello Shield Ethernet (solitamente il pin 10).
Specifiche della Libreria
Piattaforme Supportate
| Piattaforma | WiFi | Ethernet | SSL/TLS | STARTTLS |
|---|---|---|---|---|
| ESP32 | ✅ | ✅ | ✅ | ✅ |
| ESP8266 | ✅ | ✅ | ✅ | ✅ |
| Arduino Mega/Uno | ❌ | ✅ | ❌ | ❌ |
| Arduino SAMD | ✅ | ✅ | ✅ | ✅ |
| STM32 | ❌ | ✅ | ✅ | ✅ |
| Raspberry Pi Pico (RP2040) | ✅ | ✅ | ✅ | ✅ |
IMPORTANTE – Arduino Mega/Uno e SSL/TLS:
Arduino Mega e Uno NON supportano SSL/TLS a causa di gravi limitazioni di RAM:
- Arduino Mega ha solo 8KB di RAM
- Arduino Uno ha solo 2KB di RAM
- BearSSL per SSL/TLS richiede almeno 24KB di RAM per i buffer di crittografia
Soluzioni alternative per Arduino Mega/Uno:
- Usa SMTP non sicuro (porta 25) – Funziona ma non è raccomandato
- Usa un relay SMTP locale – Configura un server locale che gestisca SSL
- Passa a ESP32/ESP8266 – Hanno più RAM e supporto nativo SSL/TLS
- Usa Arduino SAMD (MKR WiFi 1010) – Ha 32KB di RAM e supporta SSL/TLS
Gli esempi per Arduino Mega/Uno in questa libreria usano solo SMTP non sicuro!
Interfacce di Rete Supportate
- WiFi (ESP32/ESP8266) – WiFiClient / WiFiClientSecure
- WiFi (SAMD/MBED) – Libreria WiFiNINA
- Ethernet W5100/W5200/W5500 – Libreria Ethernet standard
- Ethernet ENC28J60 – Libreria UIPEthernet
- Ethernet con SSL – Wrapper SSLClient per connessioni sicure
Sistemi di Archiviazione Supportati
Archiviazione Interna (Flash del Microcontrollore)
- SPIFFS (ESP32, ESP8266)
- LittleFS (ESP32, ESP8266, RP2040)
- FFAT (ESP32)
- SPIFM (SPI Flash con Adafruit_SPIFlash)
Archiviazione Esterna (Schede SD/microSD)
- SD (Libreria SD standard)
- SdFat (Versione 1.x per RP2040/ESP8266)
- SdFat2 (Versione 2.x per piattaforme moderne)

Funzionalità della Libreria
Email HTML con Destinatari Multipli
EMailSender::EMailMessage message;
message.subject = "Test Email HTML";
message.message = "<h1>Ciao!</h1><p>Questa è un'email <b>HTML</b>.</p>";
message.mime = MIME_TEXT_HTML; // Imposta il tipo MIME su HTML
// Destinatari multipli
const char* recipients[] = {
"destinatario1@example.com",
"destinatario2@example.com",
"destinatario3@example.com"
};
EMailSender::Response resp = emailSend.send(recipients, 3, message);
Email con CC e BCC
// Array con indirizzi A, Cc e Ccn
const char* allRecipients[] = {
"a@example.com", // A (1)
"cc@example.com", // Cc (1)
"ccn@example.com" // Ccn (1)
};
// send(destinatari, numA, numCc, numCcn, messaggio)
EMailSender::Response resp = emailSend.send(allRecipients, 1, 1, 1, message);
Porta 587 (STARTTLS) – Raccomandato per Gmail
STARTTLS inizia con una connessione in chiaro e poi passa a una crittografata.
// Abilita SSLClient interno in EMailSenderKey.h
#define EMAIL_ENABLE_INTERNAL_SSLCLIENT
// Usa la porta 587
EMailSender emailSend("utente@gmail.com", "password_app",
"utente@gmail.com", "Nome Mittente",
"smtp.gmail.com", 587);
// Abilita EHLO (richiesto per STARTTLS)
emailSend.setEHLOCommand(true);
Porta 465 (SSL/TLS Implicito)
La connessione è crittografata fin dall’inizio.
// Usa WiFiClientSecure (ESP32/ESP8266)
EMailSender emailSend("utente@gmail.com", "password_app",
"utente@gmail.com", "Nome Mittente",
"smtp.gmail.com", 465);
// Nessuna configurazione aggiuntiva necessaria
Uso di SSLClient con Ethernet (Arduino/STM32)
Per schede senza supporto SSL nativo:
#define EMAIL_ENABLE_OPENSLAB_SSLCLIENT
// La libreria userà SSLClient basato su BearSSL
// per connessioni sicure su Ethernet
Funzionalità Avanzate
Metodi di Autenticazione Personalizzati
// Usa AUTH PLAIN (SASL)
emailSend.setSASLLogin(true);
// Usa CRAM-MD5 (solo ESP32)
emailSend.setCramMD5Login(true);
// Disabilita l'autenticazione (open relay)
emailSend.setUseAuth(false);
Configurazione EHLO
// Usa EHLO invece di HELO (raccomandato per server moderni)
emailSend.setEHLOCommand(true);
// Imposta un identificatore personalizzato per HELO/EHLO
emailSend.setPublicIpDescriptor("miodispositivo");
Email con Allegati da Scheda SD
#include <SD.h>
// Inizializza la scheda SD
SD.begin(SD_CS_PIN);
// Prepara l'allegato
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "foto.jpg";
fileDescriptor.url = "/foto.jpg"; // Percorso sulla scheda SD
fileDescriptor.mime = MIME_IMAGE_JPG;
fileDescriptor.encode64 = true; // Codifica in Base64
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
EMailSender::Attachments attachments;
attachments.number = 1;
attachments.fileDescriptor = &fileDescriptor;
// Invia email con allegato
EMailSender::Response resp = emailSend.send("destinatario@example.com",
message,
attachments);
Allegati Multipli
EMailSender::FileDescriptior files[3];
files[0].filename = "documento.pdf";
files[0].url = "/docs/documento.pdf";
files[0].mime = "application/pdf";
files[0].encode64 = true;
files[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
files[1].filename = "immagine.png";
files[1].url = "/images/immagine.png";
files[1].mime = MIME_IMAGE_PNG;
files[1].encode64 = true;
files[1].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
files[2].filename = "dati.txt";
files[2].url = "/dati.txt";
files[2].mime = MIME_TEXT_PLAIN;
files[2].encode64 = false;
files[2].storageType = EMailSender::EMAIL_STORAGE_TYPE_SD;
EMailSender::Attachments attachments;
attachments.number = 3;
attachments.fileDescriptor = files;
EMailSender::Response resp = emailSend.send("destinatario@example.com",
message,
attachments);
Allegati da SPIFFS/LittleFS/FFat (ESP32/ESP8266)
#include <SPIFFS.h>
// Inizializza SPIFFS
SPIFFS.begin();
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "config.json";
fileDescriptor.url = "/config.json";
fileDescriptor.mime = "application/json";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFFS;
// O usa LittleFS
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_LITTLE_FS;
// O usa FFAT
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_FFAT;
Tipo di archiviazione SPIFM
C’è anche il supporto per SPI Flash, ma è meglio fare riferimento al tutorial specifico.
// fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_SPIFM;
Tipo di archiviazione String o Stream
String jsonData = "{\"device\":\"ESP32\",\"temp\":22.5,\"hum\":65.3}";
EMailSender::FileDescriptior files[1];
// Allegato JSON
files[0].filename = "data.json";
files[0].mime = "application/json";
files[0].storageType = EMailSender::EMAIL_STORAGE_TYPE_STRING;
files[0].content = jsonData;
Stream* myDataStream = ...; // La tua implementazione di Stream
size_t dataSize = 1024; // Dimensione dei dati in byte
EMailSender::FileDescriptior fileDescriptor;
fileDescriptor.filename = "dati_sensore.csv";
fileDescriptor.mime = "text/csv";
fileDescriptor.encode64 = false;
fileDescriptor.storageType = EMailSender::EMAIL_STORAGE_TYPE_STREAM;
fileDescriptor.stream = myDataStream; // Puntatore allo Stream
fileDescriptor.streamSize = dataSize; // La dimensione è richiesta!
Tipi MIME Comuni per Allegati Stringa
| Tipo di File | Tipo MIME | Utilizzo |
|---|---|---|
| JSON | application/json | Dati API, letture sensori |
| CSV | text/csv | Dati compatibili con Excel |
| XML | application/xml | File di configurazione |
| Testo | text/plain | Log, report |
| HTML | text/html | Documenti formattati |
| JavaScript | application/javascript | File di codice |
Confronto Tipi di Archiviazione
| Tipo di Archiviazione | Ideale Per | Complessità | Uso Memoria |
|---|---|---|---|
EMAIL_STORAGE_TYPE_STRING | 📝 Contenuto testuale dinamico | ⭐ Molto Facile | Solo RAM |
EMAIL_STORAGE_TYPE_STREAM | 🔄 Sorgenti dati personalizzate | ⭐⭐ Medio | Streaming RAM |
EMAIL_STORAGE_TYPE_SD | 📁 File di grandi dimensioni | ⭐⭐ Medio | Scheda SD |
EMAIL_STORAGE_TYPE_SPIFFS | 🔧 Piccoli file di configurazione | ⭐⭐ Medio | Flash Interna |
EMAIL_STORAGE_TYPE_LITTLE_FS | 📊 File medi (ESP32/ESP8266) | ⭐⭐ Medio | Flash Interna |
EMAIL_STORAGE_TYPE_FFAT | 📈 File grandi (solo ESP32) | ⭐⭐ Medio | Flash Interna |
Configurazione Gmail
Per usare Gmail, hai bisogno di una Password per le App:
- Abilita l’Autenticazione a 2 Fattori sul tuo account Google
- Vai su Password per le app di Google
- Genera una nuova password per le app
- Usa questa password di 16 caratteri nel tuo codice
Impostazioni Gmail:
- Server SMTP:
smtp.gmail.com - Porta:
587(STARTTLS) o465(SSL/TLS) - Autenticazione: Richiesta
Su ESP32 ed ESP8266 puoi abilitare EMAIL_ENABLE_INTERNAL_SSLCLIENT nel file EMailSenderKey.h per usare STARTTLS sulla porta 587
// If you want to ENABLE the internal SSLClient wrapper (needed for STARTTLS on port 587)
// instead of relying solely on the native secure client (e.g., WiFiClientSecure for 465),
// uncomment the following define. Enabling it increases flash and RAM usage
// but provides STARTTLS support on non-secure base clients.
//#define EMAIL_ENABLE_INTERNAL_SSLCLIENT
Per la porta 465 e SSL/TLS, ESP32 ed ESP8266 non necessitano di librerie aggiuntive, ma per usarle con STM32 ed Ethernet (o altri dispositivi simili), puoi abilitare EMAIL_ENABLE_OPENSLAB_SSLCLIENT, un’implementazione leggera di SSL.
// Enable integration with OPEnSLab-OSU SSLClient (BearSSL) per AVR/Ethernet o schede che ne hanno bisogno.
// Usa questo backend solo se hai INSTALLATO la libreria esterna "SSLClient" (OPEnSLab-OSU).
// STARTTLS (porta 587) NON è supportato da questo backend; è pensato per TLS implicito (465) su Client non-SSL.
// Di default DISABILITATO: abilitalo nel tuo sketch o nelle build flags definendo
// - EMAIL_ENABLE_EXTERNAL_SSLCLIENT_OPENSLAB (preferito) oppure
// - EMAIL_ENABLE_OPENSLAB_SSLCLIENT
// #define EMAIL_ENABLE_OPENSLAB_SSLCLIENT
Riferimento API
Costruttore
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* name_from);
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);
Metodi di Configurazione
void setSMTPServer(const char* smtp_server);
void setSMTPPort(uint16_t smtp_port);
void setEMailLogin(const char* email_login);
void setEMailFrom(const char* email_from);
void setNameFrom(const char* name_from);
void setEMailPassword(const char* email_password);
void setUseAuth(bool useAuth);
void setEHLOCommand(bool useEHLO);
void setSASLLogin(bool isSASLLogin);
void setCramMD5Login(bool onoff); // Solo ESP32
void setPublicIpDescriptor(const char* descriptor);
void setAdditionalResponseLineOnConnection(uint8_t numLines);
void setAdditionalResponseLineOnHELO(uint8_t numLines);
Metodi di Invio
// Destinatario singolo
Response send(const char* to, EMailMessage &email, Attachments att = {0, 0});
Response send(String to, EMailMessage &email, Attachments att = {0, 0});
// Destinatari multipli (Solo A)
Response send(const char* to[], byte sizeOfTo, EMailMessage &email, Attachments att = {0, 0});
Response send(String to[], byte sizeOfTo, EMailMessage &email, Attachments att = {0, 0});
// Destinatari multipli con Cc
Response send(const char* to[], byte sizeOfTo, byte sizeOfCc, EMailMessage &email, Attachments att = {0, 0});
// Destinatari multipli con Cc e Ccn
Response send(const char* to[], byte sizeOfTo, byte sizeOfCc, byte sizeOfCCn, EMailMessage &email, Attachments att = {0, 0});
Strutture Dati
// Messaggio Email
struct EMailMessage {
String mime = "text/html"; // o "text/plain"
String subject;
String message;
};
// Descrittore File per Allegati
struct FileDescriptior {
StorageType storageType = EMAIL_STORAGE_TYPE_SD;
String mime;
bool encode64 = false;
String filename;
String url; // Percorso del file
};
// Allegati
struct Attachments {
byte number;
FileDescriptior *fileDescriptor;
};
// Risposta
struct Response {
String code;
String desc;
bool status = false;
};
Tipi di Archiviazione
enum StorageType {
EMAIL_STORAGE_TYPE_SPIFFS,
EMAIL_STORAGE_TYPE_LITTLE_FS,
EMAIL_STORAGE_TYPE_FFAT,
EMAIL_STORAGE_TYPE_SPIFM,
EMAIL_STORAGE_TYPE_SD
};
Tipi MIME
Costanti predefinite per i tipi MIME:
MIME_TEXT_HTML // "text/html"
MIME_TEXT_PLAIN // "text/plain"
MIME_IMAGE_JPG // "image/jpg"
MIME_IMAGE_PNG // "image/png"
File di Configurazione (EMailSenderKey.h)
La libreria usa un file di configurazione per abilitare/disabilitare le funzionalità:
// Abilita il supporto STARTTLS con SSLClient interno (ESP32/ESP8266)
#define EMAIL_ENABLE_INTERNAL_SSLCLIENT
// Abilita OpenSLab SSLClient per shield Ethernet (Arduino/STM32)
#define EMAIL_ENABLE_OPENSLAB_SSLCLIENT
// Abilita il supporto per gli allegati
#define ENABLE_ATTACHMENTS
// Abilita la gestione dell'header della data
#define MANAGE_DATE_HEADER
// Tipo di rete (rilevato automaticamente in base alla piattaforma)
// EMAIL_NETWORK_TYPE può essere:
// - NETWORK_ESP8266 (ESP8266 WiFi)
// - NETWORK_ESP32 (ESP32 WiFi)
// - NETWORK_W5100 (Ethernet W5100/W5200/W5500)
// - NETWORK_ENC28J60 (Ethernet ENC28J60)
// - NETWORK_WiFiNINA (SAMD/Arduino WiFiNINA)
// - ecc.
// Tipi di archiviazione
// INTERNAL_STORAGE può essere: STORAGE_SPIFFS, STORAGE_LITTLEFS, STORAGE_FFAT
// EXTERNAL_STORAGE può essere: STORAGE_SD, STORAGE_SDFAT2
Modalità Debug
Abilita il debug decommentando in EMailSenderKey.h:
#define EMAIL_SENDER_DEBUG
#define DEBUG_PRINTER Serial
Questo stamperà la comunicazione SMTP dettagliata sul Monitor Seriale.
Grazie
- ESP32: piedinatura, specifiche e configurazione dell’Arduino IDE
- ESP32: fileSystem integrato SPIFFS
- ESP32: gestire più seriali e logging per il debug
- ESP32 risparmio energetico pratico
- ESP32 risparmio energetico pratico: gestire WiFi e CPU
- ESP32 risparmio energetico pratico: modem e light sleep
- ESP32 risparmio energetico pratico: deep sleep e ibernazione
- ESP32 risparmio energetico pratico: preservare dati al riavvio, sveglia a tempo e tramite tocco
- ESP32 risparmio energetico pratico: sveglia esterna e da ULP
- ESP32 risparmio energetico pratico: sveglia da UART e GPIO
- ESP32: filesystem integrato LittleFS
- ESP32: filesystem integrato FFat (Fat/exFAT)
- ESP32-wroom-32
- ESP32-CAM
- ESP32: ethernet w5500 con chiamate standard (HTTP) e SSL (HTTPS)
- ESP32: ethernet enc28j60 con chiamate standard (HTTP) e SSL (HTTPS)
- Come usare la scheda SD con l’esp32
- esp32 e esp8266: file system FAT su memoria SPI flash esterna
- Gestione aggiornamenti firmware e OTA
- Gestione del firmware
- Aggiornamento OTA con Arduino IDE
- Aggiornamento OTA con browser web
- Aggiornamenti automatici OTA da un server HTTP
- Aggiornamento del firmware non standard
- Integrare LAN8720 con ESP32 per la connettività Ethernet con plain (HTTP) e SSL (HTTPS)
- Collegare l’EByte E70 (CC1310) ai dispositivi ESP32 c3/s3 ed un semplice sketch di esempio
- ESP32-C3: piedinatura, specifiche e configurazione dell’IDE Arduino
- Integrazione del modulo W5500 su ESP32 con Core 3: supporto nativo ai protocolli Ethernet con SSL e altre funzionalità
- Integrazione del modulo LAN8720 su ESP32 con Core 3: supporto nativo del protocollo Ethernet con SSL e altre funzionalità.
- Dallas DS18B20
- Guida all’I2C su ESP32: comunicazione con dispositivi eterogenei 5v 3.3v, gestione interfacce aggiuntive
- Display
- Guida Completa: Come Usare un Display ILI9341 con la Libreria TFT_eSPI
- Come integrare la funzionalità touch screen nel display TFT ILI9341
- Display eInk SSD1683 con GxEPD e ESP32 (e HMI CrowPanel 4,2″): nozioni di base e configurazione
- Display e-ink SSD1683 con GxEPD e ESP32 (e CrowPanel 4.2″ HMI): font, forme e immagini



