Envoyer un mail avec un ESP32 (testé avec Gmail)

Un petit tuto rapide sur l’utilisation de la bibliothèque ESP-Mail-Client, client mail pour ESP32 et ESP8266.
Je viens de tester et ça a marché en moins de 5 minutes !

Après installation de la bibliothèque, j’ai testé deux exemples :

  • Send_Text
  • Send_HTML

Voici les lignes à configurer :

Connexion à votre box :

#define WIFI_SSID "****"
#define WIFI_PASSWORD "****"

Choix de Gmail :

#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465

Votre compte Gmail :

#define AUTHOR_EMAIL "xxx@gmail.com"
#define AUTHOR_PASSWORD "****"

Définition de la session : rien à changer, on peut laisser ceci aussi :

  session.login.user_domain = "mydomain.net";

Ce paramètre peut aussi être remplacé par l’adresse IP de l’ESPxx, mais ça marche aussi comme ça.

Le destinataire, le sujet :

  message.sender.name = "ESP Mail";
  message.sender.email = AUTHOR_EMAIL;
  message.subject = "Test sending html Email";
  message.addRecipient("un nom ici", "xxxx@xxxx.fr");
  • senser.name : le nom qui apparaîtra dans le mail reçu pour l’envoyeur
  • subject : le sujet de votre mail
  • addRecipient prend 2 paramètres (chaines de caractères) : un alias et l’adresse du destinataire. Je n’ai pas essayé d’envoyer à plusieurs destinataires, mais ce doit être possible avec plusieurs fois cette ligne

Pour un contenu complexe en HTML, on peut créer une String qui contient le code HTML, puis la convertir en char* :

   message.html.content = myString.c_str();

J’ai testé avec des caractères français (ç, é, etc), ça fonctionne en mettant

  message.html.charSet = "utf-8";

C’est tout, rien à changer dans le reste.
Le code est assez verbeux, on voit toutes les étapes dans la console :

Logging in…

C: send smtp command, AUTH PLAIN
C: xxxx@gmail.com
C: xxxx@gmail.com *********
< S: 235 2.7.0 Accepted

Sending Email…

C: send Email

Sending message header…

C: send message header
< S: 250 2.1.0 OK t14sm24015938wru.64 - gsmtp
< S: 250 2.1.5 OK t14sm24015938wru.64 - gsmtp

Sending message body…

C: send message body
< S: 354 Go ahead t14sm24015938wru.64 - gsmtp

Finishing the message sending…

C: Finish the message sending
< S: 250 2.0.0 OK 1615282810 t14sm24015938wru.64 - gsmtp

Closing the session…

C: terminate the SMTP session
< S: 221 2.0.0 closing connection t14sm24015938wru.64 - gsmtp

Message sent successfully

C: Message sent successfully


Message sent success: 1
Message sent failled: 0

Message No: 1
Status: success
Date/Time: 1970/1/1 0:0:3
Recipient: xxxx@yyy.fr
Subject: Test sending html Email

C: cleaning SSL connection

Voilà, à vous de jouer !

EDIT : il sera peut-être nécessaire de changer un paramètre sur votre compte Gmail, pour autoriser “les applications tierces” à l’utiliser. Voir ici
Je crois qu’il est possible aussi de définir un mot de passe spécifique (app password) pour une application pour se connecter à votre Gmail. Ca permettra de ne pas laisser votre pass en clair dans le source du code Arduino.

Bizarre je viens d y passer 3/4 d'heure et ca ne marche toujours pas ;D ;D.

Mon session.login.user_domain ne passe pas, il faut bien le mettre avant le void setup ?

Si tu testes d'abord les exemples de la bibliothèque, il est dans le setup
J'ai demandé à l'auteur ce qu'on devait y mettre, il m'a dit soit le nom de domaine soit l'IP externe de l'ESP. Pour moi ça fonctionne très bien en laissant

  session.login.user_domain = "mydomain.net";

@lesept
Bonsoir,
Merci pour ce mini tuto.
Comme exposé dans un autre topic, je n'ai aucune difficulté à faire fonctionner l'envoi de mail format texte ou même en html grâce à cette bibliothèque.
Par contre je dois intégrer cette application d'envoi de mail dans un sketch beaucoup plus complet, et le fait que tout s'exécute dans le Setup + une fonction ne peut pas me convenir, du fait notamment du besoin d'intégrer dans la String de contenu des valeurs de variables, mais aussi de déclencher l'envoi de mail en fonction de certaines variables...

