How to send emails in Python (with script examples)
- Why use Python to send emails?
- API or smtplib?
- How to send emails with Python
- Sending emails with smtplib
- Sending emails with an API
- How to send an HTML email
- How to send a template-based email
- How to send emails with personalization
- How to send an email with an attachment
- How to send emails in bulk
- How to schedule an email
- How to retrieve activity and analytics data
- Best practices for sending emails in Python
- Flexible and customizable email sending at your fingertips
Python is a high-level language used for creating a variety of programs. Due to its readability and simplicity, it’s a preferred language for both beginners and experienced developers. Another perk is Python’s rich standard library that provides numerous functions and modules, reducing the need to write code from scratch and, as a result, the time needed for development.
When it comes to sending emails programmatically, Python offers several options to simplify the process. These include its built-in library for sending emails and simple integration with third-party libraries for added reliability and functionality. So let’s take a look at how you send emails in a Python environment via API and SMTP (Simple Mail Transfer Protocol).
Why use Python to send emails?
Aside from Python’s clean and simple syntax, which makes it easy to create and maintain email-sending scripts, and the built-in smtplib library and email package, we think Python has some other nice benefits that make it a great choice for automating email tasks.
1. Flexibility and customization options: With Python, you can easily customize email content dynamically, send HTML emails, and use various MIME types.
2. Easy integration with other services: Python very easily integrates with APIs, databases and more so you can send emails based on data from numerous sources. You can connect with third-party libraries and services, like MailerSend, for more advanced functionality including tracking, analytics, bulk sending, and more.
3. Scalability: You can scale Python scripts to handle large volumes of emails so as your sending requirements grow, your implementation can be easily adapted.
4. Security protocols: Secure email sending is supported with TLS/SSL to ensure emails are encrypted and secure.
5. Large community: Python is open-source and has a large online community in which you can access tutorials, forums, and extensive documentation for troubleshooting and help with implementation.
Python scripts are effective for automating tasks—just like sending emails. So this makes it a good solution for sending automated notifications and alerts, automated reports, and transactional emails such as order confirmations, password resets, shipping notifications, and more.
Choosing between an email API or smtplib (SMTP)
Python’s built-in smtplib library is a great solution for simple, custom email-sending implementations. It provides full control over email content, is pretty cost-effective, and of course has direct integration into Python scripts.
But if you want more advanced features and functionality such as tracking, analytics, reporting, email template builders and more, plus increased reliability and scalability, an email API is the way to go.
Here’s a quick comparison of the two:
Feature | smtplib | Third-Party Email API |
Ease of Setup | Simple setup using built-in libraries | Simple, requires API key and setup with provider |
Email Customization | High - Full control over email content | High - Supports templates and personalization |
Security | Supports TLS/SSL | Advanced security features, compliance tools, plus TLS/SSL |
Reliability | Depends on SMTP server stability | High reliability with built-in retries |
Scalability | Limited by server and connection handling | Highly scalable, designed for high volumes of emails |
Tracking and Analytics | Minimal, requires additional implementation and tools | Built-in tracking, analytics, and reporting |
Cost | Free (excluding SMTP server costs) | May involve costs based on usage tiers |
Integration | Manual integration with Python code | Easy integration with SDKs and RESTful APIs |
Error Handling | Basic error handling | Advanced error handling and logging |
Rate Limiting | Depends on SMTP server | Managed rate limiting and throttling |
Documentation and Support | Extensive Python documentation | Provider-specific documentation and support |
Compliance | Basic compliance handled manually | Compliance features included (e.g., GDPR, CAN-SPAM) |
Attachments and MIME Types | Full support via email library | Full support with simpler interfaces |
Deployment | Runs anywhere Python is supported | Runs anywhere with API access, often with SDKs |
How to send emails with Python
Now we’ve been through the features and limitations of using smtplib and an email API, we’ll show you how to send emails with both methods, beginning with setting up smtplib and then using your MailerSend SMTP credentials to send emails.
If you’d like to try this out with MailerSend, you can sign up for free and access a trial domain for testing purposes.
For SMTP:
1. Create an account for free and sign in.
2. From the dashboard, click Domains in the left-hand menu. If you’d like to use your own domain, you can add one by clicking Add domain, or you can use the trial domain.
3. Next to the domain you want to use, click Manage. Scroll down to the SMTP section and click Generate new user. A pop-up will appear, enter a recognizable name for your new SMTP user then click Save user.
4. Your SMTP user credentials will be generated and will include a username, password, server address, and port number. Click Save user. You can then save the credentials somewhere or access them at any time by clicking Manage.
Sending emails with the smtplib module
To get started with smtplib in Python, you’ll want to create some environment variables to store any sensitive information such as login credentials. This will prevent you from exposing this information in your code.
Set the environment variables in your terminal or by using a .env file in your project directory.
In your terminal:
export SENDER_EMAIL="youremail@example.com"
export EMAIL_PASSWORD="yourpassword"
export SMTP_SERVER="smtp.mailersend.net"
export SMTP_PORT="587"
With a .env file:
Create a new .env file in your project directory with the following:
SENDER_EMAIL=youremail@example.com
EMAIL_PASSWORD=yourpassword
SMTP_SERVER=smtp.mailersend.net
SMTP_PORT=587
Then use the python-dotenv package to load the .env file:
pip install python-dotenv
You can then use os.getenv in your script to fetch your sensitive information via the environment variables.
In the script, we’ll import the required libraries, these being os for accessing the environment variables, smtplib for handling the SMTP connection, and email.mime classes for creating the email content.
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Set up email details from environment variables
sender_email = os.getenv("SENDER_EMAIL")
password = os.getenv("EMAIL_PASSWORD")
smtp_server = os.getenv("SMTP_SERVER")
smtp_port = int(os.getenv("SMTP_PORT"))
# Define the receiver email
receiver_email = "receiver@example.com"
subject = "Welcome to Amazing Company"
body = """\
Hey there!
Thanks for joining us at Amazing Company. Your email has been verified and your account has been created.
Head to the website to login and start using our features."""
# Create the email message
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# Attach the email body to the message
message.attach(MIMEText(body, "plain"))
# Establish a connection to the SMTP server and send the email
try:
# Connect to the SMTP server
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # Secure the connection
server.login(sender_email, password) # Log in to the SMTP server
server.sendmail(
sender_email, receiver_email, message.as_string()
) # Send the email
print("Email sent successfully")
except Exception as e:
print(f"Error: {e}")
Send an HTML email with smtplib
By making a few tweaks to the script, you can send HTML emails instead of plain text.
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Set up email details from environment variables
sender_email = os.getenv("SENDER_EMAIL")
password = os.getenv("EMAIL_PASSWORD")
smtp_server = os.getenv("SMTP_SERVER")
smtp_port = int(os.getenv("SMTP_PORT"))
# Define the receiver email
receiver_email = "receiver@example.com"
subject = "Welcome to Amazing Company"
body = "Hey there! Thanks for joining us at Amazing Company. Your email has been verified and your account has been created. Head to the website to login and start using our features."
# HTML content
html_content = """
<html>
<body>
<h1>Hey there! Thanks for joining us at Amazing Company.</h1>
<p>Your email has been verified and your account has been created. Head to the website to login and start using our features.</p>
</body>
</html>
"""
# Create the email message
message = MIMEMultipart("alternative")
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# Attach the plain text and HTML parts to the message
text_part = MIMEText(body, "plain")
html_part = MIMEText(html_content, "html")
message.attach(text_part)
message.attach(html_part)
# Establish a connection to the SMTP server and send the email
try:
# Connect to the SMTP server
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # Secure the connection
server.login(sender_email, password) # Log in to the SMTP server
server.sendmail(sender_email, receiver_email, message.as_string()) # Send the email
print("Email sent successfully")
except Exception as e:
print(f"Error: {e}")
How to send an email with an attachment with smtplib
Let’s say we want to send an invoice to our recipient. We can send the invoice as an attachment by including the file as a MIME part of the message.
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Set up email details from environment variables
sender_email = os.getenv("SENDER_EMAIL")
password = os.getenv("EMAIL_PASSWORD")
smtp_server = os.getenv("SMTP_SERVER")
smtp_port = int(os.getenv("SMTP_PORT"))
# Define the receiver email
receiver_email = "receiver@example.com" # Replace with the actual recipient's email address
subject = "Here’s your invoice for July"
body = "We have received your payment for your subscription with Amazing Company for the month of July. Please find attached your invoice."
# HTML content
html_content = """
<html>
<body>
<p>We have received your payment for your subscription with Amazing Company for the month of July. Please find attached your invoice.</p>
</body>
</html>
"""
# Create the email message
message = MIMEMultipart("alternative")
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# Attach the plain text and HTML parts to the message
text_part = MIMEText(body, "plain")
html_part = MIMEText(html_content, "html")
message.attach(text_part)
message.attach(html_part)
# Attach a file
filename = "invoice.pdf" # Replace with your file path
try:
with open(filename, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={filename}",
)
message.attach(part)
except FileNotFoundError:
print(f"File {filename} not found. No attachment will be sent.")
# Establish a connection to the SMTP server and send the email
try:
# Connect to the SMTP server
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # Secure the connection
server.login(sender_email, password) # Log in to the SMTP server
server.sendmail(sender_email, receiver_email, message.as_string()) # Send the email
print("Email sent successfully")
except Exception as e:
print(f"Error: {e}")
How to send emails in bulk with smtplib
For some types of emails, it might make more sense to send them in bulk. For example, non-time-sensitive emails such as feedback requests. Here’s how you can do that:
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Set up email details from environment variables
sender_email = os.getenv("SENDER_EMAIL")
password = os.getenv("EMAIL_PASSWORD")
smtp_server = os.getenv("SMTP_SERVER")
smtp_port = int(os.getenv("SMTP_PORT"))
# List of recipient emails
receiver_emails = [
"recipient1@example.com",
"recipient2@example.com",
"recipient3@example.com",
"recipient4@example.com",
] # Add more recipients as needed
subject = "Give us your feedback!"
body = "We want to hear from you! We’d love to learn more about your experience with Amazing Company. It’ll only take a few minutes and you can get started by clicking here."
# HTML content
html_content = """
<html>
<body>
<h1>We want to hear from you!</h1>
<p>We’d love to learn more about your experience with Amazing Company. It’ll only take a few minutes and you can get started by clicking <a href="https://www.amazing-company.com/feedback">here</a>.</p>
</body>
</html>
"""
# Function to create the email message
def create_message(sender_email, receiver_email, subject, body, html_content):
message = MIMEMultipart("alternative")
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# Attach the plain text and HTML parts to the message
text_part = MIMEText(body, "plain")
html_part = MIMEText(html_content, "html")
message.attach(text_part)
message.attach(html_part)
return message
# Establish a connection to the SMTP server and send emails in bulk
try:
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # Secure the connection
server.login(sender_email, password) # Log in to the SMTP server
for receiver_email in receiver_emails:
message = create_message(
sender_email, receiver_email, subject, body, html_content
)
server.sendmail(
sender_email, receiver_email, message.as_string()
) # Send the email
print(f"Email sent successfully to {receiver_email}")
except Exception as e:
print(f"Error: {e}")
receiver_emails allows you to add a list of recipients to send the emails to. The SMTP connection is established once and the emails are sent in a loop to each recipient in the list.
Sending emails in Python with an email API
Using a third-party email API is a great option if you want to create more advanced workflows with additional email-sending features and tracking options. MailerSend also provides an official Python SDK, making the implementation straightforward and efficient.
If you’d like to try this out MailerSend’s email API, you can sign up for free and use a trial domain for testing purposes. It only takes a few minutes to sign up and you can start sending immediately.
To use the API:
1. Create an account for free and sign in.
2. From the dashboard, click Domains in the left-hand menu. If you’d like to use your own domain, you can add one by clicking Add domain, or you can use the trial domain.
3. Next to the domain you want to use, click Manage. In the API section, click Generate new token. A pop-up will appear, enter a recognizable name for your new API token, set the permissions, and then click Create token.
4. Your API key will be generated and displayed. Make sure you copy and save it somewhere, or download it, as you won’t be able to access this again for security purposes.
Check out our API docs.
To get started, install MailerSend’s Python SDK in your Python app:
$ python -m pip install mailersend
Python 3.6.1 or higher is required.
You’ll also need to install the requests library to make HTTP requests to the MailerSend API:
pip install requests
Next, we recommend using environment variables for your API key and other sensitive information to avoid exposing it in your code.
You can do this in your Terminal:
export MAILERSEND_API_KEY="your_api_key"
Or by creating a .env file with the following in your project directory:
MAILERSEND_API_KEY=your_api_key
How to send an HTML email with an email API and Python
Let’s send a simple HTML email using Python and the MailerSend email API. For this example, we’ll send a simple account confirmation email to our customer, Brian.
Here’s the Python script:
from mailersend import emails
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend email client with the API key
mailer = emails.NewEmail(os.getenv("MAILERSEND_API_KEY"))
# Define an empty dict to populate with mail values
mail_body = {}
# Define the sender email details
mail_from = {
"name": "Amazing Company",
"email": "hello@amazingcompany.com",
}
# Define the recipient email details
recipients = [
{
"name": "Brian Griffin",
"email": "brian@example.com",
}
]
# Define the reply-to email details
reply_to = {
"name": "Customer Support Replies",
"email": "reply@amazingcompany.com",
}
# Set the sender email details
mailer.set_mail_from(mail_from["email"], mail_body)
# Set the recipient email details
mailer.set_mail_to(recipients, mail_body)
# Set the subject of the email
mailer.set_subject("Your account has been created!", mail_body)
# Set the HTML content of the email
mailer.set_html_content(
"<h1>Welcome to Amazing Company!</h1> "
"<p>Thanks for joining us, we’re so happy to have you. Your account is ready to go.</p>"
"<p>To get started, login to your dashboard and head to your profile.</p>"
"<p>Best regards, The Amazing Company Team</p>",
mail_body,
)
# Set the plain text content of the email
mailer.set_plaintext_content(
"Welcome to Amazing Company! Thanks for joining us, we’re so happy to have you. "
"Your account is ready to go. To get started, login to your dashboard and head to your profile. "
"Best regards, The Amazing Company Team",
mail_body,
)
# Set the reply-to email details
mailer.set_reply_to(reply_to["email"], mail_body)
# Send the email and print the response (status code and data)
try:
response = mailer.send(mail_body)
print("Status Code:", response.status_code)
print("Response JSON:", response.json())
except Exception as e:
print(f"An error occurred: {e}")
How to send a template-based email
For more professional and better-looking emails, it’s always best to use a well-designed template. You can easily create great-looking, functional templates in one of MailerSend’s 3 email template builders and then simply copy the template ID and add it to your script. Let’s send an email verification templated email to another customer, Stewart.
Here’s how the script for that would look:
from mailersend import emails
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend email client with the API key
mailer = emails.NewEmail(os.getenv("MAILERSEND_API_KEY"))
# Define the sender email details
mail_from = {
"name": "Amazing Company",
"email": "hello@amazingcompany.com",
}
# Define the recipient email details
recipients = [
{
"name": "Stewart Griffin",
"email": "stewart@example.com",
}
]
# Define the variables for personalization
variables = {
"email": "stewart@example.com",
"substitutions": [
{"var": "foo", "value": "bar"},
],
}
# Set the sender email details
mailer.set_mail_from(mail_from["email"])
# Set the recipient email details
mailer.set_mail_to(recipients)
# Set the subject of the email (if needed, otherwise the template's subject will be used)
mailer.set_subject("Verify your email address to access all features.")
# Set the template ID
mailer.set_template("templateID")
# Set personalization variables
mailer.set_personalization(variables)
# Send the email and print the response (status code and data)
try:
response = mailer.send()
print("Status Code:", response.status_code)
print("Response JSON:", response.json())
except Exception as e:
print(f"An error occurred: {e}")
How to send emails with personalization
Using personalization in your transactional emails is key to the customer journey. Not only does it allow you to provide users and customers with a more personal experience, but it also allows you to deliver personalized, important details about their purchases and activity in an efficient way. You can use a single email template and personalize it to thousands of customers.
Brian has gone ahead and placed an order, so we’ll send them a personalized order confirmation email. We’ll use a loop structure to dynamically insert the products’ details.
Here’s the script:
from mailersend import emails
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend email client with the API key
mailer = emails.NewEmail(os.getenv('MAILERSEND_API_KEY'))
# Define the sender email details
mail_from = {
"name": "Amazing Company Orders",
"email": "orders@amazingcompany.com",
}
# Define the recipient email details
recipients = [
{
"name": "Brian Griffin",
"email": "brian@example.com",
}
]
# Define the personalization data
personalization = [
{
"email": "brian@example.com",
"data": {
"name": "Brian Griffin",
"var": "value",
"boolean": True,
"object": {
"key": "object-value"
},
"number": 2,
"array": [
1,
2,
3
],
"purchased_products": [
{"name": "Product 1", "price": 19.99},
{"name": "Product 2", "price": 29.99}
]
}
}
]
# Set the sender email details
mailer.set_mail_from(mail_from['email'])
# Set the recipient email details
mailer.set_mail_to(recipients)
# Set the subject of the email
mailer.set_subject("Your Amazing Company order is confirmed!")
# Set the HTML content of the email
mailer.set_html_content("""
<html>
<body>
<h1>We’ve got your order.</h1>
<p>Hi, {{name}}!</p>
<p>Thanks for shopping at Amazing Company. Your order is currently processing and will be shipped to you within 24 hours.</p>
<p>We’ll update you with a tracking number when it’s on the way.</p>
<ul>
{% for product in purchased_products %}
<li>{{product.name}} - ${{product.price}}</li>
{% endfor %}
</ul>
</body>
</html>
""")
# Set the plain text content of the email
mailer.set_plaintext_content("""
Hello {{name}},
Thank you for purchasing the following products:
{% for product in purchased_products %}
- {{product.name}} - ${{product.price}}
{% endfor %}
""")
# Set personalization variables
mailer.set_personalization(personalization)
# Send the email and print the response (status code and data)
try:
response = mailer.send()
print("Status Code:", response.status_code)
print("Response JSON:", response.json())
except Exception as e:
print(f"An error occurred: {e}")
How to send an email with an attachment
Since our customer placed an order, we need to send them a receipt or invoice. We can do this by sending the invoice file as an attachment.
from mailersend import emails
import base64
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend email client with the API key
mailer = emails.NewEmail(os.getenv('MAILERSEND_API_KEY'))
# Define the sender email details
mail_from = {
"name": "Amazing Company Orders",
"email": "orders@amazingcompany.com",
}
# Define the recipient email details
recipients = [
{
"name": "Brian Griffin",
"email": "brian@example.com",
}
]
# Define the personalization variables
variables = [
{
"email": "brian@example.com",
"data": {
"foo": "bar",
"name": "Brian Griffin"
}
}
]
# Open and read the file for attachment
with open('path-to-file', 'rb') as attachment:
att_read = attachment.read()
att_base64 = base64.b64encode(att_read).decode('ascii')
attachments = [
{
"id": "my-attached-file",
"filename": "invoice.pdf",
"content": att_base64,
"disposition": "attachment"
}
]
# Set the sender email details
mailer.set_mail_from(mail_from['email'])
# Set the recipient email details
mailer.set_mail_to(recipients)
# Set the subject of the email
mailer.set_subject("Your order is on the way.")
# Set the HTML content of the email
mailer.set_html_content("""
<html>
<body>
<h1>Your order is on the way!</h1>
<p>Hi, {{name}}!</p>
<p>We’re happy to let you know that your order is on the way and a tracking number will be sent to you shortly.</p>
<p>Please find your invoice attached.</p>
<p>Thanks and we hope you enjoyed shopping with Amazing Company!</p>
</body>
</html>
""")
# Set the plain text content of the email
mailer.set_plaintext_content("""
Your order is on the way!
Hi, {{name}}!
We’re happy to let you know that your order is on the way and a tracking number will be sent to you shortly.
Please find your invoice attached.
Thanks and we hope you enjoyed shopping with Amazing Company!
""")
# Set personalization variables
mailer.set_personalization(variables)
# Set the attachment
mailer.set_attachments(attachments)
# Send the email and print the response (status code and data)
try:
response = mailer.send()
print("Status Code:", response.status_code)
print("Response JSON:", response.json())
except Exception as e:
print(f"An error occurred: {e}")
How to send emails in bulk
Sending bulk messages isn’t just for marketing emails. You can also utilize bulk email sending for transactional emails to preserve your resources and bypass rate limiting, essentially making your email sending more efficient.
This works best when sending emails that aren’t as time-sensitive as order confirmations or email verification. Let’s prepare some emails for our customers Brian and Stewart.
from mailersend import emails
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend email client with the API key
mailer = emails.NewEmail(os.getenv("MAILERSEND_API_KEY"))
# Define the list of emails to be sent
mail_list = [
{
"from": {"email": "hello@amazingcompany.com", "name": "Amazing Company"},
"to": [{"email": "brian@example.com", "name": "Brian Griffin"}],
"subject": "What do you think of your recent order?",
"text": "Thanks for shopping with us at Amazing Company! We’d love to hear how you’ve got on with your products. If you could spare a few minutes to leave us some feedback, it will help us to provide a better service to you in the future. Click below to submit your thoughts.",
"html": '<p>Thanks for shopping with us at Amazing Company!</p><p>We’d love to hear how you’ve got on with your products. If you could spare a few minutes to leave us some feedback, it will help us to provide a better service to you in the future. Click below to submit your thoughts.</p><p><a href="https://amazingcompany.com/feedback">Submit feedback</a></p>',
},
{
"from": {"email": "hello@amazingcompany.com", "name": "Amazing Company"},
"to": [{"email": "stewart@example.com", "name": "Stewart Griffin"}],
"subject": "Rate your experience with our customer service team",
"text": "Thanks for being a loyal customer of Amazing Company! After your recent experience with our customer service team, we’d love to know how we did. Simply click below to submit your rating.",
"html": '<p>Thanks for being a loyal customer of Amazing Company!</p><p>After your recent experience with our customer service team, we’d love to know how we did.</p><p>Simply click below to submit your rating.</p><p><a href="https://amazingcompany.com/customer-service-rating">Rate customer service</a></p>',
},
]
# Send bulk emails and print the response
try:
response = mailer.send_bulk(mail_list)
print(f"Bulk email send status code: {response.status_code}")
print(f"Response JSON: {response.json()}")
except Exception as e:
print(f"An error occurred: {e}")
How to schedule an email
By using MailerSend’s send_at parameter and setting the date and time with the ISO 8601 format, you can easily schedule an email to go out at a specified time. This is useful for system notifications or updates, such as letting users know about scheduled maintenance or downtime.
Here’s the script:
from mailersend import emails
from dotenv import load_dotenv
import os
from datetime import datetime, timedelta
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend email client with the API key
mailer = emails.NewEmail(os.getenv("MAILERSEND_API_KEY"))
# Define the email details
email_data = {
"from": {"email": "hello@amazingcompany.com", "name": "Amazing Company"},
"to": [{"email": "stewart@example.com", "name": "Stewart Griffin"}],
"subject": "Scheduled Maintenance on Wednesday, 24th July",
"text": "We’re writing to inform you that the website will be unavailable on Wednesday, 24th July between the hours of 11 PM and 11:30 PM due to scheduled maintenance. We’re sorry for any inconvenience caused.",
"html": "<p>We’re writing to inform you that the website will be unavailable on <b>Wednesday, 24th July between the hours of 11 PM and 11:30 PM</b> due to scheduled maintenance.</p> <p>We’re sorry for any inconvenience caused.</p>",
"send_at": (datetime.utcnow() + timedelta(hours=2)).isoformat()
+ "Z", # Schedule for 2 hours from now in ISO 8601 format
}
# Send the scheduled email
try:
response = mailer.send(email_data)
print(f"Status Code: {response.status_code}")
print(f"Response JSON: {response.json()}")
except Exception as e:
print(f"An error occurred: {e}")
How to retrieve activity and analytics data
MailerSend offers advanced email analytics and activity tracking data which, in addition to accessing via the dashboard, you can also access via the API.
Here’s a look at the code to fetch a full list of activities, which includes queued, sent and delivered emails, soft and hard bounces, opens, clicks, unsubscribes, and spam complaints. Note that you can set the date range using a Unix timestamp.
from mailersend import activity
from dotenv import load_dotenv
import os
# Load environment variables from .env file
load_dotenv()
# Initialize the MailerSend activity client with the API key
mailer = activity.NewActivity(os.getenv("MAILERSEND_API_KEY"))
# Define the parameters for retrieving domain activity
page = 1
limit = 20
date_from = 1623073576 # Example Unix timestamp
date_to = 1623074976 # Example Unix timestamp
events = [
"queued",
"sent",
"delivered",
"soft-bounced",
"hard-bounced",
"junk",
"opened",
"clicked",
"unsubscribed",
"spam_complaints",
]
try:
# Retrieve domain activity
response = mailer.get_domain_activity(
"domain-id", # Replace with your actual domain ID
page,
limit,
date_from,
date_to,
events,
)
# Print the response
print(f"Status Code: {response.status_code}")
print(f"Response JSON: {response.json()}")
except Exception as e:
print(f"An error occurred: {e}")
Best practices for sending emails in Python
Although sending emails in Python is made relatively simple with the built-in libraries and other third-party providers, there are a few things to keep in mind to make your sending more secure and efficient. Here are some of our top best practices for getting the best experience out of sending emails with Python.
1. Take appropriate security measures
Always store sensitive information such as API keys and SMTP credentials in environment variables or config files that are not publicly accessible. The code examples throughout this article take this into account with steps to set up your environment variables and how to correctly use them in your scripts.
You should also consider how you store such credentials for your own access—i.e. no post-it notes! In all seriousness, we recommend using a popular secrets management platform like AWS Secrets Manager or Azure Key Vault.
2. Always use authentication and encryption
Use of SMTP requires TLS/SSL to encrypt the connection and protect email content during transit. What’s more, you should use proper authentication protocols—SPF, DKIM and DMARC—to secure access to your email services and prevent abuse.
3. Use proper error handling
Implement error handling via try/except blocks to catch and manage exceptions. This will help you to manage authentication errors, invalid email addresses, and network issues more efficiently and improve the experience of the user.
You should also make use of sufficient error logging for the purposes of debugging and monitoring significant events. Having logs to look back on will help you with diagnosing issues and tracking activity.
4. Use ESPs like MailerSend
Email providers give you access to loads of features and functionality that make sending emails easier, more productive, and a lot more interesting. You’ll be able to make use of features like email templates, advanced analytics and tracking, inbound routing, bulk sending, and even SMS. All of which allow you to consolidate the majority of your communications onto a single platform and send emails more efficiently.
5. Manage email sending with rate-limiting
Rate-limiting your email sending is important to avoid exceeding service provider limits and keep your services running as usual. It can also help to prevent abuse and maintain good deliverability.
The best way to do this with Python—especially for more advanced implementations and high email sending volumes—is by using a task queue. There are various job queue systems available to help you manage this, including Celery and RQ.
And if you’re using a third-party provider, you can make use of their API’s built-in features, such as batching emails with the bulk email endpoint in MailerSend.
6. Validate email addresses
Verifying lists of email addresses or validating them in real-time as they get added to your system, is a great way to maintain healthy email sending practices that will enhance your deliverability.
There are a few different ways to do this, but by far the most reliable and efficient is by using an email verification service. MailerSend has a built-in email verification tool that you can use to validate lists of email addresses regularly and in real-time with the API.
7. Use a staging environment for testing
Testing any implementation is vital before you go to production, so you’ll want to use a test email server to try out your email workflows. It’ll prevent you from flooding any inboxes with test emails and will keep your domain safe from being blocklisted.
As well as testing your workflows, testing in this way will allow you to validate the HTML/CSS in your emails and check for spam issues.
Flexible and customizable email sending at your fingertips
Python is a great language for sending emails thanks to its automation capabilities, built-in libraries, and superior customization options.
Paired with a reliable ESP and you’ve got a simple, powerful solution for integrating email-sending into your Python apps.
Remember, you can sign up to MailerSend for free and test the platform out with a trial domain to see how everything works. Give it a go!
Try MailerSend now
Sign up for free and test out MailerSend with a free trial domain—no credit card needed. You can upgrade at any time to a free plan and get up to 3,000 emails per month.