Learn how to use an SMTP server with the ESP32 send emails. We’ll show you how to send a simple email with HTML or plain text, as well as how to send images and files as attachments (.txt). The Arduino IDE will be used to programme the ESP32 board.

Introducing SMTP Servers

SMTP means Simple Mail Transfer Protocol and it is an internet standard for email transmission. To send emails using an ESP32, you need to connect it to an SMTP Server.

ESP Mail Client Library

To send emails with the ESP32, we’ll use the ESP-Mail-Client library. This library allows the ESP32 to send and receive emails with or without attachments via SMTP and IMAP servers.

In this tutorial, we’ll use SMTP to send an email with and without attachments. As an example, we’ll send an image (.png) and a text (.txt) file. The files sent via email can be saved in the ESP32 Filesystem (SPIFFS) or a microSD card

Installing the ESP-Mail-Client Library

Before proceeding with this tutorial, you need to install the ESP-Mail-Client library. This library is not available to install through the Arduino IDE Library Manager. Follow the next steps to install the library:

  1. Click here to download ESP-Mail-Client library .zip folder.
  2. In your Arduino IDE, go to Sketch > Include Library > Add .ZIP Library.
  3. Select the .zip file you’ve just downloaded.

Then, if you go to File > Examples > ESP-Mail-Client, we’ll find several examples that you can try. 

Sender Email (New Account)

To send the emails to your main personal email address, we propose starting a new email account. Sending emails with ESP32 should not be done with your primary personal email. You may be banned or have your account temporarily suspended if something goes wrong with your code or if you make too many requests by accident.

We’ll send the emails from a newly formed Gmail.com account, but you can use any email service. It is perfectly acceptable for the recipient email to be your personal email address.

Create a Sender Email Account

Create a new email account for sending emails with the ESP32. If you want to use a Gmail account, go to this link to create a new one.

Allow less secure apps

Allow less secure apps to get access to this new Gmail account, so that you’re able to send emails. You can open this link to go to that menu.

Gmail SMTP Server Settings

If you’re using a Gmail account, these are the SMTP Server details:

  • SMTP Server: smtp.gmail.com
  • SMTP username: Complete Gmail address
  • SMTP password: Your Gmail password
  • SMTP port (TLS): 587
  • SMTP port (SSL): 465
  • SMTP TLS/SSL required: yes

Outlook SMTP Server Settings

For Outlook accounts, these are the SMTP Server settings:

  • SMTP Server: smtp.office365.com
  • SMTP Username: Complete Outlook email address
  • SMTP Password: Your Outlook password
  • SMTP Port: 587
  • SMTP TLS/SSL Required: Yes

Live or Hotmail SMTP Server Settings

For Live or Hotmail accounts, these are the SMTP Server settings:

  • SMTP Server: smtp.live.com
  • SMTP Username: Complete Live/Hotmail email address
  • SMTP Password: Your Windows Live Hotmail password
  • SMTP Port: 587
  • SMTP TLS/SSL Required: Yes

If you’re using another email provider, you need to search for its SMTP Server settings. Now, you have everything ready to start sending emails with your ESP32.

Code

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

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

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

/* The sign in credentials */
#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_PASS"

/* Recipient's email*/
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

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

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

void setup(){
  Serial.begin(115200);
  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
  */
  smtp.debug(1);

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

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

  /* 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 = "";

  /* Declare the message class */
  SMTP_Message message;

  /* Set the message headers */
  message.sender.name = "ESP";
  message.sender.email = AUTHOR_EMAIL;
  message.subject = "ESP Test Email";
  message.addRecipient("Sara", RECIPIENT_EMAIL);

  /*Send HTML message*/
  String htmlMsg = "<div style=\"color:#2f4468;\"><h1>Hello World!</h1><p>- Sent from ESP board</p></div>";
  message.html.content = htmlMsg.c_str();
  message.html.content = htmlMsg.c_str();
  message.text.charSet = "us-ascii";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

  /*
  //Send raw text message
  String textMsg = "Hello World! - Sent from ESP board";
  message.text.content = textMsg.c_str();
  message.text.charSet = "us-ascii";
  message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
  
  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
  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>");

  /* 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());
}

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

How the Code Works

This code is adapted from an example provided by the library. 

First, insert your network credentials in the following lines:

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"

#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

Insert your SMTP server settings. If you’re using a Gmail account to send the emails, these are the settings:

#define SMTP_HOST "smtp.gmail.com"

#define SMTP_PORT 465

Insert the sender email sign in credentials (complete email and password)

#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"

#define AUTHOR_PASSWORD "YOUR_EMAIL_PASS"

Insert the recipient email:

#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"

Set the message headers in the following lines in the setup()—sender name, sender email, email subject, and the recipient name and email:

/* Set the message headers */

message.sender.name = "ESP";

message.sender.email = AUTHOR_EMAIL;

message.subject = "ESP Test Email";

message.addRecipient("Sara", RECIPIENT_EMAIL);

In the following lines, set the content of the message (raw text) in the textMsg variable:

/Send raw text message

String textMsg = "Hello World - Sent from ESP board";

message.text.content = textMsg.c_str();

message.text.charSet = "us-ascii";

message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;

If you want to send HTML text instead, uncomment the following lines— you should insert your HTML text in the htmlMsg variable.

/*Send HTML message*/

/*String htmlMsg = "<div style=\"color:#2f4468;\"><h1>Hello World!</h1><p>- Sent from ESP board</p></div>";

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

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

message.text.charSet = "us-ascii";

message.html.transfer_encoding = Content_Transfer_Encoding::enc_7bit;*/

Finally, the following lines send the message:

if (!MailClient.sendMail(&smtp, &message))

  Serial.println("Error sending Email, " + smtp.errorReason());

Demonstration

Upload the code to your ESP32. After uploading, open the Serial Monitor at a baud rate of 115200. Press the ESP32 Reset button.

If everything went as expected you should get a similar message in the Serial Monitor.

Send Attachments via Email with ESP32 (Arduino IDE)

We’ll show you how to send attachments in your ESP32-based emails in this section. We’ll show you how to send.txt or.jpg files. This can be used to deliver a.txt file containing sensor readings from the previous few hours or a snapshot taken with an ESP32-CAM.

For this tutorial, the files to be sent should be saved on the ESP32 filesystem (SPIFFS).

Upload files to SPIFFS

To send files via email, these should be saved on the ESP32 filesystem (SPIFFS). We’ll upload a picture and a .txt file to the ESP32 SPIFFS using the ESP32 Filesystem Uploader plugin for Arduino IDE. Follow the next tutorial to install the plugin if you don’t have it installed yet:

Create a new Arduino sketch and save it. Go to Sketch > Show Sketch folder. Inside the Arduino sketch folder, create a folder called data. Move a .jpg file and .txt file to your data folder.

After moving the files to the data folder, in your Arduino IDE, go to Tools > ESP32 Sketch Data Upload and wait for the files to be uploaded.

You should get a success message on the debugging window. If the files were successfully uploaded, move on to the next section.

Code

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

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

#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 465

/* The log in credentials */
#define AUTHOR_EMAIL "YOUR_EMAIL@XXXX.com"
#define AUTHOR_PASSWORD "YOUR_EMAIL_PASS"

/* Recipient's email*/
#define RECIPIENT_EMAIL "RECIPIENTE_EMAIL@XXXX.com"
/* The SMTP Session object used for Email sending */

SMTPSession smtp;

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

void setup(){
  Serial.begin(115200);
  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();

  if (!SPIFFS.begin(true)) {
    Serial.println("An error has occurred while mounting SPIFFS");
  }
  else{
    Serial.println("SPIFFS mounted successfully");
  }

  /** Enable the debug via Serial port
   * none debug or 0
   * basic debug or 1
  */
  smtp.debug(1);

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

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

  /* 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;

  /* Enable the chunked data transfer with pipelining for large message if server supported */
  message.enable.chunking = true;

  /* Set the message headers */
  message.sender.name = "ESP Mail";
  message.sender.email = AUTHOR_EMAIL;

  message.subject = "Test sending Email with attachments and inline images from SD card and Flash";
  message.addRecipient("Sara", RECIPIENT_EMAIL);

  /** Two alternative content versions are sending in this example e.g. plain text and html */
  String htmlMsg = "This message contains attachments: image and text file.";
  message.html.content = htmlMsg.c_str();
  message.html.charSet = "utf-8";
  message.html.transfer_encoding = Content_Transfer_Encoding::enc_qp;

  message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal;
  message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;

  /* The attachment data item */
  SMTP_Attachment att;

  /** Set the attachment info e.g. 
   * file name, MIME type, file path, file storage type,
   * transfer encoding and content encoding
  */
  att.descr.filename = "image.png";
  att.descr.mime = "image/png"; //binary data
  att.file.path = "/image.png";
  att.file.storage_type = esp_mail_file_storage_type_flash;
  att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

  /* Add attachment to the message */
  message.addAttachment(att);

  message.resetAttachItem(att);
  att.descr.filename = "text_file.txt";
  att.descr.mime = "text/plain";
  att.file.path = "/text_file.txt";
  att.file.storage_type = esp_mail_file_storage_type_flash;
  att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

  /* Add attachment to the message */
  message.addAttachment(att);

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

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

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

How the code works

This code is very similar to the previous one, so we’ll just take a look at the relevant parts to send attachments.

In the setup(), you need to initialize SPIFFS:

if(!SPIFFS.begin(true)) {

  Serial.println("An Error has occurred while mounting SPIFFS");

  return;

}

You need to create an attachment as follows:

/* The attachment data item */

SMTP_Attachment att;

Then, add the attachment details: filename, MIME type, file path, file storage type, and transfer encoding. In the following lines, we’re sending the image file.

att.descr.filename = "image.png";

att.descr.mime = "image/png"

att.file.path = "/image.png";

att.file.storage_type = esp_mail_file_storage_type_flash;

att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

Finally, add the attachment to the message:

message.addAttachment(att);

If you want to send more attachments, you need to call the following line before adding the next attachment:

message.resetAttachItem(att);

Then, enter the details of the other attachment (text file):

att.descr.filename = "text_file.txt";

att.descr.mime = "text/plain";

att.file.path = "/text_file.txt";

att.file.storage_type = esp_mail_file_storage_type_flash;

att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;

And add this attachment to the message:

message.addAttachment(att);

Finally, you just need to send the message as you did with the previous example:

if (!MailClient.sendMail(&smtp, &message, true))

  Serial.println("Error sending Email, " + smtp.errorReason());

Demonstration

After uploading the code, open the Serial Monitor at a baud rate of 115200 and press the on-board EN/RESET button. If everything goes smoothly, you should get a similar message on the Serial Monitor.

ESP32 Send Emails Message Successfully Serial Monitor

Check the recipient’s email address. You should have a new email with two attachments.

Conclusion

In this tutorial you’ve learned how to send emails with the ESP32 using an SMTP Server. For this method to work, the ESP32 should have access to the internet.

You’ve learned how to send a simple email with text and with attachments. When using attachments, these should be save on the ESP32 filesystem (SPIFFS) 

Author