Sending Email with Python
Sending email is a very common task in any system. You probably found this tutorial because you want to send emails using Python. In this tutorial, we will learn how to send emails with and without attachment/HTML contents in Python.
After complete the tutorial, I have combined all code example to one beautiful CLI. Check out the project repository to get the full code example, and you can see a beautiful CLI as below:
Getting Started
To get started with the tutorial, we have to set up an SMTP Server and log in to send out the email. For learning purposes, we have two choices for an SMTP server that are a local SMTP Server or connect to third-party SMTP service. In this post, we will use Gmail SMTP, if you would like to use another service such as Outlook, Mailchimp, etc, just leave a comment to let us know.
1. Run a local SMTP Server
For debugging, Python offers us a tool to run a local SMTP that is installed along with Python. By using smtpd
, we run a local SMTP server. The server won’t send the email to the internet. Instead, it will print the email to your console.
Open your console/terminal and execute the below command to start the local SMTP server:
python -m smtpd -c DebuggingServer -n localhost:1025
2. Setting up a Gmail account
Because of the popular of Gmail. Through the rest of the tutorial, we assume to use Gmail SMTP for development. To get started, make sure you follow precisely below step to enable your Gmail account for development.
- Register your Gmail account.
- Allow less secure app. Turn this option ON to allow your code to send emails by using your Gmail account.
Establishing a secure connection to Gmail SMTP
Whenever connecting to Gmail SMTP, make sure we always use a secure connection. With the secure connection, your message and credential will be encrypted, so other guys are not easy to reach your sensitive information.
Gmail SMTP allows us to establish a secure connection by using SSL (Secure Sockets Layer) or TLS (Transport Layer Security) protocol. Following it, the smtplib
module also gives us two ways to connect to any SMTP service with SSL/TLS protocol by using SMTP_SSL()
and .starttls()
.
Using SSL Protocol
The code below is an example of how to establish an SSL connection to the SMTP server. Gmail SMTP server is smtp.gmail.com
and the default port of SSL is 465
Make sure you have changed “test@pythongeeks.net” on your own email
import smtplib, ssl
context = ssl.create_default_context()
password = input("Your password: ")
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login("test@pythongeeks.net", password)
# TODO: Sending your email here
Using TLS Protocol
To set up a TLS connection, we will set up an unsecured SMTP connection first. After that, encrypt the unsecured connection by using .starttls()
. It is very different from SSL while we directly establish a secured connection.
import smtplib, ssl
password = input("Your password: ")
context = ssl.create_default_context()
with smtplib.SMTP("smtp.gmail.com", 587) as server:
server.starttls(context=context) # Secure the connection with TLS
server.login("test@pythongeeks.net", password)
# TODO: Sending your email here
Sending A Plain-Text Email
Before diving deeper into sending an email with Python, we will send a simple email with plain-text only. The body of the email can be created by any text editor. There is no HTML tag, CSS class or attachment.
We will put the function .sendmail()
precisely at TODO position in the above example TODO: Sending your email here
body = """
Hi there,
This message is sent from Python Geeks.
Have a good day!
"""
server.sendmail(from_email, to_email, body)
Emailing with HTML content
Most of the time when you send an email, you would like to send a fancy mail. Sometimes it contains a beautiful HTML, sometimes it has an attachment. As a backend developer, we even have to deal with a feature that sending the marketing mail to the list subscribers. To deal with it, Python gives us the email
module.
First of all, we use both the email
module and the smtplib
module to send an email with HTML content.
import smtplib, ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
password = input("Your password: ")
context = ssl.create_default_context()
msg = MIMEMultipart('alternative')
msg['Subject'] = "[Python Geeks] Sending Email With Python"
msg['From'] = "test@pythongeeks.net"
msg['To'] = "receiver@pythongeeks.net"
# Plain-text version of content
plain_text = """\
Hi there,
This message is sent from Python Geeks.
Visit us here https://pythongeeks.net
Have a good day!
"""
# html version of content
html_content = """\
<html>
<head></head>
<body>
<p>Hi there,</p>
<p>This message is sent from Python Geeks.</p>
<p>Visit us here
<a href="https://pythongeeks.net">
Python Geeks
</a>
</p>
</body>
</html>
"""
text_part = MIMEText(plain_text, 'plain')
html_part = MIMEText(html_content, 'html')
msg.attach(text_part)
msg.attach(html_part)
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login("test@pythongeeks.net", password)
server.send_message(msg)
In this example, we create a MIMEMultipart('alternative')
message. It means we are creating an email message within the plain-text version and an alternative version – HTML version. Therefore, we have defined two-part of content separately and attach it to the main message by using .attach()
Note: Be noticed that you need to replace the login account (test@pythongeeks.net) on your own.
Emailing with an attachment
After sending an HTML email, we would like to try more by attaching an email to this email before sending it. The code below will show you how to deal with the attachment:
import mimetypes
import smtplib, ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
password = input("Your password: ")
context = ssl.create_default_context()
msg = MIMEMultipart('alternative')
msg['Subject'] = "[Python Geeks] Sending Email With Python"
msg['From'] = "test@pythongeeks.net"
msg['To'] = "receiver@pythongeeks.net"
# Plain-text version of content
plain_text = """\
Hi there,
This message is sent from Python Geeks.
Visit us here https://pythongeeks.net
Have a good day!
"""
# html version of content
html_content = """\
<html>
<head></head>
<body>
<p>Hi there,</p>
<p>This message is sent from Python Geeks.</p>
<p>Visit us here
<a href="https://pythongeeks.net">
Python Geeks
</a>
</p>
</body>
</html>
"""
text_part = MIMEText(plain_text, 'plain')
html_part = MIMEText(html_content, 'html')
msg.attach(text_part)
msg.attach(html_part)
# Define MIMEImage part
# Remember to change the file path
file_path = '../assets/level_up_your_python.png'
ctype, encoding = mimetypes.guess_type(file_path)
maintype, subtype = ctype.split('/', 1)
with open(file_path, 'rb') as fp:
img_part = MIMEImage(fp.read(), _subtype=subtype)
# Set the filename for the attachment
img_part.add_header('Content-Disposition', 'attachment', filename='level_up_your_python')
msg.attach(img_part)
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login("test@pythongeeks.net", password)
server.send_message(msg)
In the example, we easily attach an image to email by using MIMEImage
. We also attach a variety of file types in the email. For example, using MIMEAudio
for the audio file or MIMEBase
for the base64 data.
Summary
Congratulation! You have just done a quite long tutorial. Let summary what we got through this tutorial. Although it is a long tutorial, there are only two main points to remember:
- Using
smtplib
to set up an SMTP connection within the SSL/TLS protocol. - Using the
email
module, especially MIMEMultipart, we can deal well with complicated emails such as attachment or HTML content.
For more Python tutorials, please visit our Python Tutorials page and enjoy it and share it with other Python Geeks.
References
To completed this post, we have referenced a lot of sources. In the references also contains many other examples, we suggest the reader reach the below sources to get a deeper understanding:
The post Sending Email With Python appeared first on Python Geeks.
Top comments (0)