Send Email from ESP32 via SMTP Server (Arduino IDE)

Learn how to send email from ESP32 via SMTP server. We'll show you how to send a simple HTML or raw text email, as well as how to send attachments like images and files (.txt). Using Arduino's IDE, the ESP32 board will be programmed.

The following topics are covered in this tutorial:

We have a similar tutorial for the ESP8266 board: Send Email from ESP8266 NodeMCU via SMTP Server

Introducing SMTP Servers

SMTP stands for Simple Mail Transfer Protocol, and it is an internet standard for sending email. You need to connect an ESP32 to an SMTP server to send emails using it.

ESP Mail Client Library

We'll use the ESP-Mail-Client library to send emails from the ESP32. The ESP32 can send and receive emails with or without attachments over SMTP and IMAP servers using this library.

We'll use SMTP in this tutorial to send an email with and without attachments. We'll send an image (.png) and a text (.txt) file as examples. Email files may be stored in the ESP32 Filesystem (SPIFFS) or on a microSD card (which this tutorial does not cover).

Installing the ESP-Mail-Client Library

You need to install the ESP-Mail-Client library before proceeding with this tutorial. This library cannot be installed using the Arduino IDE Library Manager. To install the library, follow the next steps:

  1. Click here to download the 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, under File > Examples > ESP-Mail-Client, you'll find various examples to try. The examples are also available on the library's GitHub page.

To include the library, copy the following to your platformio.ini file if you're using the ESP32 with VS Code + PlatformIO.

lib_deps = mobizt/ESP Mail Client @ ^1.3.0

Sender Email (New Account)

To send emails to your main personal email address, we recommend starting a new email account. Do not send emails using ESP32 using your main personal email address. If anything goes wrong in your code or if you make too many requests by mistake, you may be banned or have your account temporarily suspended.

To send the emails, we'll use a newly created Gmail.com account, but you may use any other email service. The receiver's email address may be your email address without any problem.

Create a Sender Email Account

To send emails using the ESP32, create a new email account. Go to this link to create a Gmail account if you wish to use it.

Gmail Create a new account

Create an App Password

You'll need to create an app password so that the ESP32 can send emails using your Gmail account. A less secure app or device is granted permission to access your Google Account using a 16-digit passcode. Learn more about sign-in with app passwords here.

An app password can only be used with accounts that have 2-step verification turned on.

  1. Open your Google Account.
  2. In the navigation panel, select “Security“.
  3. Under “Signing in to Google”, select 2-Step Verification > Get Started.
  4. Follow the on-screen steps.

After enabling 2-step verification, you can create an app password.

  1. Open your Google Account.
  2. In the navigation panel, select Security.
  3. Under “Signing in to Google,” select App Passwords.
Create app password gmail
  1. Choose mail in the Select App field. Give the device a name, such as ESP32, and select Other. Then click the Generate button. When you use ESP32 or ESP8266 to send emails, a window with a password will pop up. You'll need that password later, even though it says you don't need to remember it.
Generated App password gmail

You should now have an app password that you'll use to send emails from the ESP32 code.

Gmail app password created for ESP32 send emails

Check how to create an app password if you're using another email provider. With a quick Google search, you should be able to find the instructions: “your_email_provider + create app password”.

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

You need to search for its SMTP Server settings if you're using another email service. You now have everything you need to get started sending emails from your ESP32.

Send an Email with HTML or Raw Text with ESP32 (Arduino IDE)

The following code sends an email with HTML or raw text via an SMTP server. The ESP32 sends an email once when it boots for demonstration reasons. You should then be able to modify the code and incorporate it into your projects.

Don't upload the code just yet; you'll need to make some modifications to get it to work for you.

/*
  LEDEdit PRO
  Complete project details at:
   - ESP32: https://lededitpro.com/send-email-from-esp32-via-smtp-server/
   - ESP8266: https://lededitpro.com/send-email-from-esp8266-nodemcu-via-smtp-server/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  Example adapted from: https://github.com/mobizt/ESP-Mail-Client
*/

// To send Emails using Gmail on port 465 (SSL), you need to create an app password: https://support.google.com/accounts/answer/185833

#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.c_str());
      ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str());
    }
    Serial.println("----------------\n");
  }
}

As well as insert the sender email, SMTP Server information, recipient, and message, you also need to set your network credentials.

How the Code Works

This code has been modified from a library example. The code in the example is well-commented, so you can understand what each line of code does. Let's take a look at the relevant parts that you need or may need to update.

First, insert your network credentials in the following lines:

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

Insert it in your SMTP server settings. If you're sending emails using a Gmail account, these are the settings:

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

