Skip to content

Airflow Email Notification Not Sending Fix

DodaTech Updated 2026-06-24 3 min read

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_failure in 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_retry false to avoid spam from retried tasks.

Common Mistakes with email notification

  1. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  2. Non-exhaustive pattern matches that compile with warnings then crash at runtime
  3. Misunderstanding that String is [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

### Why does Airflow send emails but they go to spam?

The sender domain lacks SPF, DKIM, or DMARC DNS records. Configure these email authentication records for your domain. Using a reputable SMTP provider (SendGrid, AWS SES, Mailgun) improves deliverability.

Can I use different SMTP for DAGs vs admin alerts?

Airflow uses one global SMTP configuration. For per-DAG email customization, use a custom Python callback that sends email via a different provider based on the DAG ID.

How do I send custom email content on failure?

Override on_failure_callback on the DAG or task:

def failure_alert(context):
    dag_id = context["dag"].dag_id
    task_id = context["task"].task_id
    send_custom_email(f"DAG {dag_id} failed at task {task_id}")

task = PythonOperator( task_id="my_task", python_callable=my_func, on_failure_callback=failure_alert, )

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro