Skip to content

Latest commit

 

History

History

python-elasticemail-examples

Folders and files

README.md

Python Email API Examples - Elastic Email

Send transactional and bulk email from Python with the Elastic Email email API. Standalone scripts plus three web applications - Flask, FastAPI and Django - built on the official Elastic Email Python SDK.

First time here? The Python quickstart gets you from nothing to a delivered email in five minutes. For the concepts behind these examples, see the Elastic Email guides.

Versions: Elastic Email REST API v4 · SDK ElasticEmail==4.4.0 (PyPI) · Python 3.9+ · Flask, FastAPI, Django

Prerequisites

Installation

# Create virtual environment (optional)
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Copy environment variables
cp .env.example .env

# Add your Elastic Email API key to .env

Standalone Examples

Run every script from this folder.

Basic Email Sending

python examples/basic_send.py

Batch Sending

python examples/batch_send.py

With Attachments

python examples/with_attachments.py

With CID (Inline) Attachments

python examples/with_cid_attachments.py

Using Templates

python examples/with_template.py

Scheduled Sending

python examples/scheduled_send.py

Prevent Gmail Threading

python examples/prevent_threading.py

Contacts and Lists

python examples/contacts.py

Domain Management

python examples/domains.py

Email Status

python examples/email_status.py <transactionId> [messageId]

Webhooks

python examples/webhooks.py

Creates a signed webhook (EnableSigning) that POSTs JSON (DeliveryMethod: PostJson), prints its SigningSecret, rotates the secret, then deletes it. Store the secret as ELASTICEMAIL_WEBHOOK_SECRET: it is shown only once. With it set, the webhook routes require a valid X-ElasticEmail-Signature (HMAC-SHA256 over timestamp, method, raw request target and raw body) and answer 401 otherwise. Leave it empty to use unsigned webhooks with ?token=ELASTICEMAIL_WEBHOOK_TOKEN in the URL instead.

Inbound Routes

python examples/inbound.py

Double Opt-In

# Subscribe (creates contact + sends confirmation)
python examples/double_optin_subscribe.py user@example.com "John Doe"

# Click-tracking based confirmation server
python examples/double_optin_webhook.py

Suppressions

python examples/suppressions.py [email]

Email Verification

python examples/email_verification.py someone@example.com

Statistics

python examples/statistics.py

Sub-Accounts

python examples/sub_accounts.py
# Creating a sub-account affects billing:
CREATE_SUBACCOUNT=true python examples/sub_accounts.py

Flask Application

python examples/flask_app.py

# Then in another terminal:
curl -X POST http://localhost:3000/send \
  -H "Content-Type: application/json" \
  -d '{"to": "you@yourdomain.com", "subject": "Hello", "message": "Hi from Flask!"}'

FastAPI Application

python examples/fastapi_app.py
# or: uvicorn examples.fastapi_app:app --reload --port 3000

curl -X POST http://localhost:3000/send \
  -H "Content-Type: application/json" \
  -d '{"to": "you@yourdomain.com", "subject": "Hello", "message": "Hi from FastAPI!"}'

Django Application

cd django_app
python manage.py runserver 8001

curl -X POST http://localhost:8001/send \
  -H "Content-Type: application/json" \
  -d '{"to": "you@yourdomain.com", "subject": "Hello", "message": "Hi from Django!"}'

API Endpoints

All three server apps expose the same routes and JSON shapes.

  • GET /health -> {"status": "ok"}
  • POST /send body {"to", "subject", "message"} -> {"success": true, "transactionId", "messageId"}; an optional Idempotency-Key request header is forwarded to Elastic Email (a new key is generated otherwise), so clients can retry safely with the same key
  • GET|POST /webhook - Elastic Email event notifications (status, to, transaction, messageid, target, ...). Recommended: a signed webhook with DeliveryMethod: PostJson, which sends each event as a POST with a JSON body; set ELASTICEMAIL_WEBHOOK_SECRET and the route verifies the signature (401 if it is missing or wrong). Fallback for unsigned webhooks: leave the secret empty, add ?token=... matching ELASTICEMAIL_WEBHOOK_TOKEN to the URL, and the details arrive in the query string of a GET.
  • POST /inbound?token=... - inbound email pushed by an inbound route (from_email, subject, body_html, att1_name, att1_content, ...). Forwards a copy to CONTACT_EMAIL.
  • POST /double-optin/subscribe body {"email", "name"} - stores the contact as Transactional and sends a confirmation link
  • GET /double-optin/confirm?email=&token= - verifies the HMAC token and adds the contact to ELASTICEMAIL_LIST_NAME
  • GET|POST /double-optin/webhook - confirms on a Clicked event whose target is the confirm link (signed, or ?token=... like /webhook)

Failures return {"error": "<message from the API>"} with the API status code.

Quick Usage

import ElasticEmail

configuration = ElasticEmail.Configuration()
configuration.api_key["apikey"] = "your_api_key"

with ElasticEmail.ApiClient(configuration) as api_client:
    emails_api = ElasticEmail.EmailsApi(api_client)
    result = emails_api.emails_transactional_post(
        ElasticEmail.EmailTransactionalMessageData(
            Recipients=ElasticEmail.TransactionalRecipient(To=["you@yourdomain.com"]),
            Content=ElasticEmail.EmailContent(
                From="Acme <hello@yourdomain.com>",
                Subject="Hello",
                Body=[ElasticEmail.BodyPart(ContentType="HTML", Content="<p>Hello World</p>")],
            ),
        )
    )
    print(result.transaction_id, result.message_id)

Project Structure

python-elasticemail-examples/
├── examples/
│   ├── ee.py                     # Shared config (API key, env values)
│   ├── basic_send.py             # Simple transactional email
│   ├── batch_send.py             # Bulk send with merge fields
│   ├── with_attachments.py       # Emails with files
│   ├── with_cid_attachments.py   # Inline images
│   ├── with_template.py          # Templates with merge values
│   ├── scheduled_send.py         # Delayed delivery (TimeOffset)
│   ├── prevent_threading.py      # Prevent Gmail threading
│   ├── contacts.py               # Contacts and lists
│   ├── domains.py                # Domain verification
│   ├── email_status.py           # Delivery status by transaction id
│   ├── webhooks.py               # Manage webhooks
│   ├── inbound.py                # Manage inbound routes
│   ├── double_optin_subscribe.py # Double opt-in: subscribe
│   ├── double_optin_webhook.py   # Double opt-in: click-based confirm server
│   ├── suppressions.py           # Unsubscribes, bounces, complaints
│   ├── email_verification.py     # Verify an address
│   ├── statistics.py             # Account statistics
│   ├── sub_accounts.py           # Sub-accounts (read-only by default)
│   ├── flask_app.py              # Flask web application
│   └── fastapi_app.py            # FastAPI web application
├── django_app/                   # Django web application
│   ├── manage.py
│   ├── django_project/
│   └── elasticemail_app/
├── requirements.txt
├── .env.example
└── README.md

Resources

License

MIT