Email

Email components for Dash wrapping React Email patterns — 15 email-safe components, table-based layouts, live preview, and sending via Resend.

Full documentation: https://email.2plot.dev — the dedicated dash-email documentation site, with the complete API reference and deeper examples. This page is the quick-start overview.

Installation

Visit GitHub Repo · PyPI

pip install dash-email

Introduction

dash-email bridges Python-first development with the component patterns pioneered by React Email. Build email templates with familiar Dash syntax, preview them live inside your app, and export inline-styled, table-based HTML that renders correctly in Gmail, Outlook, Apple Mail, and every other major client.

import dash_email as de

Status: early release (0.0.x). The component API is stable; the AI builder and sending utilities are actively evolving.


Quick Start

A complete welcome email: EmailEmailBodyEmailContainerEmailSection, with a heading, paragraph, and a bulletproof CTA button. What you see below is the live component tree rendered in the browser — the exact same tree converts to email-safe HTML at send time.

# File: docs/dash_email/quick_start.py

import dash_email as de

component = de.Email(
    lang="en",
    children=[
        de.EmailBody(
            style={"backgroundColor": "#f6f9fc", "padding": "40px 0",
                   "borderRadius": "12px"},
            children=[
                de.EmailContainer([
                    de.EmailSection(
                        style={
                            "backgroundColor": "#ffffff",
                            "borderRadius": "8px",
                            "padding": "40px",
                        },
                        children=[
                            de.EmailHeading(
                                "Welcome to 2plot.dev!",
                                as_="h1",
                                style={"color": "#1a1a1a", "marginBottom": "16px"},
                            ),
                            de.EmailText(
                                "Thanks for creating an account. You now have access to "
                                "every live component example, full API references, and "
                                "the AI documentation assistant.",
                                style={"color": "#666666", "lineHeight": "1.6"},
                            ),
                            de.EmailButton(
                                "Explore the docs",
                                href="https://2plot.dev",
                                style={
                                    "backgroundColor": "#12B886",
                                    "color": "#ffffff",
                                    "padding": "12px 24px",
                                    "borderRadius": "4px",
                                    "fontWeight": "bold",
                                },
                            ),
                        ],
                    )
                ])
            ],
        )
    ],
)

Rows & Columns

Email clients are not browsers — floats, flexbox, and grid are unreliable or stripped entirely. EmailRow / EmailColumn are the layout primitives that survive every client: rows render as HTML tables and columns as table cells. Set widths with percentage styles on each column.

# File: docs/dash_email/rows_columns.py

import dash_email as de

# Emails are always light-themed artifacts: every text element carries an
# explicit color so the preview renders identically on the docs site's
# light AND dark modes (unstyled text would inherit the page theme color).
CELL = {"padding": "12px", "verticalAlign": "top"}
HEADING = {"color": "#1a1a1a"}
BODY_TEXT = {"color": "#666666", "lineHeight": "1.6"}

component = de.Email([
    de.EmailBody(
        style={
            "backgroundColor": "#f6f9fc",
            "padding": "32px 0",
            "borderRadius": "12px",
        },
        children=[
            de.EmailContainer([
                de.EmailSection(
                    style={
                        "backgroundColor": "#ffffff",
                        "borderRadius": "8px",
                        "padding": "24px",
                    },
                    children=[
                        de.EmailHeading("Two columns", as_="h3", style=HEADING),
                        de.EmailRow([
                            de.EmailColumn(
                                style={"width": "50%", **CELL},
                                children=[
                                    de.EmailText(
                                        "Left column — rows and columns render "
                                        "as real HTML tables, the only layout "
                                        "primitive every email client supports.",
                                        style=BODY_TEXT,
                                    )
                                ],
                            ),
                            de.EmailColumn(
                                style={"width": "50%", **CELL},
                                children=[
                                    de.EmailText(
                                        "Right column — set widths with "
                                        "percentage styles on each column.",
                                        style=BODY_TEXT,
                                    )
                                ],
                            ),
                        ]),
                        de.EmailDivider(style={"margin": "16px 0"}),
                        de.EmailHeading("70 / 30 split", as_="h3", style=HEADING),
                        de.EmailRow([
                            de.EmailColumn(
                                style={"width": "70%", **CELL},
                                children=[
                                    de.EmailText("dash-email Pro license",
                                                 style=BODY_TEXT)
                                ],
                            ),
                            de.EmailColumn(
                                style={"width": "30%", "textAlign": "right", **CELL},
                                children=[
                                    de.EmailText("$99.00", style=BODY_TEXT)
                                ],
                            ),
                        ]),
                    ],
                )
            ])
        ],
    )
])

