MicroPython: Send Emails with the ESP32/ESP826

Learn how to program the ESP32 or ESP8266 NodeMCU boards with MicroPython to send emails using an SMTP server. This feature can be useful in your automation and IoT projects to send alert notifications, send messages with sensor readings, and much more.

MicroPython Send Emails with the ESP32 ESP826 NodeMCU board

If you prefer to program your boards using Arduino IDE, you can check the following tutorials instead:

Prerequisites

New to MicroPython? You can get started here: Getting Started with MicroPython on ESP32 and ESP8266.

To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:

Or, if you’re familiar with VS Code, you may want to use the PyMakr extension:

For a comparison between different MicroPython IDEs, read: MicroPython IDEs for ESP32 and ESP8266.

Learn more about MicroPython: MicroPython Programming with ESP32 and ESP8266 eBook.

Introducing SMTP Servers

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

uMail Module

To easily send emails with MicroPython, we’ll use a module called uMail. This module is not part of the standard collection of MicroPython libraries, so we’ll need to upload it separately to our board—we’ll provide instructions for this later in the tutorial.

SMTP Server Settings

To send emails with the ESP32 or ESP8266 boards, you need a sender email and you’ll need to know your email SMTP server settings. Below you’ll find the settings for the most popular email providers.

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—you’ll easily find them with a quick google search.

Sender Email (New Account)

We recommend creating a new email account to send the emails to your main personal email address. Do not use your main personal email to send emails via ESP32 or ESP8266. If something goes wrong in your code or if by mistake you make too many requests, you can be banned or have your account temporarily disabled.

We’ll use a newly created Gmail.com account to send the emails, but you can use any other email provider. The receiver email can be your personal email without any problem.

Create a Sender Email Account

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

Gmail Create a new account

Create an App Password

You need to create an app password so that new devices can send emails using your Gmail account. An App Password is a 16-digit passcode that gives a less secure app or device permission to access your Google Account. 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. In the Select app field, choose mail. For the device, select Other and give it a name, for example ESP32. Then, click on Generate. It will pop-up a window with a password that you’ll use with the ESP32 or ESP8266 to send emails. Save that password (even though it says you won’t need to remember it) because you’ll need it later.
Generated App password gmail

Now, you should have an app password that you’ll use on the ESP32/ESP8266 micropython script to send the emails.

Gmail app password created for ESP32 send emails

If you’re using another email provider, check how to create an app password. You should be able to find the instructions with a quick google search “your_email_provider + create app password”.

Uploading the uMail Module

To send the emails, we’ll use the uMail module. You can check its Github page and several examples here. This library isn’t part of the standard MicroPython library by default. So, you need to upload the following file to your ESP32/ESP8266 board (save it with the name umail.py) before using the library.

# Complete project details: https://RandomNerdTutorials.com/micropython-send-emails-esp32-esp826/
# uMail (MicroMail) for MicroPython
# Copyright (c) 2018 Shawwwn <[email protected]> https://github.com/shawwwn/uMail/blob/master/umail.py
# License: MIT
import usocket

DEFAULT_TIMEOUT = 10 # sec
LOCAL_DOMAIN = '127.0.0.1'
CMD_EHLO = 'EHLO'
CMD_STARTTLS = 'STARTTLS'
CMD_AUTH = 'AUTH'
CMD_MAIL = 'MAIL'
AUTH_PLAIN = 'PLAIN'
AUTH_LOGIN = 'LOGIN'

