Do you want to send emails from your Python application?
Whether you’re a developer looking to automate email sending or build robust email functionality into your Python applications, this tutorial covers everything from basic implementation to advanced features.
In this post, you’ll learn how to send emails with Python using SMTP. I’ll also show you how to send emails through the SendLayer API.
What Is SMTP?
Simple Mail Transmission Protocol (SMTP) is a service email providers use to send emails online. Transactional email services like SendLayer provide an SMTP server (smtp.sendlayer.net) that can be used to send emails through third-party software or programmatically.
How to Send an Email With Python
In this section, I’ll show you the 2 ways to send emails in Python.
Prerequisites
Below are some requirements you’ll need to meet to follow along with this guide:
- Python installed on your machine. I’m using Python version 3.x and I recommend using it as well. Download the latest Python version 3 here
- Knowledge of the Python programming language
- A SendLayer account. You can get started with the trial account that lets you send up to 200 emails for free
After creating your SendLayer account, make sure to authorize your domain. This step is essential to improve your site’s email deliverability. With that, you’re all set up and ready to send your first email in Python.
How to Send an Email With SMTP in Python
Python’s smtplib
library allows you to send emails using an SMTP server. I’ll use SendLayer’s SMTP server in this guide.
However, the steps are similar for the Gmail SMTP server or any other SMTP server you intend to use.
To get started with SendLayer, you’ll need to access the login credentials for your SMTP account.
For this, log in to your SendLayer account and select the Settings sidebar menu. Then select the SMTP Credentials tab.

You’ll see the SMTP credentials required to use SendLayer’s SMTP server. The Host and Port number are the same for all users. However, the Username and Password details are unique to your SendLayer account.
You can leave this browser tab open to access the SMTP server details easily.
Send a Plain Text Email
After you’ve gotten the SMTP credentials, you’re ready to start sending emails in your Python app. To do so, create a new Python script or open an existing file in your project.
The first step is to import the smtplib
library.
import smtplib
Next, I’ll create an SMTP instance using the library we just imported.
server = smtplib.SMTP('smtp.sendlayer.net', 587)
The server variable is where we establish the connection between SendLayer and the Python script. The 2 arguments we specified in the SMTP()
function correspond to the SMTP Host and Port number SendLayer provides.
After initiating the connection, we’ll need to secure it through TLS (Transport Layer Security). This protocol encrypts the connection between your script and SendLayer’s SMTP server.
server.starttls()
Next, we’ll authenticate the connection using the SMTP login details. Recall that I asked you to keep the browser tab with your SendLayer SMTP details open. You’ll need the username and password now.
server.login('username', 'password')
Ensure you replace username and password in the snippet above with your actual SMTP login credentials.
Sending the Email
The final step is where we send the actual email using the sendmail()
function. This function accepts 3 arguments: sender’s email, recipient’s email, and email message.
server.sendmail('[email protected]', '[email protected]', "This is a test email sent from Python")
Note: If you’re using SendLayer to send your emails, the sender email needs to be at the domain you’ve authorized in SendLayer. For instance, if you authorized example.com
, your sender email domain should be @example.com
.
Putting it all together:
import smtplib
server = smtplib.SMTP("smtp.sendlayer.net", 587)
server.starttls()
server.login("username", "password")
server.sendmail("[email protected]", "[email protected]", "This is a test email sent from Python")
print("Email sent successfully")
I added a print statement to the code that’ll notify us when running the code if the email was sent successfully.
To test the code, open a terminal window and run the command below
python3 email_script.py
email_script.py should correspond to the file name where you added the script. After running the script, you should receive an email in the recipient’s inbox.

