Skip to content

Email Executor Guide

The send_email_executor provides email sending capabilities via two providers: - Resend: Cloud email API via HTTP (recommended for simplicity) - SMTP: Traditional SMTP protocol (for self-hosted or existing mail servers)

Installation

For SMTP support, install the email extras:

pip install apflow[email]

Resend provider works out of the box (uses HTTP).

Quick Start

Configure once in .env, then send emails with minimal input:

# .env file
RESEND_API_KEY=re_xxxxxxxxxxxxx
FROM_EMAIL=[email protected]
# Send email with just recipient, subject, and body
apflow run - <<EOF
{
  "id": "send-welcome",
  "name": "Send Welcome Email",
  "schemas": {"method": "send_email_executor"},
  "inputs": {
    "to": "[email protected]",
    "subject": "Welcome!",
    "body": "Welcome to our service!"
  }
}
EOF

Explicit Configuration

Override env vars or use without them:

apflow run - <<EOF
{
  "id": "send-notification",
  "name": "Send Notification",
  "schemas": {"method": "send_email_executor"},
  "inputs": {
    "provider": "resend",
    "api_key": "re_xxxxxxxxxxxxx",
    "to": "[email protected]",
    "from_email": "[email protected]",
    "subject": "Order Shipped",
    "body": "Your order has been shipped!"
  }
}
EOF

Environment Variables

Variable Type Default Description
RESEND_API_KEY string - Resend API key
SMTP_HOST string - SMTP server hostname
SMTP_PORT integer 587 SMTP server port
SMTP_USERNAME string - SMTP auth username
SMTP_PASSWORD string - SMTP auth password
SMTP_USE_TLS string true Use STARTTLS ("true"/"false")
FROM_EMAIL string - Default sender email

Priority: Input values always override environment variables.

Auto-Detection: If provider is not specified: - RESEND_API_KEY set → uses resend - SMTP_HOST set → uses smtp

Input Schema

Field Type Required Description
provider string No* "resend" or "smtp" (auto-detected from env)
to string/array Yes Recipient email(s)
subject string Yes Email subject
from_email string No* Sender email (falls back to FROM_EMAIL env)
body string No** Plain text body
html string No** HTML body
cc string/array No CC recipients
bcc string/array No BCC recipients
reply_to string No Reply-to address
timeout float No Request timeout in seconds (default: 30)
api_key string No* Resend API key (falls back to RESEND_API_KEY env)
smtp_host string No* SMTP hostname (falls back to SMTP_HOST env)
smtp_port integer No SMTP port (falls back to SMTP_PORT env, default: 587)
smtp_username string No SMTP username (falls back to SMTP_USERNAME env)
smtp_password string No SMTP password (falls back to SMTP_PASSWORD env)
smtp_use_tls boolean No Use STARTTLS (falls back to SMTP_USE_TLS env)

* Required unless provided via environment variable ** At least one of body or html is required

Output Schema

Field Type Description
success boolean Whether email was sent successfully
provider string Provider used (resend or smtp)
message_id string Message ID (Resend only)
status_code integer HTTP status code (Resend only)
message string Success message (SMTP only)
error string Error details (on failure)

Examples

Example 1: Simple Text Email (Resend)

# With env vars: RESEND_API_KEY, FROM_EMAIL
apflow run - <<EOF
{
  "id": "simple-email",
  "name": "Simple Email",
  "schemas": {"method": "send_email_executor"},
  "inputs": {
    "to": "[email protected]",
    "subject": "Hello",
    "body": "This is a simple text email."
  }
}
EOF

Example 2: HTML Email with CC/BCC

{
  "id": "html-email",
  "name": "HTML Email",
  "schemas": {"method": "send_email_executor"},
  "inputs": {
    "to": ["[email protected]", "[email protected]"],
    "cc": "[email protected]",
    "bcc": ["[email protected]"],
    "subject": "Monthly Report",
    "html": "<h1>Monthly Report</h1><p>Please find the report attached.</p>",
    "body": "Monthly Report\n\nPlease find the report attached.",
    "reply_to": "[email protected]"
  }
}

Example 3: SMTP Configuration

# .env file for SMTP
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=[email protected]
SMTP_PASSWORD=your-app-password
FROM_EMAIL=[email protected]
{
  "id": "smtp-email",
  "name": "SMTP Email",
  "schemas": {"method": "send_email_executor"},
  "inputs": {
    "to": "[email protected]",
    "subject": "Test via SMTP",
    "body": "This email was sent via SMTP."
  }
}

Example 4: Task Tree with Email Notification

{
  "id": "workflow-with-email",
  "name": "Data Processing with Email Notification",
  "schemas": {"method": "aggregate_results_executor"},
  "children": [
    {
      "id": "fetch-data",
      "name": "Fetch Data",
      "schemas": {"method": "rest_executor"},
      "inputs": {
        "method": "GET",
        "url": "https://api.example.com/data"
      }
    },
    {
      "id": "notify-complete",
      "name": "Send Completion Email",
      "schemas": {"method": "send_email_executor"},
      "inputs": {
        "to": "[email protected]",
        "subject": "Data Processing Complete",
        "body": "The data processing workflow has completed successfully."
      },
      "dependencies": ["fetch-data"]
    }
  ]
}

Example 5: Python API Usage

import asyncio
from apflow.extensions.email import SendEmailExecutor

async def send_email():
    executor = SendEmailExecutor()

    # With env vars configured, minimal input needed
    result = await executor.execute({
        "to": "[email protected]",
        "subject": "Hello from Python",
        "body": "This email was sent using the Python API."
    })

    if result["success"]:
        print(f"Email sent! Message ID: {result.get('message_id')}")
    else:
        print(f"Failed to send: {result.get('error')}")

asyncio.run(send_email())

Provider Comparison

Feature Resend SMTP
Setup Complexity Low (just API key) Medium (host, port, auth)
Dependency None (uses HTTP) aiosmtplib
Message ID Yes No
Deliverability High (managed service) Depends on server
Cost Free tier available Free (self-hosted)
Best For Transactional emails Existing mail servers

Troubleshooting

"provider is required" Error

Cause: No provider specified and no env vars set.

Solution: Either: 1. Set RESEND_API_KEY or SMTP_HOST environment variable 2. Specify provider in task inputs

"api_key is required for resend provider" Error

Cause: Using Resend without API key.

Solution: Either: 1. Set RESEND_API_KEY environment variable 2. Provide api_key in task inputs

"aiosmtplib is not installed" Error

Cause: SMTP provider requires optional dependency.

Solution: Install email extras:

pip install apflow[email]

SMTP Connection Timeout

Cause: Wrong host/port or firewall blocking.

Solutions: 1. Verify SMTP_HOST and SMTP_PORT are correct 2. Check firewall allows outbound connections 3. Try port 465 (SSL) or 25 (no encryption) if 587 fails 4. Increase timeout value in inputs

Gmail "Less secure app" Error

Cause: Gmail blocks basic auth.

Solution: Use App Passwords: 1. Enable 2-Factor Authentication on Google Account 2. Generate App Password: Google Account → Security → App Passwords 3. Use the generated password as SMTP_PASSWORD

See Also