Insert the sender email sign-in credentials (complete the email and app password you created previously).

#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 setup() by including the following lines: sender name, sender email, email topic, and 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);

Set the message content (raw text) in the textMsg variable in the following lines:

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

On your ESP32, upload the code. Open the Serial Monitor after uploading at 115200 baud rate. Reset the ESP32 by pressing the button.

If everything went according to plan, the Serial Monitor should display a message similar to this.

ESP Send Email Message Successfully Serial Monitor

Check your email account. You should have received an email from your ESP32 board.

ESP32 SMTP Server Receive Email Test

The messages look like this if you set the option to send a message with HTML text:

ESP32 SMTP Server Send Email with Body Text format HTML

If you’ve enabled the raw text message, this is the email that you should receive.

ESP32 SMTP Server Send Email with Body Text only format

Send Attachments via Email with ESP32 (Arduino IDE)

In this part, we'll show you how to send attachments in your emails sent by the ESP32. We will show you how to send .txt pictures or files. This is useful to send a .txt file with sensor readings from the past several hours or a photo taken by an ESP32-CAM.

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

Upload files to SPIFFS

Files should be saved on the ESP32 filesystem (SPIFFS) before being sent via email. Using the ESP32 Filesystem Uploader plugin for the Arduino IDE, we'll upload a picture and a.txt file to the ESP32 SPIFFS. If you haven't already, go to the next tutorial to install the plugin:

Create and save a new Arduino sketch. Select Sketch > Show Sketch Folder. Create a folder named “data” within the Arduino sketch folder. Add a.jpg and a.txt files to your data folder.

Alternatively, you can click here to download the project folder.

Your files must be named image.png and text_file.txt with the default code. You may also modify the code to import files with other names.

We’ll be sending these files:

Send emails with attachments ESP32 ESP8266 Text file and image

Your folder structure should look as follows (download project folder):

Send email attachments folder structure filesystem organizing files

In your Arduino IDE, go to Tools > ESP32 Sketch Data Upload and wait for the files to upload after moving the files to the data folder.

ESP32 Sketch Data Upload Arduino IDE SPIFFS FS Filesystem

In the debugging window, you should see a success message. Move on to the next stage if the files were uploaded successfully.

SPIFFS image done uploading success message

Note: If you start seeing many dots ….….. being printed on the debugging window, you need to hold the ESP32 on-board BOOT button for the files to be uploaded.

Code

The following code sends an email with a .txt file and a picture attached. Make sure to insert your sender email address and your recipient email before uploading the code.

/*
  LEDEdit PRO
  Complete project details at:
   - ESP32: https://lededitpro.com/send-email-from-esp32-via-smtp-server/
   
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  Example adapted K. Suwatchai (Mobizt): https://github.com/mobizt/ESP-Mail-Client Copyright (c) 2021 mobizt
*/

// To send Emails using Gmail on port 465 (SSL), you need to create an app password: https://support.google.com/accounts/answer/185833
// The file systems for flash and sd memory can be changed in ESP_Mail_FS.h.

#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.c_str());
      ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str());
    }
    Serial.println("----------------\n");
  }
}

How the code works

We'll just take a look at the relevant parts to send attachments since this code is very similar to the previous one.

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 information: filename, MIME type, file path, file storage type, and transfer encoding. We're sending the image file in the following lines:

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 115200 baud rate and press the on-board EN/RESET button. If everything goes well, you should see a message similar to this on the Serial Monitor.

ESP Send Email Message Successfully Serial Monitor

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

Send Email with Attachments ESP32 and ESP8266

Conclusion

You've learned how to send emails with the ESP32 using an SMTP server in this tutorial. The ESP32 must have internet connectivity for this method to work.

If you do not want to use an SMTP server, you may write a PHP script to send email notifications with the ESP32 or ESP8266 boards.

You have learned how to send a simple email with text and attachments. When using extensions, they should be saved on the ESP32 filesystem (SPIFFS) or on a microSD card (which is not addressed in this tutorial).

The examples show how to send a single email when the ESP32 boots. The plan is to modify the code and include it in your projects. For example, it may be helpful to send a.txt file with sensor readings, a photo taken with the ESP32-CAM, to use deep sleep to wake up your board every hour, to send an email containing data, and so on.

We hope you’ve found this tutorial interesting.

If you like ESP32, you may also like:

We hope you find this tutorial useful. Thanks for reading.

Oh hi there It’s nice to meet you.

Sign up to receive awesome content in your inbox, every month.

We don’t spam! Read our privacy policy for more info.

Leave a Reply

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

Developing IoT Projects with ESP32

Automate your home or business with inexpensive Wi-Fi devices