Send an HTML Email
The implementation above works great if you only intend to send plain text emails. However, modern emails include HTML content like bolded text, images, buttons, links, etc.
To send such emails, you’ll need to use the HTML syntax within the email message. Fortunately, Python’s email
library lets you format emails to support HTML syntax.
Here’s a basic implementation:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# SMTP Server details
port = 587
smtp_server = "smtp.sendlayer.net"
username = "paulie" # Your username generated by SendLayer
password = "sendlayer_smtp_password" # Your password generated by SendLayer
sender_email = "[email protected]"
receiver_email = "[email protected]"
# Email content
subject = "HTML Email Example"
html_message = """\
<html>
<body>
<p>Hi,<br>
This is a <b>test</b> email sent from <a href="https://www.python.org">Python</a> using <a href="https://sendlayer.com">SendLayer's</a> SMTP server</p>
</body>
</html>
"""
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# Attach the HTML part
message.attach(MIMEText(html_message, "html"))
# Send the email
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(username, password)
server.sendmail(sender_email, receiver_email, message.as_string())
print('Email sent successfully')
In the snippet above, we’re importing the MIMEText
and MIMEMultipart
classes from the email
library. The MIMEMultipart
class allows us to specify the different components of an email like the subject, sender address, recipient address, etc.
We use the MIMEText
method to specify the format for the email message. It accepts 2 arguments: message and format.
The message is the actual HTML message you intend to send, corresponding to the html_message variable in the code above. The format we specified is “html”. You can use “plain” if you’d like to send a plain text message.
When you run the snippet above, it should send the email message with the email subject and HTML content properly formatted.