Buttons & Links

EmailButton is a "bulletproof" call-to-action — a styled anchor that keeps its padding and background across clients. EmailLink is its inline counterpart for links inside running text.

# File: docs/dash_email/button_cta.py

import dash_email as de

component = de.Email([
    de.EmailBody(
        style={"backgroundColor": "#f6f9fc", "padding": "32px 0",
               "borderRadius": "12px"},
        children=[
            de.EmailContainer([
                de.EmailSection(
                    style={
                        "backgroundColor": "#ffffff",
                        "borderRadius": "8px",
                        "padding": "32px",
                        "textAlign": "center",
                    },
                    children=[
                        de.EmailHeading(
                            "New release: dash-leaflet2",
                            as_="h2",
                            style={"color": "#1a1a1a"},
                        ),
                        de.EmailText(
                            "Leaflet 2-native maps for Dash — 26 components, no "
                            "react-leaflet dependency. Read the announcement, or "
                            "jump straight into the interactive docs.",
                            style={"color": "#666666", "lineHeight": "1.6"},
                        ),
                        de.EmailButton(
                            "Read the docs",
                            href="https://2plot.dev/pip/dash_leaflet2",
                            style={
                                "backgroundColor": "#228be6",
                                "color": "#ffffff",
                                "padding": "12px 28px",
                                "borderRadius": "6px",
                                "fontWeight": "bold",
                                "marginRight": "8px",
                            },
                        ),
                        de.EmailText(
                            [
                                "Prefer video? Watch the walkthrough on ",
                                de.EmailLink(
                                    "YouTube @2plotai",
                                    href="https://www.youtube.com/@2plotai",
                                    style={"color": "#12B886"},
                                ),
                                ".",
                            ],
                            style={"color": "#999999", "fontSize": "13px"},
                        ),
                    ],
                )
            ])
        ],
    )
])

The styling boundary

Email clients strip <style> tags and ignore most modern CSS, so every dash-email component takes a style dict of camelCase CSS that renders inline on the element.

Rules of thumb:

de.EmailRow([
    de.EmailColumn(style={"width": "70%"}, children=[de.EmailText("Product")]),
    de.EmailColumn(style={"width": "30%", "textAlign": "right"}, children=[de.EmailText("$99.00")]),
])

Sending with Resend

Templates built with these components convert to email-safe HTML and send through the Resend API — single sends, batches up to 100 recipients, and scheduled delivery (up to 30 days ahead). Set RESEND_API_KEY in your environment:

from utils.email_sender import send_email, component_to_html

html = component_to_html(my_email_component)
result = send_email(
    to_email="[email protected]",
    subject="Welcome!",
    html_content=html,
    from_email="[email protected]",
    scheduled_at="in 1 hour",   # optional — ISO 8601 or natural language
)

This documentation site uses exactly this pipeline for its own transactional and announcement emails.


Components

ComponentCategoryWhat it is
EmailStructureRoot wrapper for the email template
EmailHeadStructureMetadata container (font imports, etc.)
EmailPreviewStructureInbox preview text — visible next to the subject, hidden in body
EmailBodyStructureMain content wrapper
EmailContainerLayoutCentered container at the 600px email standard
EmailSectionLayoutGroups related content with its own background/padding
EmailRowLayoutHorizontal row — renders as an HTML <table>
EmailColumnLayoutColumn within a row — renders as a <td>
EmailHeadingContentHeadings h1h6 via the as_ prop
EmailTextContentParagraph text
EmailButtonContentBulletproof call-to-action button (styled anchor)
EmailLinkContentInline hyperlink
EmailImageMediaImage with explicit dimensions
EmailDividerMediaHorizontal rule separator
EmailFontMediaWeb font loading with graceful fallback

Component Properties

PropertyTypeDefaultDescription
idstringDash callback identity — available on every component
styledictcamelCase CSS, rendered inline for email-client safety
childrennodeChild components / text
as_string"h1"EmailHeading level: "h1""h6" (Python-safe alias for as)
hrefstringEmailButton / EmailLink target URL
srcstringEmailImage source URL
altstringEmailImage alt text
width / heightstring \numberEmailImage explicit dimensions
langstring"en"Email document language
fontFamilystringEmailFont font family name
fallbackFontFamilystringEmailFont web-safe fallback
webFontobjectEmailFont web font source configuration

Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: