How to send email in Python? (the simplest approach)
Sending emails from Python code is simple. It can be used for automation and notification apps. In this article we will create send_email()
function that will simplify the email sending. We will use Python built-in packages smtplib
and email
. Let's start sending emails with Python!
How to send email in Python?
The simplest approach is to use the following code:
# import packages
# below packages are built-in - no need to install anything new!
# yupi :)
import smtplib
from email.message import EmailMessage
# set your email and password
# please use App Password
email_address = "my-gmail-address@gmail.com"
email_password = "app-password-for-gmail"
# create email
msg = EmailMessage()
msg['Subject'] = "Email subject"
msg['From'] = email_address
msg['To'] = "to-address@gmail.com"
msg.set_content("This is eamil message")
# send email
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(email_address, email_password)
smtp.send_message(msg)
The email is sent with 3 last lines of code! And you don't need to install any additional packages to make it work (I like it!). The above code snippet is using Gmail SMTP (Simple Mail Transfer Protocol) server. If you are using different email provider then you need to change the smtp.gmail.com
to your provider address and change the port number (465
). You need to set email_address
and email_password
variables to yours. For email password please generate the App Password
for your Gmail. Here is a link with docs how to generate the App Password
for Gmail account. It might be a good idea to create a new Gmail account only for use in Python scripts (a throwaway account).
The above code construct EmailMessage
object. It is easy to manipulate. To set the subject of the email just change the string assigned to msg['Subject']
. The email content is set with msg.set_content("This is email message")
.
The above code is simple and can be used for quick experiments. If you are going to use it in serious project let's do some code refactoring.
Don't keep password in the code!
Please don't keep secrets hard coded. Please don't push them to the repository. Please keep all secrets as environment variables or in the .env
file. There is a fatnatstic package python-dotenv
for loading environment variables from .env
file. Please do not push .env
file to the repository. Please add .env
to .gitignore
.
You can easily install python-dotenv
with:
pip install python-dotenv
Then create .env
file:
EMAIL_ADDRESS=my-gmail-address@gmail.com
EMAIL_PASSWORD=app-password-for-gmail
Please keep the .env
file in the same directory as your code. To load values from .env
you can use the following code:
import os
from dotenv import load_dotenv
_ = load_dotenv()
email_address = os.environ.get("EMAIL_ADDRESS")
email_password = os.environ.get("EMAIL_PASSWORD")
OK, our code looks better. The next step will be to turn it into a nice function.
Python send email as a single function
The Python code for email sending can be included in a single send_email()
function. It will accept three arguments:
to
- address to whom send an email,subject
- the email subject,message
- the email content.
The code is below:
import os
import smtplib
from email.message import EmailMessage
from dotenv import load_dotenv
_ = load_dotenv()
def send_email(to, subject, message):
email_address = os.environ.get("EMAIL_ADDRESS")
email_password = os.environ.get("EMAIL_PASSWORD")
# create email
msg = EmailMessage()
msg['Subject'] = subject
msg['From'] = email_address
msg['To'] = to
msg.set_content(message)
# send email
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(email_address, email_password)
smtp.send_message(msg)
The above code is not perfect, but it's simple. Why is it not perfect? Because there are no error handling ... Let's try to improve a little:
import os
import smtplib
from email.message import EmailMessage
from dotenv import load_dotenv
_ = load_dotenv()
def send_email(to, subject, message):
try:
email_address = os.environ.get("EMAIL_ADDRESS")
email_password = os.environ.get("EMAIL_PASSWORD")
if email_address is None or email_password is None:
# no email address or password
# something is not configured properly
print("Did you set email address and password correctly?")
return False
# create email
msg = EmailMessage()
msg['Subject'] = subject
msg['From'] = email_address
msg['To'] = to
msg.set_content(message)
# send email
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(email_address, email_password)
smtp.send_message(msg)
return True
except Exception as e:
print("Problem during send email")
print(str(e))
return False
The above code is better. We added exception handling and check for email and password setup. The function send_email()
returns True
for successful email send and False
otherwise.
Summary
The above Python code makes email sending easy. It can be a great start for creating some automation or notification systems. If you would like to have more functionality, you can code it yourself or use existing packages. I would recommend yagmail
for advanced email sending (if you would like to send attachments, HTML version of the content). The usage of yagmail
is simple:
# after installation with
# pip install yagmail[all]
import yagmail
yag = yagmail.SMTP(EMAIL_ADDRESS, EMAIL_PASSWORD)
yag.send("to@someone.com", "subject", "message")
If you are using Django web framework, you can use send_mail()
or send_mass_mail()
from django.core.mail
. If you are going to send many emails daily you sould consider transactional email service providers like: AWS SES, SendGrid, MailGun, MailJet. They have some free plans. The Gmail service let's you send 500 emails per day. You need to check which one fits you.
If you have any questions or need help please subscribe to the newsletter below. In the form, you can leave feedback, comment, or question. We do our best to respond quickly :)