C'est un programme de démonstration. Le but n'est pas de faire une application complète. Il faut analyser ce programme, le comprendre et extraire la partie qui t'intéresse pour l'intégrer dans ton application.
Si le code qui assure l'envoi du mail doit être placé dans une fonction il te suffit de copier le morceau de code que tu veux utiliser dans ladite fonction.

C'est bien là le problème car ce code très "verbeux" dépasse largement mes capacités de compréhension car en plus :

Si le code qui assure l'envoi du mail doit être placé dans une fonction il te suffit de copier le morceau de code que tu veux utiliser dans ladite fonction.

ce n'est pas le cas ...

bonsoir lesept,
ça fait 3 heures que je bataille,
j'ai bien utilisé ton code et modifié les paramètres idoine, mais ca plante toujours

22:54:14.175 -> < S: 535-5.7.8 Username and Password not accepted. Learn more at

apparemment il ne reconnais pas mes identifiants...
j'ai bien modifié le paramètre pour les application tierces.. rien à faire

le code brut:




/**
 * This example will send the Email in plain text version.
 * 
 * Created by K. Suwatchai (Mobizt)
 * 
 * Email: suwatchai@outlook.com
 * 
 * Github: https://github.com/mobizt/ESP-Mail-Client
 * 
 * Copyright (c) 2021 mobizt
 *
*/

//To use send Email for Gmail to port 465 (SSL), less secure app option should be enabled. https://myaccount.google.com/lesssecureapps?pli=1

#include <Arduino.h>
#if defined(ESP32)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <ESP_Mail_Client.h>

#define WIFI_SSID "XXXXXXXXXXX"    
#define WIFI_PASSWORD "XXXXXXXXXXXXXXXXX"

 

/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com
 * For yahoo mail, log in to your yahoo mail in web browser and generate app password by go to
 * https://login.yahoo.com/account/security/app-passwords/add/confirm?src=noSrc
 * and use the app password as password with your yahoo mail account to login.
 * The google app password signin is also available https://support.google.com/mail/answer/185833?hl=en
*/
//#define SMTP_HOST "<host>"
#define SMTP_HOST "smtp.gmail.com"

/** The smtp port e.g. 
 * 25  or esp_mail_smtp_port_25
 * 465 or esp_mail_smtp_port_465
 * 587 or esp_mail_smtp_port_587
*/
//#define SMTP_PORT esp_mail_smtp_port_587
  #define SMTP_PORT 465
/* The log in credentials */
#define AUTHOR_EMAIL "XXXXXXXX@gmail.com"
#define AUTHOR_PASSWORD "XXXXXXXXXXX"

 


 
/* The SMTP Session object used for Email sending */
SMTPSession smtp;

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);

const char rootCACert[] PROGMEM = "-----BEGIN CERTIFICATE-----\n"
                                  "-----END CERTIFICATE-----\n";

