Sending Emails From Raspberry Pi Using Python (yagmail)
embedded linux
In this guide, we will learn how to send emails from a Raspberry Pi using a Gmail account and the Python library yagmail. This is incredibly useful for IoT projects, such as sending alerts when a sensor triggers or sending daily logs.
Under the "Signing in to Google" section, ensure 2-Step Verification is turned ON. (App Passwords will not appear unless 2FA is enabled).
Once 2FA is on, look for App Passwords (you may need to use the search bar at the top of the settings page).
Create a new App Password:
App name: "Raspberry Pi" (or whatever you prefer).
Click Create.
Google will generate a 16-character code (e.g., abcd efgh ijkl mnop). Copy this code immediately. You will not see it again. This is the "password" you will use in your Python script.
Now we will write a basic script to test if the connection works.
⚠ Security Warning: Hardcoding credentials (writing your password directly in the file) is insecure, especially if you share your code online. We are doing it here only for a quick test. In a production environment, you should use a separate secrets file or environment variables.
Create a file named send_email_simple.py:
text
nano send_email_simple.py
Paste the following code:
python
#!/usr/bin/env python3import yagmail# --- Configuration ---# Your email addressmy_gmail = "your_gmail@gmail.com"# The 16-character App Password you generated in Step 1# (Do not use your regular Gmail password)my_password = "xxxx xxxx xxxx xxxx"# The person receiving the emailrecipient = "recipient@example.com"# --- Sending the Email ---try: # Initialize the connection yag = yagmail.SMTP(user=my_gmail, password=my_password) # Send the email yag.send( to=recipient, subject="Test Email from Raspberry Pi", contents="Hello! This is a test email sent successfully using Yagmail on Raspberry Pi." ) print("✅ Email sent successfully!")except Exception as e: print(f"❌ Error sending email: {e}")
Create a hidden file for the password so it's not visible in directory listings:
bash
echo "my_app_password_or_secret" > /home/pi/.local/share/.email_password# Restrict permissions so only the file owner can read itchmod 600 /home/pi/.local/share/.email_password
Update your script to read from this file:
python
#!/usr/bin/env python3import yagmail# Read password from the secure filewith open("/home/pi/.local/share/.email_password", "r") as f: password = f.read().strip()my_gmail = "your_gmail@gmail.com"recipient = "recipient@example.com"try: yag = yagmail.SMTP(user=my_gmail, password=password) yag.send( to=recipient, subject="Test Email (Password from File)", contents="Now I'm reading my password from a local file!" ) print("✅ Email sent!")except Exception as e: print(f"❌ Error: {e}")
One of the best features of yagmail is how easy it makes sending attachments (like log files or photos) and HTML content.
Here is a complete example:
python
#!/usr/bin/env python3import yagmaildef send_email_with_attachment(gmail_user, gmail_password, recipient, filepath): yag = yagmail.SMTP(gmail_user, gmail_password) # List items can be text, file paths, or HTML strings # Yagmail automatically detects if a string is a file path contents = [ "Hello, here's an attachment:", filepath, "<b>This is some HTML content in bold!</b>", "<p>You can format this however you like.</p>" ] try: yag.send( to=recipient, subject="Email with Attachment and HTML", contents=contents ) print("✅ Email sent with attachment and HTML!") except Exception as e: print(f"❌ Error: {e}")if __name__ == "__main__": # Example usage gmail_address = "your_gmail@gmail.com" # Use your preferred method for getting the password here # For simplicity in this snippet, we assume a variable gmail_password = "your_app_password" recipient = "recipient@example.com" # Make sure this file actually exists! file_to_attach = "/home/pi/test.txt" send_email_with_attachment(gmail_address, gmail_password, recipient, file_to_attach)
Under the hood, Yagmail automatically constructs a MIME email with multiple parts (text, HTML, attachments), saving you from writing dozens of lines of complex boilerplate code.
Yagmail supports OAuth2 flows via the yagmail[oauth] extras:
Install with OAuth2 extras:
bash
pip3 install yagmail[oauth]
Register your email with Yagmail to generate an OAuth2 token:
python
import yagmail# The first time, you may need to authorize via a browser window# You will typically need a 'client_secret.json' from Google Cloud Consoleyagmail.register('your_gmail@gmail.com', oauth2_file='~/oauth2_creds.json')
This command-line or script process may prompt you to visit a link in your browser to grant permission. Once complete, your token is saved locally (in oauth2_creds.json).
Alternatively: If you have a Google Cloud project with OAuth2 credentials (Client ID & Secret), you can specify them. See Yagmail docs or google-auth-oauthlib docs for advanced details.
After registering, you can use OAuth2 automatically:
python
#!/usr/bin/env python3import yagmaildef send_oauth2_email(): # No password needed here if you have the token file yag = yagmail.SMTP( user="your_gmail@gmail.com", oauth2_file="~/oauth2_creds.json" ) yag.send( to="recipient@example.com", subject="Hello via OAuth2", contents="This message is sent with OAuth2. No stored password!" ) print("Email sent via OAuth2!")if __name__ == "__main__": send_oauth2_email()
Explanation:
Once oauth2_creds.json is set up, Yagmail uses it to generate a valid OAuth2 token for sending Gmail.
If the token expires or is invalid, Yagmail will help you refresh or reauthorize.
MIME stands for Multipurpose Internet Mail Extensions. It is an internet standard that extends the format of email to support:
Multiple parts: text, HTML, images, audio, video, and other application programs.
Non-ASCII text: Using characters sets other than ASCII.
Headers: describing content type and encoding.
When you use yagmail, it automatically handles all the complex MIME structuring for you. It detects if you are sending a file or a string, and packages it into the correct MIME type. However, sometimes you might want full control or need to avoid external libraries like Yagmail. In those cases, you must build the MIME structure manually.
For advanced usage, debugging, or if you simply prefer using Python's standard library without installing yagmail, you can manually create MIME messages. This requires more code but gives you total control.
python
import smtplibimport sslfrom email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMEText# --- Configuration ---sender = "your_gmail@gmail.com"receiver = "recipient@example.com"password = "YOUR_APP_PASSWORD" # Or load from file/envsubject = "Manual MIME Example"body_text = "Hi, this email is built using MIMEMultipart and MIMEText."body_html = """<html> <body> <p>Hi,<br> This email is built using <b>MIMEMultipart</b> and <b>MIMEText</b>.<br> It has both plain text and HTML parts! </p> </body></html>"""# --- Create the MIME Object ---msg = MIMEMultipart("alternative")msg["From"] = sendermsg["To"] = receivermsg["Subject"] = subject# Attach parts into message container.# According to RFC 2046, the last part of a multipart message, in this case# the HTML message, is best and preferred.part1 = MIMEText(body_text, "plain")part2 = MIMEText(body_html, "html")msg.attach(part1)msg.attach(part2)# --- Send the Email ---context = ssl.create_default_context()try: with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server: server.login(sender, password) server.sendmail(sender, receiver, msg.as_string()) print("✅ Email sent via smtplib!")except Exception as e: print(f"❌ Error: {e}")
This script demonstrates how to send a "multipart/alternative" email, which includes both a plain text version and an HTML version. Email clients will choose the best version to display.
Comments
Loading the discussion…