Send Emails to Multiple Recipients in Python
Python’s email library supports sending emails to multiple recipients by default. Once you specify the recipient email addresses in a list, the sendmail()
method will auto-detect each email address and send the mail to the recipients.
The only drawback to this approach is that emails are sent as a whole. This essentially means the process will complete when the script has looped through the list of recipients. It might also take a while if you have a large list of recipients.
Pro Tip: For better email deliverability, I suggest sending emails to multiple recipients through an API service. Here’s how to use SendLayer’s API.
Adding the Snippet
Here’s the snippet for this implementation.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# SMTP Server details
port = 587
smtp_server = "smtp.sendlayer.net"
username = "paulie" # Your username generated by SendLayer
password = "sendlayer_smtp_password" # Your password generated by SendLayer
sender_email = "[email protected]"
# Recipient email addresses list
receiver_emails = ["[email protected]", "[email protected]", "[email protected]"]
# Email content
subject = "Email Example to Multiple Recipients"
html_message = """\
<html>
<body>
<p>Hi,<br>
This is a <b>test</b> email sent from <a href="https://www.python.org">Python</a> using <a href="https://sendlayer.com">SendLayer's</a> SMTP server</p>
</body>
</html>
"""
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["Subject"] = subject
# Join the list of receiver emails into a string separated by commas
message["To"] = ", ".join(receiver_emails)
# Attach the HTML part
message.attach(MIMEText(html_message, "html"))
# Send the email
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(username, password)
server.sendmail(sender_email, receiver_emails, message.as_string())
print('Email sent successfully')
In the code above, I’ve created a list with each recipient’s email and stored the value in the receiver_emails variable.
Next, I combined the list into a single string and separated each email address with a comma. This step is essential to ensure the recipient header in the email message is populated with all the email recipients.
The sendmail()
function will loop through the list and send the email to each recipient.
Sending Emails With Attachments
You can also add attachment files to your emails before sending them out. For this, we’ll need the MIMEBase
class and the encoders
function from the email
library. I’ve gone ahead to add the import statement below to your code.
from email.mime.base import MIMEBase
from email import encoders
Adding the Snippet
Here is the full code snippet to handle attachment files in email messages.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
# SMTP Server details
port = 587
smtp_server = "smtp.sendlayer.net"
username = "paulie" # Your username generated by SendLayer
password = "sendlayer_smtp_password" # Your password generated by SendLayer
sender_email = "[email protected]"
receiver_email = "[email protected]"
# Email content
subject = "Email Example with Attachment"
html_message = """\
<html>
<body>
<p>Hi,<br>
This is a <b>test</b> email sent from <a href="https://www.python.org">Python</a> using <a href="https://sendlayer.com">SendLayer's</a> SMTP server <br>
The email also includes an attachment</p>
</body>
</html>
"""
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["Subject"] = subject
# Join the list of receiver emails into a string separated by commas
message["To"] = ", ".join(receiver_emails)
# Attach the HTML part
message.attach(MIMEText(html_message, "html"))
# Specify the file path for the attachment
filename = "./path/to/attachment/file.pdf" # Change this to the correct path
# Open the file in binary mode
with open(filename, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header("Content-Disposition", f"attachment; filename= {filename}")
# Add attachment to message
message.attach(part)
# Send the email
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(username, password)
server.sendmail(sender_email, receiver_email, message.as_string())
print('Email sent successfully')
Code Explanation
In the snippet above, we use the MIMEBase
class to specify the attachment type. Setting it to application/octet-stream
means it’s a generic file and works for all file formats. Email clients will read it as an attachment file.
Attachment files need to be encoded in base64 to ensure it is properly transmitted. The line encoders.encode_base64(part)
handles that.
Next, we’re including the attachment file in the email header so email clients know to treat it as an attachment using the part.add_header()
function.
Finally, we add the attachment to the message so it’s included in the mail using the message.attach(part)
function.
When you test the implementation, you should see the file attached to the email message.

Send Emails Via API Using SendLayer
Sending emails through SMTP works well for smaller projects. However, it is less secure and slower when compared to using an API-based email provider. Using an API-based service is also much faster especially when you need to send bulk emails.
Fortunately, platforms like SendLayer provide API endpoints you can use to send single and bulk emails programmatically. I’ll show you how to set up a program that uses the SendLayer email API to send emails.
Send HTML Content Email With SendLayer API
To get started, open your terminal and run the command below to install requests (if not installed already).
pip install requests
After installing the library, create a new Python file (you can use any name), just make sure to use the .py file extension. For this tutorial, I’ve named mine as sl_api_email.py
.
Now, open the file you just created and add the following import statement.
import requests
import json
The requests library is used to send requests to an API endpoint. For instance, sending a post request to the email endpoint will trigger the email-sending event.
Since most API requests are sent in JSON format, we’ll use the json
library we imported to translate the request into a format Python understands.
Understanding SendLayer API Parameters
To send an email using SendLayer API, you’ll need 3 parameters:
- URL: This is the API endpoint for sending emails. For SendLayer, this endpoint is available at
https://console.sendlayer.com/api/v1/email
- Headers: This is where you’ll define the format for the request and also authenticate your connection
- Payload: This contains the actual JSON requests with details for sending an email like the sender and recipient email address.
Note: To learn more about how SendLayer’s API works, be sure to check our beginner’s guide to using the SendLayer API.
Adding the Snippet
Let’s proceed to use the API endpoint to send an email. For this, copy and paste the code snippet below. I’ll explain what each line does afterward.
import requests
import json
def send_sendlayer_email(payload):
# SendLayer API endpoint
url = 'https://console.sendlayer.com/api/v1/email'
headers = {
"Authorization": "Bearer your-sendlayer-api-key",
"Content-Type": "application/json"
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
return response.text
# Email data
payload = {
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Pattie Paloma",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"PlainContent": "This is the plain text email.",
"Tags": [
"tag-name",
"daily"
],
"Headers": {
"X-Mailer": "Test mailer",
"X-Test": "test header"
}
}
# Call the function
response_text = send_sendlayer_email(payload)
print(response_text)
In the snippet above, we’ve defined a function send_sendlayer_email()
that accepts one parameter, payload
. The payload variable contains the JSON request with the email message.
Within the function, we specify the url
and headers
variable. The url variable is SendLayer’s endpoint for sending emails. In the headers
block, we define the Authorization and Content-Type. You’ll need to replace your-sendlayer-api-key
with your actual API key.
Retrieving SendLayer API Key
To get your API key, log in to your SendLayer account. Once you’re logged in, click the Settings menu and select the API Keys tab.

Then click the copy icon next to Default API key to copy it.

The requests.post()
line of code is where we send the actual post request. The post function accepts 3 parameters; url, headers, and data. The data contains details about the email message. This is usually in JSON format, but we’re using json.dumps()
to translate it to a Python command.
The return statement for the function is response.text. Which will print a message in the console about our email status.
In the payload variable, I’ve specified the JSON format for the email I intend to send. You’ll need to update the name and email address in the “From” field to match your sender email.
Note: The From email domain needs to match the domain you authorized in your SendLayer account. For instance, if you authorized example.com in SendLayer, the from email needs to use @example.com
extension.
Also, update the name and email in the “To” field to match the recipient’s name and email.
To run this code, open a terminal window and run the command below.
python3 sl_api_email.py
You should see a message similar to the one below logged in the terminal.
{"MessageID":"451c0388-cdd4-4a0e-b554-06a381880b14"}
When you open the email inbox of the recipient, you’ll see the email message we just sent out.

Send Email to Multiple Recipients
With SendLayer’s API, you can send emails to multiple recipients from your Python script. To do so, you’ll just need to add to the objects in the “To” list in the JSON payload. Here is an example:
payload = {
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Pattie Paloma",
"email": "[email protected]"
},
{
"name": "John Doe",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test emails sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"PlainContent": "This is the plain text email.",
"Tags": [
"tag-name",
"daily"
],
"Headers": {
"X-Mailer": "Test mailer",
"X-Test": "test header"
}
}
Using the “CC” and “BCC” Fields
SendLayer also lets you add more recipients using the Cc and Bcc feature email servers support. To use this, simply add the “CC” and “BCC” fields to the JSON payload. Within each field, add the recipients’ email address object which should be similar to the objects in the “To” field. Here is an example snippet:
payload = {
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Pattie Paloma",
"email": "[email protected]"
},
{
"name": "John Doe",
"email": "[email protected]"
}
],
"CC": [
{
"name": "David O",
"email": "[email protected]"
}
],
"BCC": [
{
"name": "Jane Doe",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"PlainContent": "This is the plain text email.",
"Tags": [
"tag-name",
"daily"
],
"Headers": {
"X-Mailer": "Test mailer",
"X-Test": "test header"
}
}
Note: There is a limit to the number of emails you can add to the “To”, “CC”, and “BCC” fields when sending emails through SendLayer’s API. Please see our guide to learn more about these limits.
Sending Emails With Attachment
SendLayer’s email API supports adding attachments to email messages. To attach files to your emails, you’ll need to encode them to base64, which is a format email services understand. Here’s how to attach files using SendLayer API:
Start by importing the base64 library.
import base64
After that, I’ll create a function to handle decoding the attachment files.
def read_attachment(path):
with open(path, 'rb') as file:
file_content = file.read()
encoded_content = base64.b64encode(file_content)
return encoded_content.decode('utf-8')
The function above accepts one parameter, which is the file path. Within the function, we’re reading the file and then using the base64 library to encode it.
Updating the Payload
After adding the function, update the payload field to include the “Attachments” field as seen in the snippet below.
# Email data
payload = {
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "John Doe",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"PlainContent": "This is the plain text email.",
"Tags": [
"tag-name",
"daily"
],
"Headers": {
"X-Mailer": "Test mailer",
"X-Test": "test header"
}
"Attachments": [
{
"Content": f"{read_attachment('path/to/attachment/file.pdf')}", # Change to the path to your file
"Type": "application/pdf", # Change to the type of your attachment
"Filename": "file.pdf", # Update this with the file name
"Disposition": "attachment",
"ContentId": 0
}
]
}
The “Content” field contains the base64 string of the attachment file. We get the decoded value from the read_attachment()
function. Make sure to update the function’s argument with the path to your attachment file.
Including Multiple Attachment Files
You can add multiple attachment files to the list. Simply create a new key-value pair within the “Attachments” list.
payload = {
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "John Doe",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"PlainContent": "This is the plain text email.",
"Tags": [
"tag-name",
"daily"
],
"Headers": {
"X-Mailer": "Test mailer",
"X-Test": "test header"
}
"Attachments": [
{
"Content": f"{read_attachment('path/to/attachment/file.pdf')}", # Change to the path to your file
"Type": "application/pdf", # Change to the type of your attachment
"Filename": "file.pdf", # Update this with the file name
"Disposition": "attachment",
"ContentId": 0
},
{
"Content": f"{read_attachment('path/to/attachment/picture.jpg')}", # Change to the path to your file
"Type": "image/jpg", # Change to the type of your attachment
"Filename": "picture.jpg", # Update this with the file name
"Disposition": "attachment",
"ContentId": 0
}
]
}
In the code above, I only included the payload variable. The complete snippet should also contain the send_sendlayer_email()
function.
When you run the script, both attachments should be included in the email message.

Best Practices For Sending Emails Using Python
If the project you’re working on is an enterprise application, there are security considerations to keep in mind. Below, I’ll share some tips to optimize your Python application.
1. Secure Sensitive Credentials
Details such as API keys, SMTP username and password should be personal and not shared with the general public. If your codebase is public, it’ll be easy for attackers to access sensitive details.
Here’s how to use environment variables to store server details in Python:
First, create a .env
file in your project’s root directory. Inside this file, you’ll need to store the server details as variables:
# .env file
EMAIL_API_KEY=your_sendlayer_api_key
[email protected]
SENDER_NAME=Sender Name
API_URL=https://console.sendlayer.com/api/v1/email
The next step is to install the dotenv
library for Python. To do so, run the command below in your terminal window:
pip install python-dotenv
Once you’ve installed the library, you’re ready to load the .env file to your main project file. Here’s how to do it:
import os
from dotenv import load_dotenv
In the code above, we’re importing the built-in os
module and the dotenv
library we just installed. After that update the send email function to read the values from the environment variable we created.
def send_sendlayer_email():
# Get values from environment variables
api_key = os.getenv('EMAIL_API_KEY')
sender_email = os.getenv('SENDER_EMAIL')
sender_name = os.getenv('SENDER_NAME')
api_url = os.getenv('API_URL')
The rest of the code should remain unchanged.
2. Implement Error Handling
One drawback to our current implementation is that there is no way to know the exact cause if an email isn’t sent to the recipient(s).
To account for such issues, we need to implement an error-handling mechanism to know why emails fail to deliver. I’ll use the try-except syntax in Python to implement the checks.
import requests
import json
def send_sendlayer_email():
# Your SendLayer API key
api_key = "YOUR_API_KEY_HERE"
# SendLayer email API endpoint
url = "https://console.sendlayer.com/api/v1/email"
# Email data
payload = {
"From": {
"name": "Paulie Paloma",
"email": "[email protected]"
},
"To": [
{
"name": "Pattie Paloma",
"email": "[email protected]"
},
{
"name": "John Doe",
"email": "[email protected]"
}
],
"Subject": "This is the email subject",
"ContentType": "HTML",
"HTMLContent": "<html><body><p>This is a test email sent with the <a href=\"https://sendlayer.com\">SendLayer</a> API!</p></body></html>",
"PlainContent": "This is the plain text email.",
"Tags": [
"tag-name",
"daily"
],
"Headers": {
"X-Mailer": "Test mailer",
"X-Test": "test header"
}
}
# Headers
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
try:
# Send the request
response = requests.post(url, headers=headers, data=json.dumps(payload))
# Check if the request was successful
if response.status_code == 200:
print("Email sent successfully!")
print(response.json())
else:
print(f"Failed to send email. Status code: {response.status_code}")
print(response.text)
except Exception as e:
print(f"An error occurred: {str(e)}")
# Call the function
send_sendlayer_email()
Code Explanation
In the code snippet above, I added the try and except block to catch errors as they occur. Within the try block, we’re checking to see if the status code for the request is 200 (which indicates the request was successful).
Otherwise, we want to print out a response to let the user know their email hasn’t been delivered. Here is an example of an error you might encounter:
Failed to send email. Status code: 401
{"Errors":[{"Code":13,"Message":"Invalid SenderAPIKey"}]}
The error above indicates your email failed due to an invalid API key. If you encounter this error make sure to replace the API key placeholder with your actual SendLayer API key.
FAQs –– Using Python to Send Emails
These are answers to some of the top questions we see on how to send emails using Python.
How to run a Python script?
To run a Python script, you’ll need to open up a terminal window and then navigate to the root directory of the project. Once there, specify the version of Python you’re running, give a space, and then mention the script name you want to run.
For instance, if your file name is send_email.py
, enter the command python3 send_email.py
in your terminal window to run the script.
How do I send an email using Python without using SMTP?
The easiest way to send an email in Python without SMTP is with an API service provider. Transactional email services like SendLayer provide an API for sending emails through their service.
That’s it! Now you know how to send email in Python via SMTP and through an API provider like SendLayer.
Next, would you like to learn about the difference between different sending methods? Check out our tutorial on SMTP vs API for more information.
0 comment on "How To Send an Email With Python (+ Code Snippets)"