This guide will teach you to send email with Raspberry Pi Pico using SMTP(Simple Mail Transfer Protocol). The code will be explained in MicroPython and will be uploaded using the Thonny IDE. We will MicroPython modules to connect to Wi-Fi and send emails from one account to another.
Overview of SMTP Protocol
SMTP(Simple Mail Transfer Protocol) is a communication protocol used to transfer electronic mail messages over the Internet. It uses commands and responses between an email client and an email server to transfer email messages and defines how email clients communicate with the SMTP server, how messages are formatted and transmitted, and how errors are handled during the communication process.
We need to know the SMTP server details of the email provider that we will be using to send emails from Raspberry Pi Pico. This information will be required in our MicroPython code later.
Below are the SMTP server details for Gmail by Google:
- SMTP server address: smtp.gmail.com
- SMTP username: Your Gmail address(e.g. email@example.com)
- SMTP password: Your Gmail password
- SMTP port (TLS): 587
- SMTP port (SSL): 465
- SMTP TLS/SSL Required: Yes
Here are the SMTP server details for MS Outlook:
- SMTP server address: smtp.office365.com
- SMTP Username: Your Outlook address(e.g. firstname.lastname@example.org)
- SMTP Password: Your Outlook password
- SMTP Port: 587(With TLS)
- Alternative Port Number: 25 (Without TLS/SSL)
If you are using an email from another service provider, you can easily get the SMTP details by a simple search in Google/Bing/DuckDuckGo.
Setting Up Your Email Account
Here, we will use Gmail to send email with Raspberry Pi Pico. In order for new devices to send emails using your Gmail account, you must generate an app password. A 16-digit passcode known as a “App Password” permits a device or app to access your Google Account.
In the case of Gmail, the App password only works when your account has 2-step verification turned on. You can visit this link to learn how to turn on 2-step verification on your Google account.
ⓘ You are advised not to use your primary email address as the sender account. Frequent SMTP requests may cause your email account to become blocked/disabled. The receiving email address can be your personal email ID.
Generating App Password In Gmail
- Go to your Google account management section.
- Search for “app passwords” in the search bar. Click on “App passwords”.
- In the ‘App passwords’ section, set the ‘Select app’ field to mail, and the ‘Select device’ field to other.
- You can set a device name such as “Pi Pico”. Then click on GENERATE.
- In the pop-up that appears, you will now see the app password. Copy this password and save it elsewhere. We shall use it in our code.
Setting Up Raspberry Pi Pico W For Sending Email.
Your Raspberry Pi Pico needs to be preloaded with a MicroPython UF2 file to program it in MicroPython. You can read our getting started guide for Raspberry Pi Pico, where we show all the steps required to start programming RP2040 in MicroPython. The guide explains coding using two IDEs:
ⓘ We also recommend reading our tutorial to connect Raspberry Pi Pico to the internet using MicroPython where you will find an in-depth explanation of connecting to Wi-Fi and making HTTP requests.
Installation of MicroPython Library to Send Email
We will use a MicroPython library called ‘umail’ to send email with Raspberry Pi Pico. It is a lightweight, scalable SMTP client for sending emails using MicroPython. You can visit its Github page to learn more about it.
Let us now see the steps to upload this module to Raspberry Pi Pico using Thonny IDE.
- Connect the Pico to your computer using a USB cable. Open Thonny IDE, and paste the following code into a new project.
# uMail (MicroMail) for MicroPython # Copyright (c) 2018 Shawwwn <email@example.com> 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)[-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()Code language: Python (python)
- Run the code by clicking the Run icon or by pressing the F5 key.
- Save the script to your Raspberry Pi Pico.
- Save the script as umail.py.
MicroPython Code to Send Email With Raspberry Pi Pico W
With the ‘umail.py‘ library installed, you can now upload the main script. The following script will send an email when the device boots up.
Note that you have to change the details in the code according to your Wi-Fi network and email. Set the sender name, sender email, sender app password, recipient email, and the subject of your email. Set the ‘
ssid‘ to the name of your Wi-Fi network and also enter the password.
Open a new file in Thonny IDE and paste the following script.
import umail import network import time # Your email details sender_email = 'firstname.lastname@example.org' sender_name = 'RaspberryPiPico' sender_app_password = 'xxxxxxxxxxxxxx' recipient_email ='email@example.com' email_subject ='Email from RPi Pico' # Your network credentials ssid = 'Your WIFI SSID' password = 'Your password' #Connect to Wi-Fi wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) # Wait for connection to establish max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('waiting for connection...') time.sleep(1) # Manage connection errors if wlan.status() != 3: raise RuntimeError('Network Connection has failed') else: print('connected') # Send email once after MCU boots up smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True) 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("This is an email from Raspberry Pi Pico") smtp.send() smtp.quit()Code language: Python (python)
The steps to run the script are similar to the ones we discussed above for the umail.py module. Save the script to your Pico and name it ‘main.py‘.
When I ran the script, I received an email as shown in the screenshot below.
MicroPython Code Explained
We first import the required modules for our code to work. The ‘
umail‘ library is the one we saved earlier, the ‘network’ library will be used to connect to Wi-Fi and the ‘time’ library is used to introduce delay in code execution.
Replace ‘firstname.lastname@example.org’ with the email address you will use to send emails. The email address must be within single quotes as shown. Also, set the sender name. You can set it as ‘RaspberryPiPico’.
The ‘sender-app-password’ is the one you generated, as shown in the Gmail app password generation step.
Next, specify the address where you will receive the email, and also give a suitable email subject.
Set the Wi-Fi credentials of the Wi-Fi network with which your Pico will connect to. Remember to include the Wi-Fi name and password within single quotes.
An instance is created of the ‘WLAN’ class in station mode(STA_IF). Then we activate the network interface and connect to it using our network credentials. You can read our article on connecting Raspberry Pi Pico to the internet using Wi-Fi to know more.
wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password)Code language: PHP (php)
If the connection to the Wi-Fi fails, we make 10 attempts to reconnect. The function ‘
wlan.status()‘ gives the wireless connection status.
max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('waiting for connection...') time.sleep(1)Code language: PHP (php)
The code below handles any communication error that may occur. If the code returned by ‘
wlan.status()‘ is not equal to 3(i.e. LINK UP), then a runtime error is raised to notify the user.
if wlan.status() != 3: raise RuntimeError('Network Connection has failed') else: print('connected')Code language: PHP (php)
Initiate an ‘
smtp‘ instance by specifying the SMTP server details, SMTP port, and set ‘ssl=True’ if SSL is required for your server. Here the server details of Gmail are entered for demonstration.
smtp = umail.SMTP('smtp.gmail.com', 465, ssl=True)Code language: PHP (php)
smtp.login()‘ and ‘
smtp.to()‘ functions used to login to the server and set the recipient email address respectively.
smtp.login(sender_email, sender_app_password) smtp.to(recipient_email)Code language: CSS (css)
smtp.write()‘ function can be used to specify the sender details and subject as shown in the code below.
The ‘smtp.write()’ function is also used to write the body of the email.
smtp.send()‘ function sends the email according to the details we entered in the previous steps. In the end, it is necessary to call ‘
smtp.quit()‘ function to close the connection with the server.
smtp.send() smtp.quit()Code language: CSS (css)
In this guide, we went through the following steps:
- Obtained an app password from a Gmail account.
- Uploaded ‘umail’ module to Raspberry Pi Pico which contains useful functions to send email using SMTP.
- Ran the ‘main.py’ MicroPython script to send a simple email from Raspberry Pi Pico.
- Learned how the MicroPython script worked.
We hope you found this tutorial to send email using Raspberry Pi Pico W helpful. Please leave your thoughts in the comment below.