class SMTP:
    def cmd(self, cmd_str):
        sock = self._sock;
        sock.write('%s\r\n' % cmd_str)
        resp = []
        next = True
        while next:
            code = sock.read(3)
            next = sock.read(1) == b'-'
            resp.append(sock.readline().strip().decode())
        return int(code), resp

    def __init__(self, host, port, ssl=False, username=None, password=None):
        import ssl
        self.username = username
        addr = usocket.getaddrinfo(host, port)[0][-1]
        sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)
        sock.settimeout(DEFAULT_TIMEOUT)
        sock.connect(addr)
        if ssl:
            sock = ssl.wrap_socket(sock)
        code = int(sock.read(3))
        sock.readline()
        assert code==220, 'cant connect to server %d, %s' % (code, resp)
        self._sock = sock

        code, resp = self.cmd(CMD_EHLO + ' ' + LOCAL_DOMAIN)
        assert code==250, '%d' % code
        if not ssl and CMD_STARTTLS in resp:
            code, resp = self.cmd(CMD_STARTTLS)
            assert code==220, 'start tls failed %d, %s' % (code, resp)
            self._sock = ssl.wrap_socket(sock)

        if username and password:
            self.login(username, password)

    def login(self, username, password):
        self.username = username
        code, resp = self.cmd(CMD_EHLO + ' ' + LOCAL_DOMAIN)
        assert code==250, '%d, %s' % (code, resp)

        auths = None
        for feature in resp:
            if feature[:4].upper() == CMD_AUTH:
                auths = feature[4:].strip('=').upper().split()
        assert auths!=None, "no auth method"

        from ubinascii import b2a_base64 as b64
        if AUTH_PLAIN in auths:
            cren = b64("\0%s\0%s" % (username, password))[:-1].decode()
            code, resp = self.cmd('%s %s %s' % (CMD_AUTH, AUTH_PLAIN, cren))
        elif AUTH_LOGIN in auths:
            code, resp = self.cmd("%s %s %s" % (CMD_AUTH, AUTH_LOGIN, b64(username)[:-1].decode()))
            assert code==334, 'wrong username %d, %s' % (code, resp)
            code, resp = self.cmd(b64(password)[:-1].decode())
        else:
            raise Exception("auth(%s) not supported " % ', '.join(auths))

        assert code==235 or code==503, 'auth error %d, %s' % (code, resp)
        return code, resp

    def to(self, addrs, mail_from=None):
        mail_from = self.username if mail_from==None else mail_from
        code, resp = self.cmd(CMD_EHLO + ' ' + LOCAL_DOMAIN)
        assert code==250, '%d' % code
        code, resp = self.cmd('MAIL FROM: <%s>' % mail_from)
        assert code==250, 'sender refused %d, %s' % (code, resp)

        if isinstance(addrs, str):
            addrs = [addrs]
        count = 0
        for addr in addrs:
            code, resp = self.cmd('RCPT TO: <%s>' % addr)
            if code!=250 and code!=251:
                print('%s refused, %s' % (addr, resp))
                count += 1
        assert count!=len(addrs), 'recipient refused, %d, %s' % (code, resp)

        code, resp = self.cmd('DATA')
        assert code==354, 'data refused, %d, %s' % (code, resp)
        return code, resp

    def write(self, content):
        self._sock.write(content)

    def send(self, content=''):
        if content:
            self.write(content)
        self._sock.write('\r\n.\r\n') # the five letter sequence marked for ending
        line = self._sock.readline()
        return (int(line[:3]), line[4:].strip().decode())

    def quit(self):
        self.cmd("QUIT")
        self._sock.close()

View raw code

Regardless of the IDE you’re using, these are the general instructions to upload the uMail library to your board:

  1. First, make sure your board is running MicroPython firmware—check the Prerequisites section.
  2. Create a new file in your IDE with the name umail.py and paste the previous code there. Save that file.
  3. Establish a serial communication with your board using your IDE.
  4. Upload the umail.py file to your board.
  5. At this point, the library should have been successfully uploaded to your board. Now, you can use the library functionalities in your code by importing the library: import umail.

Sending Emails with the ESP32/ESP8266 (MicroPython) – Code

At this point, you should have uploaded the umail.py file to your board to be able to send emails using the umail module.

The following script sends a simple email when the ESP32/ESP8266 board first boots/resets.

# Complete project details: https://RandomNerdTutorials.com/micropython-send-emails-esp32-esp826/
# Micropython lib to send emails: https://github.com/shawwwn/uMail
import umail
import network

# Your network credentials
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

# Email details
sender_email = 'REPLACE_WITH_THE_SENDER_EMAIL'
sender_name = 'ESP32' #sender name
sender_app_password = 'REPLACE_WITH_THE_SENDER_EMAIL_APP_PASSWORD'
recipient_email ='REPLACE_WITH_THE_RECIPIENT_EMAIL'
email_subject ='Test Email'

def connect_wifi(ssid, password):
  #Connect to your network
  station = network.WLAN(network.STA_IF)
  station.active(True)
  station.connect(ssid, password)
  while station.isconnected() == False:
    pass
  print('Connection successful')
  print(station.ifconfig())
    
# Connect to your network
connect_wifi(ssid, password)

# Send the email
smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True) # Gmail's SSL port
smtp.login(sender_email, sender_app_password)
smtp.to(recipient_email)
smtp.write("From:" + sender_name + "<"+ sender_email+">\n")
smtp.write("Subject:" + email_subject + "\n")
smtp.write("Hello from ESP32")
smtp.send()
smtp.quit()

View raw code

You need to insert your details on the code before uploading the code to the board: SSID and password, sender email, sender name, and corresponding app password, recipient’s email, and email subject.

After inserting all your details you can upload the code to your board. The file with the code needs to be named main.py, otherwise, it will not work.

How the Code Works

First, include the required libraries. The umail library, which we loaded previously to the board, so that we can send emails, and the network library so that we can set the ESP32/ESP8266 as a wi-fi station to be able to connect to the internet (local network).

import umail # Micropython lib to send emails: https://github.com/shawwwn/uMail
import network

Insert your network credentials, SSID and password, on the following variables so that your board can connect to the internet:

ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'

Insert the email details: sender email, sender name, and corresponding app password. You really need to create an app password—using the regular email password won’t work, see this section.

# Email details
sender_email = 'REPLACE_WITH_THE_SENDER_EMAIL'
sender_name = 'ESP32' #sender name
sender_app_password = 'REPLACE_WITH_THE_SENDER_EMAIL_APP_PASSWORD'

Insert the recipient’s email on the recipient_email variable:

recipient_email ='REPLACE_WITH_THE_RECIPIENT_EMAIL'

The email subject is set to Test Email, but you can change it on the email_subject variable.

email_subject ='Test Email'

We created a function called connect_wifi() that accepts as arguments the SSID and password of the network you want to connect to. You should call this function later to actually connect the ESP board to the internet.

def connect_wifi(ssid, password):
  #Connect to your network
  station = network.WLAN(network.STA_IF)
  station.active(True)
  station.connect(ssid, password)
  while station.isconnected() == False:
    pass
  print('Connection successful')
  print(station.ifconfig())

Before sending the email, we need to connect the ESP32/ESP8266 to the internet, so call the connect_wifi() function (pass as arguments the ssid and password).

# Connect to your network
connect_wifi(ssid, password)

Now, we can finally start preparing and sending the email.

Start by creating an SMTP client using your email provider SMTP settings called smtp. Here we’re using a Gmail account. Change the settings if you’re using a different email provider—set the server, port, and if SSL is required or not.

smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True) # Gmail's SSL port

Then, login into your account using the login() method on the smtp client—pass as arguments the email and corresponding app password.

smtp.login(sender_email, sender_app_password)

Set the recipient using the to() method and pass the recipient’s email as an argument:

smtp.to(recipient_email)

Then, use the write() method to write the email. You can use this method as follows to set the sender name.

smtp.write("From:" + sender_name + "<"+ sender_email+">\n")

And you can use the following line to set the email subject.

smtp.write("Subject:" + email_subject + "\n")

Finally, you can actually write your email content. This is just a test email. We’re setting the message to “Hello from the ESP32/ESP8266” board. The write() method sends the email to the SMTP server.

smtp.write("Hello from the ESP32/ESP8266")

If you need to send a long string as the email body, break the email message into smaller chunks and send each chunk using the write() method—see the uMail library documentation.

Finally, use the send() method to make the SMTP server send the email to the recipient.

smtp.send()

In the end, close the connection with the server using the quit() method.

smtp.quit()

Demonstration

After uploading the umail module and the main.py script to your board, run the code or reset/restart your board. You should get a similar message in the shell indicating that your board connected successfully to the internet.

micropython internet connection successful

After a while, you should receive a new email on the recipient’s email account.

test email sent from EPS32/ESP8266 using MicroPython (inbox)

Open the email to check its content.

test email sent from EPS32/ESP8266 using MicroPython

Wrapping Up

In this tutorial, you learned how to send emails with the ESP32/ESP8266 using MicroPython firmware. Sending an email using an SMTP server is very straightforward thanks to the uMail Micropython module.

We’ve shown you a simple example application. Now, the idea is to use this feature in your own projects. This can be useful to send notification alerts, sensor readings, and other applications.

We hope you find this tutorial useful. If you want to use a different notification method, we have a tutorial showing how to send messages to WhatsApp using MicroPython (ESP32 and ESP8266):

You can check all our MicroPython projects here.

If you want to learn more about programming the ESP32 and ESP8266 boards with MicroPython, check out our eBook: MicroPython Programming with ESP32 and ESP8266.

Thanks for reading



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

16 thoughts on “MicroPython: Send Emails with the ESP32/ESP826”

  1. Hi, thanks for another very interesting tutorial!

    The one thing I missed was the “To: ” information in the messages. This was easily adjusted by adding the following line:

    smtp.write(“To:” + recipient_email + “\n”)

    directly below the line containing smtp.write(“From: ” = . . . .

    Reply
  2. Hi Sara
    thanks for this tutorial
    I amworking with a google account,
    I have a the app password, but how can I generate the sender_email ?
    Thanks for your help
    Charles

    Reply
    • Hi.
      What do you mean?
      The sender_email is the account that will send the emails. The one where you got the app password.
      Regards,
      Sara

      Reply
      • Hi Sara
        Thanks for your reply.
        My formulation was not right .
        I try different change in the email detail lines of the main .py
        sender_email = ‘[email protected]’ : I try different different email adress
        sender_app_password = ‘ swqchecibgaptjkw’ : password generated by Google
        The result of testing the program is always :
        QUOTE
        Connection successful
        (‘192.168.1.35’, ‘255.255.255.0’, ‘192.168.1.1’, ‘192.168.1.1’)
        Traceback (most recent call last):
        File “”, line 32, in
        File “umail.py”, line 74, in login
        AssertionError: auth error 535, [‘5.7.8 Username and Password not accepted. Learn more at’, ‘5.7.8 https://support.google.com/mail/?p=BadCredentials z6-20020a5d4d06000000b002e6d4ac31a3sm4812726wrt.72 – gsmtp’]
        UNQUOTE
        Line 32 is the line SMPT login in main .py
        Line 74 is related to Def. login fonction
        assert code==235 or code==503, ‘auth error %d, %s’ % (code, resp)
        What is the problem
        Thanks for your comment

        Reply
        • It seems an issue logging in.
          Check that you’re inserting the right email and corresponding app password.
          Try generating a new app password and try with that one.

          Reply
      • Hi Sara,
        Sorry for the late reply
        I try with different mail providers, different name, different apppasword, but without success
        Hereafter the latest version

        Email details

        sender_email = ‘[email protected]’ #comming the screen wher the app_password is genereted
        sender_name = ‘DB18X20’ #sender name
        sender_app_password = ‘dudripvopbhcpkld’
        recipient_email =’[email protected]
        email_subject =’Test Email’

        from the repshell:
        Connection successful
        (‘192.168.1.35’, ‘255.255.255.0’, ‘192.168.1.1’, ‘192.168.1.1’)
        Traceback (most recent call last):
        File “”, line 32, in
        File “umail.py”, line 74, in login
        AssertionError: auth error 535, [‘5.7.8 Username and Password not accepted. Learn more at’, ‘5.7.8 https://support.google.com/mail/?p=BadCredentials o3-20020a05600c4fc300b003ee1e07a14asm1305937wmq.45 – gsmtp’]

        Your comment will be appreciated
        Charles

        Reply
  3. Dear Sara,
    the E-mail application is working well. Thanks !!
    BUT, how to add/mail a file ? (F.i a .TXT file)
    Best regards, Marc

    Reply
  4. Hello,

    I and attempting to send an email that displays a message as well as display the current time. However when I run, it my email is blank. I am running the code like this,

    smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True) # Gmail's SSL port
    smtp.login(sender_email, sender_app_password)
    smtp.to(recipient_email)
    smtp.write("From:" + sender_name + "<"+ sender_email+">\n")
    smtp.write("Subject:" + email_subject + "\n")
    time_date_string = get_time_and_date()
    smtp.write("You got mail "+"on " + get_time_and_date())
    smtp.send()
    smtp.quit()
    previous_distance=distance

    where get_time_and_date() calls on a function that give the time and date in a string format. Is it possible to send variables with strings in the write() function?

    Reply
    • Yes.
      Maybe there is something wrong with the return of your function.
      Save the date and time on a variable and then, concatenate everything on a variable instead of inside the write() function.
      Regards,
      Sara

      Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.