Send Bulk Email Using Python and AWS SES SMTP
Send Bulk Email Using Python and AWS SES SMTP
This tutorial shows how to send emails to a list of recipients using Python and the AWS SES SMTP interface. The script sends an HTML email with a header and footer image and records the result of each send operation in a log file.
What This Script Does
- Connects to AWS SES using SMTP.
- Reads recipients from
list_of_emails.txt. - Builds an HTML email.
- Adds header and footer images.
- Sends the email to each recipient.
- Writes success and failure messages to a log file.
1. Install Python
This script uses Python's built-in email and SMTP libraries, so no external Python package is required for the sending logic.
2. Prepare the Files
Keep the script and recipient list in the same directory:
BulkEmail/
├── bulk_email.py
├── list_of_emails.txt
└── email_send_status.txtThe header and footer images can be stored at any local path accessible by the script.
3. Create the Email List
Create list_of_emails.txt with one recipient email address per line:
user1@example.com
user2@example.com
user3@example.com4. Configure AWS SES
Update these values in the script:
aws_smtp_server = "email-smtp.ap-south-1.amazonaws.com"
aws_smtp_port = 587
aws_smtp_username = "YOUR_SES_SMTP_USERNAME"
aws_smtp_password = "YOUR_SES_SMTP_PASSWORD"
sender_email = "Email Helpdesk <helpdesk@yourdomain.com>"The SMTP endpoint must match the AWS Region where your SES SMTP credentials and sending configuration are being used.
5. Complete Python Script
Save the following as bulk_email.py.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from datetime import datetime
# AWS SES SMTP settings
aws_smtp_server = "email-smtp.ap-south-1.amazonaws.com"
aws_smtp_port = 587
aws_smtp_username = "YOUR_SES_SMTP_USERNAME"
aws_smtp_password = "YOUR_SES_SMTP_PASSWORD"
sender_email = "Email Helpdesk <helpdesk@yourdomain.com>"
subject = "Regarding Use of E-Library in Customer Portal"
# HTML email
body = """
<html>
<body>
<img src="cid:header_image" alt="Header Image">
<p>Dear Students,</p>
<p>
The e-Library facility is now available through the customer portal.
Please follow the user guide to access the available eBooks.
</p>
<p>Regards,<br>Customer Support Team</p>
<img src="cid:footer_image" alt="Footer Image">
</body>
</html>
"""
output_file = "email_send_status.txt"
def send_email(to_email, subject, body):
msg = MIMEMultipart()
msg["From"] = sender_email
msg["To"] = to_email
msg["Subject"] = subject
# Header image
with open(r"E:\scripts\customer\header.png", "rb") as file:
image = MIMEImage(file.read())
image.add_header("Content-ID", "<header_image>")
msg.attach(image)
# Footer image
with open(r"E:\scripts\customer\footer.png", "rb") as file:
image = MIMEImage(file.read())
image.add_header("Content-ID", "<footer_image>")
msg.attach(image)
# HTML body
msg.attach(MIMEText(body, "html"))
# Send through AWS SES SMTP
with smtplib.SMTP(
aws_smtp_server,
aws_smtp_port
) as server:
server.starttls()
server.login(
aws_smtp_username,
aws_smtp_password
)
server.send_message(msg)
with open("list_of_emails.txt", "r") as file:
with open(output_file, "a") as output:
for line in file:
email = line.strip()
if not email:
continue
try:
send_email(
email,
subject,
body
)
status = (
f"{datetime.now():%Y-%m-%d %H:%M:%S} - "
f"Email sent successfully to {email}"
)
print(status)
output.write(status + "\n")
except Exception as e:
status = (
f"{datetime.now():%Y-%m-%d %H:%M:%S} - "
f"Failed to send email to {email}: {e}"
)
print(status)
output.write(status + "\n")
6. How It Works
Read the Email List
with open("list_of_emails.txt", "r") as file:The script reads the recipient list one line at a time.
Create the HTML Email
msg = MIMEMultipart()
msg["From"] = sender_email
msg["To"] = to_email
msg["Subject"] = subjectThe message contains the sender, recipient, subject, HTML body, and inline images.
Send Through AWS SES SMTP
server = smtplib.SMTP(
aws_smtp_server,
aws_smtp_port
)
server.starttls()
server.login(
aws_smtp_username,
aws_smtp_password
)The script establishes an SMTP connection, enables TLS encryption, authenticates with the SES SMTP credentials, and sends the email.
Write Sending Status
email_send_status.txtEach successful or failed send is recorded with a timestamp.
7. Run the Script
python bulk_email.pyThe script processes each email address in the list and records the result.
8. Example Output
2026-09-18 14:30:10 - Email sent successfully to user1@example.com
2026-09-18 14:30:11 - Email sent successfully to user2@example.com
2026-09-18 14:30:12 - Failed to send email to user3@example.com: SMTP errorQuick Reference
# Run the bulk email script
python bulk_email.pyImportant AWS SES Notes
- Verify the sender identity in AWS SES before sending.
- Follow SES sending quotas and rate limits.
- Handle bounces and complaints appropriately.
- Do not send to purchased or scraped email lists.
- Keep SMTP credentials secret.
- Include an appropriate unsubscribe mechanism for applicable bulk communications.
Conclusion
Python's built-in SMTP and email libraries can be used with AWS SES to automate email delivery to a controlled recipient list. The script also provides a simple status log so delivery attempts can be reviewed later.
Discussion (0)