Prefect Email
Prefect Email provides integrations for sending emails within Prefect workflows, enabling notifications and reporting capabilities. It's an official Prefect integration, currently at version 0.4.2, and its release cadence often aligns with new Prefect core features or significant updates to the Prefect platform.
Common errors
-
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted.')
cause The provided SMTP username or password is incorrect, or the user lacks permission to send email through the server.fixVerify your `username` and `password` in `EmailServerCredentials`. Check if two-factor authentication is enabled for the SMTP account and if an app-specific password is required. -
ConnectionRefusedError: [Errno 111] Connection refused
cause The client could not establish a connection to the SMTP server. This usually indicates an incorrect host/port, a firewall blocking the connection, or the SMTP server not running/listening on the specified port.fixConfirm the `host` and `port` for `EmailServerCredentials` are correct. Check local and remote firewalls. Ensure the SMTP server is running and configured to accept connections on that port. -
ModuleNotFoundError: No module named 'prefect_email'
cause The `prefect-email` library has not been installed in the current Python environment.fixRun `pip install prefect-email` to install the library. -
AttributeError: 'NoneType' object has no attribute 'host' (when loading a block)
cause This typically occurs when `EmailServerCredentials.load('block-name')` is called, but the specified block does not exist in the Prefect API server, or the Prefect API server is not running/reachable.fixEnsure the Prefect API server is running and accessible. Verify that an `EmailServerCredentials` block with the exact name 'block-name' has been created and saved to the Prefect server.
Warnings
- gotcha Always store SMTP credentials securely using Prefect Blocks (e.g., EmailServerCredentials Block) rather than hardcoding them or relying solely on environment variables in production deployments. Blocks provide encrypted storage and better management.
- gotcha SMTP server connection issues (e.g., 'Connection refused', 'timeout') are often caused by incorrect host/port, firewall restrictions, or incorrect TLS/SSL settings.
- gotcha For `EmailServerCredentials.load('block-name')` to work, a Prefect API server must be running and accessible by your flow/agent. If running locally without a server, direct instantiation or using environment variables is necessary.
- gotcha When sending HTML emails, use the `email_send_html_message` task and set the `html` parameter to `True` for the `msg` argument in `email_send_message`.
Install
-
pip install prefect-email
Imports
- EmailServerCredentials
from prefect_email import EmailServerCredentials
from prefect_email.credentials import EmailServerCredentials
- email_send_message
from prefect_email import send_email
from prefect_email.tasks import email_send_message
- email_send_html_message
from prefect_email.tasks import email_send_html_message
Quickstart
import os
from prefect import flow
from prefect_email.credentials import EmailServerCredentials
from prefect_email.tasks import email_send_message
@flow(log_prints=True)
def send_notification_email_flow():
# For production, it is highly recommended to store credentials
# in a Prefect EmailServerCredentials Block for security and reusability.
# Example: EmailServerCredentials(host=..., port=..., username=..., password=...).save('my-email-creds')
# Then load: credentials = EmailServerCredentials.load('my-email-creds')
# For this quickstart, we'll instantiate directly from environment variables.
# Ensure these are set: SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, TO_EMAIL, FROM_EMAIL
credentials = EmailServerCredentials(
host=os.environ.get("SMTP_HOST", "smtp.mailtrap.io"),
port=int(os.environ.get("SMTP_PORT", 2525)),
username=os.environ.get("SMTP_USERNAME", "YOUR_USERNAME"),
password=os.environ.get("SMTP_PASSWORD", "YOUR_PASSWORD"),
use_tls=True # Often required for secure SMTP
)
to_emails = os.environ.get("TO_EMAIL", "recipient@example.com").split(',')
from_email = os.environ.get("FROM_EMAIL", "sender@example.com")
subject = "Prefect Email Test Notification"
body = "This is a test email sent from a Prefect flow using prefect-email."
print(f"Attempting to send email from {from_email} to {to_emails}...")
try:
email_send_message(
smtp_credentials=credentials,
subject=subject,
msg=body,
email_from=from_email,
email_to=to_emails
)
print("Email sent successfully!")
except Exception as e:
print(f"Failed to send email: {e}")
if __name__ == "__main__":
# To run locally, set environment variables like:
# export SMTP_HOST="smtp.mailtrap.io"
# export SMTP_PORT="2525"
# export SMTP_USERNAME="your_mailtrap_username"
# export SMTP_PASSWORD="your_mailtrap_password"
# export TO_EMAIL="your_email@example.com"
# export FROM_EMAIL="prefect@example.com"
# Then execute: python your_script_name.py
send_notification_email_flow()