Skip to main content

Email Me Anything

A simple Python package for sending emails programmatically with various content, such as quotes, custom messages, or data from CSV files. It provides utilities for handling CSV files, email configuration, and sending templated emails via MailerSend.

Installation

Install the package from PyPI:

pip install email_me_anything

Configuration

The package uses environment variables for configuration. Most are optional, but if you intend to send emails, certain variables become mandatory.

Create a .env file in your project directory with the following variables as needed:

# Optional: Sender details
EMAIL_SENDER=Your Name
EMAIL_SENDER_ADDRESS=your-email@example.com

# Optional: Recipient details (can be set programmatically if needed)
EMAIL_RECIPIENT_0_NAME=Recipient Name
EMAIL_RECIPIENT_0_ADDRESS=recipient@example.com

# Mandatory if email sending is required; defaults to false (no emails sent)
PROD_MODE=true

# Mailer selection: 'mailersend' (default) or 'smtp'
MAILER_CLIENT=mailersend

# MailerSend API key (required when MAILER_CLIENT=mailersend and PROD_MODE=true)
MAILERSEND_API_KEY=your-mailersend-api-key

# SMTP settings (required when MAILER_CLIENT=smtp and PROD_MODE=true)
SMTP_HOST=smtp.example.com
SMTP_PORT=465
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
  • PROD_MODE: Set to true to enable email sending. If false (default), no emails are sent; instead, the generated HTML is saved to debug-email.html for inspection.
  • MAILER_CLIENT: Choose between mailersend (default) or smtp as the email backend.
  • If PROD_MODE is true and MAILER_CLIENT is mailersend, you must configure your MailerSend API key via the MAILERSEND_API_KEY environment variable.
  • If PROD_MODE is true and MAILER_CLIENT is smtp, you must configure the SMTP settings (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS).

Usage

Import the helpers below and work with pathlib Paths whenever you load templates or CSV files.

Sending a Lucky Email

Send a random row from a CSV file by rendering it into an HTML template. You can override the default sender and recipient values or pass a variable_map that renames CSV columns for the template.

from pathlib import Path
from email_me_anything import send_lucky_email

csv_path = Path("quotes.csv")
template_path = Path("templates/quote.html")

send_lucky_email(
    csv_path,
    template_path,
    subject="Daily Inspiration",
    recipients=[{"email": "friend@example.com", "name": "Friend"}],
    variable_map={"quote": "text", "author": "author"},
)

Sending a Custom Email

Use build_html_content (and build_context if you need to massage the data) to render a template and send it with send_email.

from pathlib import Path
from email_me_anything import build_context, build_html_content, send_email

template = Path("templates/notification.html")
data = {"status": "Completed", "details": "System update succeeded."}
context = build_context(data)
html_content = build_html_content(template, context)

sender = {"email": "alerts@example.com", "name": "Alert Bot"}
recipients = [{"email": "ops@example.com", "name": "Ops Team"}]
send_email(sender, recipients, "System Alert", html_content)

variable_map lets you rename keys from data before rendering the template.

Working with CSV Files

read_csv returns the raw rows from a file, while select_random_row returns a dict keyed by the header row (or col0, col1, etc. when headers are missing).

from pathlib import Path
from email_me_anything import read_csv, select_random_row

csv_path = Path("quotes.csv")
rows = read_csv(csv_path)

if rows:
    sample = select_random_row(csv_path)
    print(sample)

select_random_row yields False when the file cannot be read and None when there are no rows beyond the header.

Examples

Example 1: Daily Quote Email

import schedule
from pathlib import Path
from email_me_anything import send_lucky_email

csv_path = Path("quotes.csv")
template_path = Path("templates/quote.html")

def send_daily_quote():
    send_lucky_email(csv_path, template_path, subject="Quote of the Day")

# Schedule to run daily at 8 AM
schedule.every().day.at("08:00").do(send_daily_quote)

Example 2: Custom Notification Email

from pathlib import Path
from email_me_anything import build_context, build_html_content, send_email

template_path = Path("templates/notification.html")
data = {"title": "Alert", "message": "System update completed successfully."}
context = build_context(data, variable_map={"title": "title", "message": "message"})
html_content = build_html_content(template_path, context)

sender = {"email": "alerts@example.com", "name": "Alert System"}
recipients = [{"email": "team@example.com", "name": "Team"}]
send_email(sender, recipients, "System Alert", html_content)

Example 3: Bulk Email from CSV

from pathlib import Path
from email_me_anything import read_csv, build_html_content, send_email

template_path = Path("templates/bulk-welcome.html")
csv_path = Path("recipients.csv")
rows = read_csv(csv_path)

if not rows or len(rows) < 2:
    raise SystemExit("No recipient data")

headers = rows[0]
sender = {"email": "hello@example.com", "name": "Hello Team"}

for row in rows[1:]:
    data = dict(zip(headers, row))
    recipient = {"email": data["email"], "name": data["name"]}
    html = build_html_content(template_path, data)
    send_email(sender, [recipient], f"Welcome {data['name']}", html)

Example 4: Using SMTP Instead of MailerSend

To use SMTP as your email backend, configure your .env file:

PROD_MODE=true
MAILER_CLIENT=smtp
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password

Then use the same code as before — the package automatically uses SMTP based on the MAILER_CLIENT setting:

from pathlib import Path
from email_me_anything import send_lucky_email

send_lucky_email(
    csv_path=Path("quotes.csv"),
    template_path=Path("templates/quote.html"),
    subject="Daily Quote via SMTP",
    recipients=[{"email": "friend@example.com", "name": "Friend"}],
)

Testing

The package includes comprehensive test coverage using pytest. Tests verify:

  • Configuration Management: Parsing of environment variables with proper defaults, SMTP settings, and mailer client selection
  • CSV Operations: Reading CSV files, handling missing/malformed data, random row selection with deterministic and probabilistic tests
  • Email Building: HTML template rendering, variable mapping, Unicode support, error handling
  • Email Sending: Integration with MailerSend API and SMTP, recipient handling, production vs. debug modes
  • Complete Workflows: End-to-end email sending through send_lucky_email with variable maps and default values

Running Tests

Install development dependencies and run pytest:

pip install pytest
pytest tests/ -v

Current test suite includes 73 tests covering:

  • 13 configuration tests (env variable parsing, defaults, SMTP and mailer settings)
  • 23 CSV utility tests (reading, parsing, randomization, edge cases)
  • 17 email utility tests (context building, HTML rendering, sending)
  • 14 integration tests (complete workflows, mode switching)

License

Apache License 2.0

Metadata

Release files for email_me_anything 0.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for email_me_anything 0.2.3
File Size Uploaded
email_me_anything-0.2.3.tar.gz 12.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for email_me_anything 0.2.3
File Interpreter ABI Platform
email_me_anything-0.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 26.5 kB

Release files / email_me_anything-0.2.3.tar.gz

Download URL email_me_anything-0.2.3.tar.gz
Size 12.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c96ab715090d93db50f19e018c679c3b9a5fc75bb258d2f021bc1c3fa783d364
BLAKE2b-256 checksum
How to use checksums
147e5bd0bcd918eb453466662658150d4fda6a5c04c100d8840572544e350e73
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.2.1 CPython/3.14.0 Windows/11

Release files / email_me_anything-0.2.3-py3-none-any.whl

Download URL email_me_anything-0.2.3-py3-none-any.whl
Size 14.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d80fc1191f16aefb2ba3c0658b52ea15580f3f7e8d0f900948451a205724b2a1
BLAKE2b-256 checksum
How to use checksums
6ae84edf24a758329728a93d035a45546f4c19ed97de0a8164311a77001faf2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.2.1 CPython/3.14.0 Windows/11

Release history Release notifications | RSS feed

This release

0.2.3 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page