void setup()
{

  Serial.begin(115200);

#if defined(ARDUINO_ARCH_SAMD)
  while (!Serial)
    ;
  Serial.println();
  Serial.println("**** Custom built WiFiNINA firmware need to be installed.****\nTo install firmware, read the instruction here, https://github.com/mobizt/ESP-Mail-Client#install-custom-built-wifinina-firmware");

#endif

  Serial.println();

  Serial.print("Connecting to AP");

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(200);
  }

  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  /** Enable the debug via Serial port
   * none debug or 0
   * basic debug or 1
   * 
   * Debug port can be changed via ESP_MAIL_DEFAULT_DEBUG_PORT in ESP_Mail_FS.h
  */
  smtp.debug(1);

  /* Set the callback function to get the sending results */
  smtp.callback(smtpCallback);

  /* Declare the session config data */
  ESP_Mail_Session session;

  /** ########################################################
   * Some properties of SMTPSession data and parameters pass to 
   * SMTP_Message class accept the pointer to constant char
   * i.e. const char*. 
   * 
   * You may assign a string literal to that properties or function 
   * like below example.
   *   
   * session.login.user_domain = "mydomain.net";
   * session.login.user_domain = String("mydomain.net").c_str();
   * 
   * or
   * 
   * String doman = "mydomain.net";
   * session.login.user_domain = domain.c_str();
   * 
   * And
   * 
   * String name = "Jack " + String("dawson");
   * String email = "jack_dawson" + String(123) + "@mail.com";
   * 
   * message.addRecipient(name.c_str(), email.c_str());
   * 
   * message.addHeader(String("Message-ID: <abcde.fghij@gmail.com>").c_str());
   * 
   * or
   * 
   * String header = "Message-ID: <abcde.fghij@gmail.com>";
   * message.addHeader(header.c_str());
   * 
   * ###########################################################
  */

  /* Set the session config */
  session.server.host_name = SMTP_HOST;
  session.server.port = SMTP_PORT;
  session.login.email = AUTHOR_EMAIL;
  session.login.password = AUTHOR_PASSWORD;
  session.login.user_domain = "mydomain.net";

  /* Declare the message class */
  SMTP_Message message;

  /* Set the message headers */
  message.sender.name = "ESP Mail";
  message.sender.email = AUTHOR_EMAIL;
  message.subject = "Test sending plain text Email";
  message.addRecipient("Armindo SIMAO", "armindo.simao@wanadoo.fr");

  String textMsg = "This is simple plain text message";
  message.text.content = textMsg.c_str();

  /** The Plain text message character set e.g.
   * us-ascii
   * utf-8
   * utf-7
   * The default value is utf-8
  */
 // message.text.charSet = "us-ascii";

  message.html.charSet = "utf-8";

  /** The content transfer encoding e.g.
   * enc_7bit or "7bit" (not encoded)
   * enc_qp or "quoted-printable" (encoded)
   * enc_base64 or "base64" (encoded)
   * enc_binary or "binary" (not encoded)
   * enc_8bit or "8bit" (not encoded)
   * The default value is "7bit"
  */
  message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;


  //If this is a reply message
  //message.in_reply_to = "<parent message id>";
  //message.references = "<parent references> <parent message id>";

  /** The message priority
   * esp_mail_smtp_priority_high or 1
   * esp_mail_smtp_priority_normal or 3
   * esp_mail_smtp_priority_low or 5
   * The default value is esp_mail_smtp_priority_low
  */
  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;



  //message.response.reply_to = "someone@somemail.com";
  //message.response.return_path = "someone@somemail.com";

  /** The Delivery Status Notifications e.g.
   * esp_mail_smtp_notify_never
   * esp_mail_smtp_notify_success
   * esp_mail_smtp_notify_failure
   * esp_mail_smtp_notify_delay
   * The default value is esp_mail_smtp_notify_never
  */
  //message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

  /* Set the custom message header */
  message.addHeader("Message-ID: <abcde.fghij@gmail.com>");

  //For Root CA certificate verification (ESP8266 and ESP32 only)
  //session.certificate.cert_data = rootCACert;
  //or
  //session.certificate.cert_file = "/path/to/der/file";
  //session.certificate.cert_file_storage_type = esp_mail_file_storage_type_flash; // esp_mail_file_storage_type_sd
  //session.certificate.verify = true;

  //The WiFiNINA firmware the Root CA certification can be added via the option in Firmware update tool in Arduino IDE

  /* Connect to server with the session config */
  if (!smtp.connect(&session))
    return;

  /* Start sending Email and close the session */
  if (!MailClient.sendMail(&smtp, &message))
    Serial.println("Error sending Email, " + smtp.errorReason());

  //to clear sending result log
  //smtp.sendingResult.clear();

  ESP_MAIL_PRINTF("Free Heap: %d\n", MailClient.getFreeHeap());
}

void loop()
{
}

/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status)
{
  /* Print the current status */
  Serial.println(status.info());

  /* Print the sending result */
  if (status.success())
  {
    Serial.println("----------------");
    ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());
    ESP_MAIL_PRINTF("Message sent failled: %d\n", status.failedCount());
    Serial.println("----------------\n");
    struct tm dt;

    for (size_t i = 0; i < smtp.sendingResult.size(); i++)
    {
      /* Get the result item */
      SMTP_Result result = smtp.sendingResult.getItem(i);
      time_t ts = (time_t)result.timestamp;
      localtime_r(&ts, &dt);

      ESP_MAIL_PRINTF("Message No: %d\n", i + 1);
      ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");
      ESP_MAIL_PRINTF("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);
      ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients);
      ESP_MAIL_PRINTF("Subject: %s\n", result.subject);
    }
    Serial.println("----------------\n");

    //You need to clear sending result as the memory usage will grow up as it keeps the status, timstamp and
    //pointer to const char of recipients and subject that user assigned to the SMTP_Message object.

    //Because of pointer to const char that stores instead of dynamic string, the subject and recipients value can be
    //a garbage string (pointer points to undefind location) as SMTP_Message was declared as local variable or the value changed.

    //smtp.sendingResult.clear();
  }
}
 

LE RESULTAT:


22:54:13.847 -> SMTP server connected, wait for greeting...
22:54:13.847 -> < S: 220 smtp.gmail.com ESMTP w14sm9028862wro.8 - gsmtp
22:54:13.847 -> 
22:54:13.847 -> Sending greeting response...
22:54:13.847 -> > C: send smtp command, HELO
22:54:13.893 -> < S: 250-smtp.gmail.com at your service, [XXXXXXXXXX] (modifie)
22:54:13.893 -> < S: 250-SIZE 35882577
22:54:13.893 -> < S: 250-8BITMIME
22:54:13.893 -> < S: 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
22:54:13.940 -> < S: 250-ENHANCEDSTATUSCODES
22:54:13.940 -> < S: 250-PIPELINING
22:54:13.940 -> < S: 250-CHUNKING
22:54:13.940 -> < S: 250 SMTPUTF8
22:54:13.940 -> 
22:54:13.940 -> Logging in...
22:54:13.940 -> > C: send smtp command, AUTH PLAIN
22:54:13.940 -> > C: XXXXXXXXXX@gmail.com  // (modifié)
22:54:13.940 -> > C: XXXXXXXXXX@gmail.com ************
22:54:14.175 -> < S: 535-5.7.8 Username and Password not accepted. Learn more at
22:54:14.175 -> < S: 535 5.7.8  https://support.google.com/mail/?p=BadCredentials w14sm9028862wro.8 - gsmtp
22:54:14.175 -> Error, authentication failed
22:54:14.175 -> > E: authentication failed
22:54:14.175 -> > C: cleaning SSL connection

merci

Bonsoir Arzou
Q ?

excuse, le msg est parti alors que j’étais en train de l’écrire
tu connaitrais les paramètres à modifier pour une bal Orange?..

Bonjour Arzou. As-tu bien autorisé les applications tierces dans Gmail, comme je l'indique dans mon tuto, à la fin ?

Pour Orange, je n'ai pas testé. Je n'ai pas de compte mail Orange, je suis chez Free, mais je n'ai pas testé avec autre chose que Gmail.

A priori, il faut modifier le SMTP HOST et le port. Tu peux certainement les trouver dans ton logiciel de mail sur ton PC.

Après recherche, je dirais :

Merci lesept,
Oui, j'ai bien modifié l'autorisation ...rien a faire.
Pour orange j'ai essaye avec ces paramètres idem..ca ne passe pas :thinking:

As-tu essayé les 3 ports cités dans ton code ?

Bizarre, j'ai réussi à le faire marcher en 5 minutes...
Voici une autre bibliothèque, un exemple de code pour ESP32 est donné vers le milieu de la page :

/*
 * EMailSender library for Arduino, esp8266 and esp32
 * Simple esp32 Gmail send example
 *
 * https://www.mischianti.org/category/my-libraries/emailsender-send-email-with-attachments/
 *
 */
 
#include "Arduino.h"
#include <EMailSender.h>
#include <WiFi.h>
 
const char* ssid = "<YOUR-SSID>";
const char* password = "<YOUR-PASSWD>";
 
uint8_t connection_state = 0;
uint16_t reconnect_interval = 10000;
 
EMailSender emailSend("account_login@gmail.com", "<YOUR-GMAIL-PASSWD>");
 
uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
    static uint16_t attempt = 0;
    Serial.print("Connecting to ");
    if(nSSID) {
        WiFi.begin(nSSID, nPassword);
        Serial.println(nSSID);
    }
 
    uint8_t i = 0;
    while(WiFi.status()!= WL_CONNECTED && 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("receive_email@gmail.com", message);
 
    Serial.println("Sending status: ");
 
    Serial.println(resp.status);
    Serial.println(resp.code);
    Serial.println(resp.desc);
}
 
void loop()
{
 
}

(j'ai pas testé) :stuck_out_tongue:

Bonjour lesept !

finalement c’était l'option sur gmail qui ne fonctionnait pas, il ne mémorisait pas "autorisation application moins sécurisées ", c'est reglé

du coup tes 2 sketchs fonctionnent!
Merci

Cool ! :smiley:

Bonjour,

Je sais envoyer un courriel avec gmail en revanche j'ignore comment y joindre un fichier stocké sur carte sd
Un lien ?
Merci d'avance
fr

Les deux biblis que je propose (messages 1 & 14) permettent d'envoyer des pièces jointes