Introduction
As a developer, sending bulk or personalized emails is a common requirement for various applications. Whether you're sending newsletters, product announcements, feedback requests, or marketing campaigns, you need a reliable way to handle email distribution at scale.
Building this functionality from scratch involves dealing with SMTP setup, email templates, user lists, rate limiting to avoid being flagged as spam, and robust error handling. This can be time-consuming and error-prone.
Installation
Install mail-senderpy using pip:
pip install mail-senderpy
Project Setup
To get started, you'll need three files in your project directory:
-
.env- SMTP configuration -
users.json- List of recipients -
template.html- Email template
Configure SMTP Credentials
Create a .env file with your SMTP settings:
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
EMAIL_ADDRESS=your@email.com
EMAIL_PASSWORD=app_password
SMTP_TLS=true
Here's what each variable does:
-
SMTP_SERVER: Your SMTP server address -
SMTP_PORT: SMTP port (587 for TLS, 465 for SSL) -
EMAIL_ADDRESS: Your email address -
EMAIL_PASSWORD: Your email password or app password -
SMTP_TLS: Whether to use TLS encryption
Note for Gmail users: Use an App Password instead of your regular password. Generate one from your Google Account settings under Security > App passwords.
Create the Users List
Emails are sent to recipients defined in a JSON file. Create users.json:
[
{"email": "user1@example.com", "name": "Rahul"},
{"email": "user2@example.com", "name": "Priya"}
]
All fields in the JSON objects are available as variables in your email templates.
Create an Email Template
Use Jinja2 templates for personalized emails. Create template.html:
<h1>Hello {{ name }}!</h1>
<p>We're reaching out to you at {{ email }}.</p>
Jinja2 placeholders like {{ name }} and {{ email }} will be replaced with actual values from your users.json file for each recipient.
Send Emails Using the CLI
The easiest way to send emails is through the command line:
mail-senderpy send --env .env --users users.json --template template.html
Parameters explained:
-
--env: Path to your environment file -
--users: Path to your users JSON file -
--template: Path to your email template
For more control, specify a subject and delay between emails:
mail-senderpy send \
--env .env \
--users users.json \
--template template.html \
--subject "Hello {{name}}!" \
--delay 10
The --delay parameter adds seconds between emails to prevent hitting SMTP rate limits.
Send Emails Using Python Code
For programmatic usage, use the Python API:
from mail_senderpy import send_message
result = send_message(
env_path=".env",
users_path="users.json",
template_path="template.html",
)
print(result)
Expected output:
{
"success": 18,
"failed": 2,
"errors": [
{"email": "user@test.com", "error": "SMTP authentication failed"}
]
}
Async Email Sending
For better performance with large recipient lists, use async sending:
from mail_senderpy import send_message_async
result = await send_message_async(
env_path=".env",
users_path="users.json",
template_path="template.html",
)
Async sending is particularly useful in web applications or when sending thousands of emails.
Built-in Templates
mail-senderpy includes ready-made templates for common use cases:
marketing_email.htmlfeedback_request.htmlannouncement.html
Use them directly:
mail-senderpy send --template marketing_email.html
Error Handling
The library provides structured error handling:
Code example:
from mail_senderpy import send_message, MailSenderError
try:
result = send_message(
env_path=".env",
users_path="users.json",
template_path="template.html"
)
except MailSenderError as e:
print(f"Error: {e}")
print(f"Details: {e.details}")
Common error types:
-
ConfigError: Issues with SMTP configuration -
UsersFileError: Problems reading the users JSON file -
TemplateError: Template parsing or rendering issues
Mail-senderpy makes bulk email sending in Python simple and reliable. With support for personalization through Jinja2 templates, both CLI and Python API usage, and compatibility with major SMTP providers, it handles the complexities so you can focus on your application logic.
Link to github repo
Link to PYPI
Happy Coding!



Top comments (0)