A powerful, flexible Python script for sending personalized HTML emails with scheduling capabilities. Perfect for academic research, surveys, marketing campaigns, and professional outreach.
- π¨ Personalized HTML Emails - Use templates with dynamic placeholders
- π Smart Scheduling - Send emails at specific times or dates
- π§ͺ Safe Testing - Dry run mode to test without sending
- π Comprehensive Logging - Console output with colors + optional file logging
- π Secure Configuration - Environment variables for sensitive data
- π€ BCC Support - Add blind carbon copy recipients
- π Batch Processing - Handle multiple recipient groups efficiently
- π‘οΈ Error Handling - Robust error handling with clear messages
git clone https://github.com/YourUsername/email-automation.git
cd email-automation
pip install -r requirements.txtCopy the example configuration:
cp .env.example .envEdit .env with your details:
# Email Configuration
YOUR_EMAIL=your_email@gmail.com
YOUR_PASSWORD=your_app_password_here
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=465
# Email Content
SUBJECT_LINE=π Your Custom Subject Line
SENDER_NAME=Your Name
AFFILIATION=Your Organization
BCC_EMAILS=supervisor@example.com,backup@example.com
# Safety & Logging
DRY_RUN=true
LOG_TO_FILE=true
# Scheduling (optional)
SEND_AT=14:30
# SEND_AT=2025-07-22 09:00Create email_recipients.json:
[
{
"university": "Trinity College Dublin",
"emails": ["contact@tcd.ie", "admin@tcd.ie"]
},
{
"university": "University College Dublin",
"emails": ["info@ucd.ie"]
}
]# Test first (DRY_RUN=true)
python send_emails.py
# Send for real (DRY_RUN=false)
python send_emails.py- Enable 2-Factor Authentication in your Google Account
- Generate App Password:
- Go to Google Account Security
- Navigate: Security β 2-Step Verification β App passwords
- Select "Mail" and generate password
- Use the 16-character password in your
.envfile
| Provider | SMTP Server | Port | Authentication |
|---|---|---|---|
| Gmail | smtp.gmail.com |
465 |
App Password (if 2FA) |
| Outlook | smtp.live.com |
587 |
App Password |
| Yahoo | smtp.mail.yahoo.com |
465 |
App Password |
| Custom | Your server | Varies | Regular/App Password |
email-automation/
βββ send_emails.py # Main script
βββ email_template.html # Your HTML template
βββ email_recipients.json # Recipient data
βββ requirements.txt # Python dependencies
βββ .env # Your configuration (create this)
βββ .env.example # Configuration template
βββ log.txt # Generated log file (optional)
βββ README.md # This file
Your email_template.html should include these placeholders:
<!DOCTYPE html>
<html>
<body>
<h2>Dear {{Recipient Department/Office}},</h2>
<p>Your email content here...</p>
<p>
Sincerely,<br />
{{Your Name/Project Name}}<br />
{{Your Affiliation/Study Area}}
</p>
</body>
</html>Placeholders:
{{Recipient Department/Office}}β Replaced withuniversityfrom JSON{{Your Name/Project Name}}β Replaced withSENDER_NAMEfrom .env{{Your Affiliation/Study Area}}β Replaced withAFFILIATIONfrom .env
YOUR_EMAIL=your_email@gmail.com # Your sending email
YOUR_PASSWORD=app_password_here # App password (not regular password!)
SMTP_SERVER=smtp.gmail.com # Email provider's SMTP server
SMTP_PORT=465 # SMTP port (465 for SSL, 587 for TLS)SUBJECT_LINE=Your Email Subject # Email subject line
SENDER_NAME=Your Full Name # Your name in email signature
AFFILIATION=Your Organization # Your organization/department
BCC_EMAILS=email1@ex.com,email2@ex.com # Comma-separated BCC recipientsHTML_TEMPLATE_FILE=email_template.html # Path to HTML template
JSON_FILE=email_recipients.json # Path to recipients JSON
LOG_FILE=log.txt # Log file pathDRY_RUN=true # Test mode (true/false)
LOG_TO_FILE=true # Save logs to file (true/false)SEND_AT= # Send immediately (empty)
SEND_AT=14:30 # Send today at 2:30 PM
SEND_AT=2025-07-22 09:00 # Send on specific date/time# .env settings
DRY_RUN=false
SEND_AT=# .env settings
SEND_AT=15:30 # Send at 3:30 PM today# .env settings
SEND_AT=2025-07-25 09:00 # Send on July 25th at 9 AM# .env settings
DRY_RUN=true # Safe testing mode
LOG_TO_FILE=true # Save detailed logsThe script provides colorized console output:
π EMAIL AUTOMATION SCRIPT STARTED
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΉοΈ π§ Sender: your_email@gmail.com
βΉοΈ π Template: email_template.html
βΉοΈ π Recipients: email_recipients.json
β οΈ π§ͺ DRY RUN MODE: No emails will be sent!
π¨ STARTING EMAIL CAMPAIGN
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π« π Processing Trinity College Dublin (2 emails)
β
βοΈ Sent to: contact@tcd.ie
β
βοΈ Sent to: admin@tcd.ie
π CAMPAIGN SUMMARY
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
π§ Successfully sent: 2
β
β
Total processed: 2
β οΈ π§ͺ This was a DRY RUN - no actual emails were sent
- β Use App Passwords for 2FA-enabled accounts
- β
Keep
.envfile out of version control (it's in.gitignore) - β
Test with
DRY_RUN=truefirst - β Use BCC for sensitive recipient lists
- β Review logs before and after sending
- β Use your regular email password with 2FA enabled
- β Commit
.envfile to Git - β Send to large lists without testing first
- β Include sensitive data in recipient JSON if sharing
- β Verify you're using an App Password (not regular password)
- β Check SMTP server and port are correct
- β Ensure 2FA is enabled and App Password is generated
- β
Check file paths in
.envare correct - β
Ensure
email_template.htmlandemail_recipients.jsonexist - β Verify you're running script from correct directory
- β Validate JSON syntax using online JSON validator
- β Check for trailing commas or missing quotes
- β Ensure UTF-8 encoding
- β
Use correct format:
HH:MMorYYYY-MM-DD HH:MM - β Keep terminal/command prompt open during scheduled wait
- β Ensure computer doesn't sleep during wait time
Enable file logging for detailed records:
LOG_TO_FILE=true
LOG_FILE=campaign_2025_07_21.logAdd multiple supervisors or monitoring emails:
BCC_EMAILS=supervisor@uni.edu,backup@org.com,monitor@dept.eduOrganize your files:
HTML_TEMPLATE_FILE=templates/survey_invitation.html
JSON_FILE=data/research_participants.json
LOG_FILE=logs/campaign_$(date).log- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter issues:
- Check the troubleshooting section above
- Enable logging (
LOG_TO_FILE=true) for detailed error information - Test in DRY_RUN mode to isolate issues
- Open an issue with:
- Error messages (remove sensitive data)
- Your configuration (remove credentials)
- Steps to reproduce
Made with β€οΈ for efficient email automation