Send emails with Flask

In this quickstart, you'll learn how to send transactional emails from your Flask app with Sidemail. You'll set up the SDK, send your first email, and see examples for common use cases like welcome emails, password resets, and scheduled reports.

Before you start

  1. Create a Sidemail account → get your API key
  2. Add a sending domain → set up your domain for sending

1. Install

pip install sidemail

2. Add your API key

Add your Sidemail API key to .env (make sure you have python-dotenv installed):

SIDEMAIL_API_KEY=your-api-key

3. Setup

Create a shared instance of the Sidemail client. This allows you to import the configured client anywhere in your application (e.g., in Blueprints).

# sidemail_client.py
from sidemail import Sidemail
import os

# The SDK automatically reads SIDEMAIL_API_KEY from environment variables
sidemail = Sidemail()

4. Send a welcome email

Send an email when a user registers.

# app.py
from flask import Flask, request, jsonify
from sidemail_client import sidemail

app = Flask(__name__)

@app.route('/register', methods=['POST'])
def register():
    data = request.get_json()
    email = data.get('email')
    name = data.get('name')

    # ... create user in database ...

    sidemail.send_email(
        toAddress=email,
        fromAddress="[email protected]",
        fromName="Your App",
        templateName="Welcome",
        templateProps={"firstName": name},
    )

    return jsonify({"message": "User registered"})

5. Send a password reset email

@app.route('/forgot-password', methods=['POST'])
def forgot_password():
    email = request.get_json().get('email')
    token = "secure-reset-token" # Generate this securely

    sidemail.send_email(
        toAddress=email,
        fromAddress="[email protected]",
        fromName="Your App",
        templateName="Password Reset",
        templateProps={
            "actionUrl": f"https://myapp.com/reset/{token}",
        },
    )

    return jsonify({"message": "Reset email sent"})

6. Send a weekly report (CLI Command)

Flask has built-in support for creating CLI commands, which is perfect for cron jobs.

# app.py (or in a separate commands module)
import click

@app.cli.command("send-weekly-report")
def send_weekly_report():
    # In a real app, fetch this from your database
    new_signups = 150
    chart_data = [100, 200, 300, 400, 200, 300, 200, 500]

    sidemail.send_email(
        toAddress="[email protected]",
        fromAddress="[email protected]",
        fromName="My App",
        templateName="Weekly Report",
        templateProps={
            "signups": new_signups,
            "chart": chart_data,
        },
    )

    click.echo("Weekly report sent")

Run it via cron:

# Run every Monday at 8:00 AM
0 8 * * 1 flask send-weekly-report

7. Send email via Signals

Decouple email sending from your routes by using Flask signals (requires blinker library).

# signals.py
from flask import signals

user_registered = signals.Namespace().signal('user-registered')

# app.py
from signals import user_registered

@user_registered.connect
def send_welcome_email(sender, user):
    sidemail.send_email(
        toAddress=user['email'],
        fromAddress="[email protected]",
        fromName="My App",
        templateName="Welcome",
    )

@app.route('/register', methods=['POST'])
def register():
    # ... create user ...
    user = {"email": "[email protected]", "name": "Alex"}

    # Trigger the signal
    user_registered.send(app, user=user)

    return jsonify({"message": "User registered"})

8. Send HTML email (with Jinja2)

Use Flask's render_template to generate HTML from your Jinja2 templates.

from flask import render_template

@app.route('/send-invoice', methods=['POST'])
def send_invoice():
    # templates/emails/invoice.html
    html_content = render_template('emails/invoice.html', amount=99)

    sidemail.send_email(
        toAddress="[email protected]",
        fromAddress="[email protected]",
        fromName="Your App",
        subject="Your Invoice",
        html=html_content,
    )

    return jsonify({"message": "Invoice sent"})

9. Send Markdown email

Store your markdown content in a file and load it (learn more).

import os

@app.route('/send-markdown', methods=['POST'])
def send_markdown():
    # Assuming templates are in the 'templates' folder
    template_path = os.path.join(app.root_path, 'templates/emails/welcome.md')

    with open(template_path, "r") as f:
        markdown_content = f.read()

    # Subject and sender are defined in the markdown frontmatter
    sidemail.send_email(
        toAddress="[email protected]",
        markdown=markdown_content,
        templateProps={
            "name": "John",
            "link": "https://example.com",
        },
    )

    return jsonify({"message": "Email sent"})

10. Send plain text email

sidemail.send_email(
    toAddress="[email protected]",
    fromAddress="[email protected]",
    fromName="Your App",
    subject="Hello",
    text="Hello! 👋",
)

11. Schedule email

Send email later. Set scheduledAt to an ISO date string.

import datetime

# Schedule for 1 hour from now
scheduled_at = (datetime.datetime.utcnow() + datetime.timedelta(hours=1)).isoformat() + "Z"

sidemail.send_email(
    toAddress="[email protected]",
    fromAddress="[email protected]",
    fromName="Your App",
    templateName="Welcome",
    templateProps={"firstName": "Alex"},
    scheduledAt=scheduled_at,
)

12. Send with attachment

Use the Sidemail.file_to_attachment helper to attach files.

from sidemail import Sidemail

with open("invoice.pdf", "rb") as f:
    pdf_data = f.read()

attachment = Sidemail.file_to_attachment("invoice.pdf", pdf_data)

sidemail.send_email(
    toAddress="[email protected]",
    fromAddress="[email protected]",
    fromName="Your App",
    subject="Your invoice",
    text="See attached.",
    attachments=[attachment],
)

13. Handle errors

from sidemail import SidemailError

try:
    sidemail.send_email(
        # ...
    )
except SidemailError as e:
    # Log error to file or monitoring system
    app.logger.error(f"Sidemail error: {e.message}")
    return jsonify({"error": "Failed to send email"}), 500