Airflow Email Notification Not Sending Fix
In this tutorial, you'll learn about Airflow Email Notification Not Sending Fix. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Airflow does not send email notifications on task failure:
Task failed but no email was sent to the recipients.
Email delivery requires SMTP configuration in airflow.cfg. If the SMTP server is unreachable, authentication fails, or the email configuration is incomplete, Airflow silently skips email sending. The error may appear in the scheduler logs.
Step-by-Step Fix
1. Configure SMTP in airflow.cfg
WRONG — using default configuration that doesn't work:
[email]
email_backend = airflow.utils.email.send_email_smtp
RIGHT — provide full SMTP settings:
[smtp]
smtp_host = smtp.gmail.com
smtp_starttls = True
smtp_ssl = False
smtp_user = your-email@gmail.com
smtp_password = your-app-password
smtp_port = 587
smtp_mail_from = your-email@gmail.com
For Gmail, use an App Password (not your regular password) generated from Google Account > Security > App Passwords.
2. Set email recipients on tasks
WRONG — missing email_on_failure:
task = PythonOperator(
task_id="my_task",
python_callable=my_func,
# No email_on_failure
)
RIGHT — configure notifications:
default_args = {
"email": ["alerts"@example".com"],
"email_on_failure": True,
"email_on_retry": False, # Don't email on retry, only final failure
"email_on_success": False,
}
task = PythonOperator(
task_id="my_task",
python_callable=my_func,
default_args=default_args,
)
3. Test SMTP connection
WRONG — assuming config is correct:
RIGHT — test from the Airflow environment:
# Test SMTP connection using Python
python -c "
import smtplib
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login('your-email@gmail.com', 'your-app-password')
server.sendmail('from@example.com', 'to@example.com', 'Test message')
server.quit()
print('SMTP OK')
"
4. Check scheduler logs for email errors
# Look for email-related errors
grep -i "email\|smtp\|mail" ~/airflow/logs/scheduler/*.log
Common errors:
smtplib.SMTPAuthenticationError → Wrong credentials
smtplib.SMTPConnectError → Server unreachable
socket.gaierror → DNS resolution failed
5. Use environment variables
WRONG — hardcoding SMTP credentials:
RIGHT — use environment variables:
export AIRFLOW__SMTP__SMTP_HOST=smtp.sendgrid.net
export AIRFLOW__SMTP__SMTP_USER=apikey
export AIRFLOW__SMTP__SMTP_PASSWORD=SG.xxxxx
export AIRFLOW__SMTP__SMTP_MAIL_FROM=noreply@example.com
Or use Airflow's secrets backend:
airflow variables set smtp_password SG.xxxxx
6. Configure default email on DAG level
from datetime import datetime, timedelta
default_args = {
"owner": "data-team",
"depends_on_past": False,
"email": ["alerts"@example".com", "team"@example".com"],
"email_on_failure": True,
"email_on_retry": True,
"retries": 2,
"retry_delay": timedelta(minutes=5),
}
with DAG(
dag_id="email_notification_dag",
default_args=default_args,
start_date=datetime(2024, 1, 1),
schedule="@daily",
catchup=False,
):
task = PythonOperator(
task_id="fail_example",
python_callable=lambda: 1/0 # Intentional failure
)
Expected output: email notification sent to the configured recipients on task failure.
Prevention
- Set
email_on_failurein default_args for all DAGs. - Test SMTP configuration before relying on failure notifications.
- Use App Passwords or dedicated SMTP services (SendGrid, SES) for production.
- Monitor Airflow logs for email delivery failures.
- Keep
email_on_retryfalse to avoid spam from retried tasks.
Common Mistakes with email notification
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations
These mistakes appear frequently in real-world AIRFLOW code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro