Raspberry Pi Pico W: Sending Emails using SMTP Server (MicroPython)

Learn how to send emails with the Raspberry Pi Pico 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. We’ll program the Raspberry Pi Pico using MicroPython firmware.

Raspberry Pi Pico W Sending Emails using SMTP Server MicroPython

New to the Raspberry Pi Pico? Get started with the Raspberry Pi Pico here.

Table of Contents:

Prerequisites – MicroPython Firmware

To follow this tutorial you need MicroPython firmware installed in your Raspberry Pi Pico board. You also need an IDE to write and upload the code to your board.

The recommended MicroPython IDE for the Raspberry Pi Pico is Thonny IDE. Follow the next tutorial to learn how to install Thonny IDE, flash MicroPython firmware, and upload code to the board.

Introducing SMTP Servers

SMTP means Simple Mail Transfer Protocol and it is an internet standard for email transmission. To send emails using the Raspberry Pi Pico, you need to connect it 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 Raspberry Pi Pico, 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 the Raspberry Pi Pico. 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 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 Raspberry Pi Pico. 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 search bar, search for App Password.
  3. Click on the App Passwords menu.
Gmail create app password menu
  1. Now, you can create a new app password to use with the Raspberry Pi Pico. Give it a name. For example: Pi Pico.
Gmail, create new app password, rpi pico

Click Create. Your app password will show up. Copy it to a safe place because you’ll need it later (even though it says you don’t need to).

Generated app password

Now, you should have an app password that you’ll use on the Raspberry Pi Pico micropython script to send the emails.

App password created for the Raspberry Pi Pico Gmail

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. This library isn’t part of the standard MicroPython library by default. So, you need to upload the following file to your Raspberry Pi Pico (save it with the name umail.py) before using the library.

# Complete project details: https://RandomNerdTutorials.com/raspberry-pi-pico-w-send-email-micropython/
# 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 ussl
        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 = ussl.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 = ussl.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

  1. Create a new file in Thonny IDE and paste the previous code;
  2. Go to File > Save as… and select Raspberry Pi Pico;
  3. Save the file with the name umail.py (don’t change the name).

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 Raspberry Pi Pico (MicroPython) – Code

The following MicroPython script sends a simple email when the Raspberry Pi Pico board first boots/resets.

# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-w-send-email-micropython/
# Micropython lib to send emails: https://github.com/shawwwn/uMail
import umail
import network
import time

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

# Email details
sender_email = 'REPLACE_WITH_THE_SENDER_EMAIL'
sender_name = 'Raspberry Pi Pico'
sender_app_password = 'REPLACE_WITH_THE_SENDER_EMAIL_APP_PASSWORD'
recipient_email ='REPLACE_WITH_THE_RECIPIENT_EMAIL'
email_subject ='Hello from RPi Pico W'

# Init Wi-Fi Interface
def init_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    # Connect to your network
    wlan.connect(ssid, password)
    # Wait for Wi-Fi connection
    connection_timeout = 10
    while connection_timeout > 0:
        print(wlan.status())
        if wlan.status() >= 3:
            break
        connection_timeout -= 1
        print('Waiting for Wi-Fi connection...')
        time.sleep(1)
    # Check if connection is successful
    if wlan.status() != 3:
        print('Failed to connect to Wi-Fi')
        return False
    else:
        print('Connection successful!')
        network_info = wlan.ifconfig()
        print('IP address:', network_info[0])
        return True
    
# Connect to your network
init_wifi(ssid, password)

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

try:
    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 the Raspberry Pi Pico. Testing.")
    smtp.send()
    print("Email Sent Successfully")
    
except Exception as e:
    print("Failed to send email:", e)
finally:
    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 (it’s the app password not the email password), recipient’s email, and email subject.

After inserting all your details you can run the code to test it. If you want the code to run without being connected to your computer, you need to save it on the Raspberry Pi Pico with the name main.py.

How the Code Works

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

import 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 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 = 'Raspberry Pi Pico'
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 Hello from RPi Pico W, but you can change it on the email_subject variable.

email_subject ='Hello from RPi Pico W'

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

# Init Wi-Fi Interface
def init_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    # Connect to your network
    wlan.connect(ssid, password)
    # Wait for Wi-Fi connection
    connection_timeout = 10
    while connection_timeout > 0:
        print(wlan.status())
        if wlan.status() >= 3:
            break
        connection_timeout -= 1
        print('Waiting for Wi-Fi connection...')
        time.sleep(1)
    # Check if connection is successful
    if wlan.status() != 3:
        print('Failed to connect to Wi-Fi')
        return False
    else:
        print('Connection successful!')
        network_info = wlan.ifconfig()
        print('IP address:', network_info[0])
        return True

Before sending the email, we need to connect the Raspberry Pi Pico to the internet, so call the init_wifi() function (pass as arguments the ssid and password).

# Connect to your network
init_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

We then have try and except statements to send the email or print an error message if it fails.

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

You can use the following line to set the email subject.

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

Finally, you can write your email content. This is just a test email. We’re setting the message to “Hello from the Raspberry Pi Pico. Testing.”. The write() method sends the email to the SMTP server.

smtp.write("Hello from the Raspberry Pi Pico. Testing.")

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()

If it fails to send the email, it will print an error message:

except Exception as e:
    print("Failed to send email:", e)

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

finally:
    smtp.quit()

Demonstration

After uploading the umail.py module, you can run our sample code to test sending an email.

Run MicroPython script Thonny IDE

The Pico should connect to the internet and send the email.

Raspberry Pi Pico Send Email Successfully

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

test email sent from Raspberry Pi Pico using MicroPython (inbox)

Open the email to check its content.

test email sent from Raspberry Pi Pico using MicroPython

Wrapping Up

In this tutorial, you learned how to send emails with the Raspberry Pi Pico W using MicroPython. Sending an email using an SMTP server is very simple thanks to the uMail Micropython module.

We’ve shown you a simple example of how to send emails. Now you can use this in your projects to send notification alerts, sensor readings, and other applications.

Learn more about the Raspberry Pi Pico with our eBook:

If you’re using an ESP32 or ESP8266, check the following tutorial: MicroPython: Send Emails with the ESP32/ESP826.

We hope you’ve found this tutorial useful.

You can check all our Raspberry Pi Pico projects here.

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!

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.