Send Bulk Email Using Python and AWS SES SMTP

Python September 18, 2026 35 Views 5 min read
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.

Important: Send email only to recipients who have given permission to receive it. Follow AWS SES sending limits, suppression-list requirements, and applicable anti-spam laws and policies. Never publish real SMTP credentials.

What This Script Does

  1. Connects to AWS SES using SMTP.
  2. Reads recipients from list_of_emails.txt.
  3. Builds an HTML email.
  4. Adds header and footer images.
  5. Sends the email to each recipient.
  6. 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.txt

The 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.com

4. 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.

Security Note: Do not commit SMTP usernames or passwords to Git or publish them in a tutorial. Use environment variables, a secrets manager, or another secure credential store for production use.

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"] = subject

The 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.txt

Each successful or failed send is recorded with a timestamp.

7. Run the Script

python bulk_email.py

The 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 error

Quick Reference

# Run the bulk email script
python bulk_email.py

Important 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)