Introduction
Ansible can send email notifications using the community.general.mail module — for deployment reports, error alerts, job completion summaries, and scheduled status updates. This article covers Gmail SMTP setup, HTML emails, attachments, conditional failure alerts, and securing credentials with Ansible Vault.
Prerequisites
Install the community.general collection:
ansible-galaxy collection install community.general
Basic Email
---
- name: Send email report
hosts: localhost
gather_facts: false
tasks:
- name: Send notification
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to: "Ops Team <ops@example.com>"
subject: "Ansible Playbook Report"
body: "Deployment completed successfully on {{ ansible_date_time.date | default('today') }}"
delegate_to: localhost
Module Parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
host | No | localhost | SMTP server hostname |
port | No | 25 | SMTP port (587 for TLS, 465 for SSL) |
username | No | — | SMTP authentication username |
password | No | — | SMTP authentication password |
to | Yes | — | Recipient(s) — string or list |
cc | No | — | CC recipients |
bcc | No | — | BCC recipients |
from | No | root | Sender address |
subject | Yes | — | Email subject line |
body | No | — | Email body content |
subtype | No | plain | plain or html |
attach | No | — | File paths to attach |
headers | No | — | Custom email headers |
charset | No | utf-8 | Character encoding |
secure | No | starttls | always, never, starttls, try |
timeout | No | 20 | Connection timeout in seconds |
Gmail SMTP Setup
App Password (Required for Gmail)
Gmail requires an App Password when 2FA is enabled:
- Go to Google Account Security
- Enable 2-Step Verification
- Generate an App Password: Security → App Passwords → Mail
- Use the 16-character app password in your playbook
Secure Credentials with Vault
# Create encrypted vars file
ansible-vault create vars/email_creds.yml
# vars/email_creds.yml (encrypted)
vault_email_user: "your.email@gmail.com"
vault_email_pass: "abcd efgh ijkl mnop" # App Password
---
- name: Send email with vault credentials
hosts: localhost
gather_facts: false
vars_files:
- vars/email_creds.yml
tasks:
- name: Send report
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to: ops@example.com
subject: "Daily Report"
body: "All systems operational."
delegate_to: localhost
no_log: true
HTML Emails
- name: Send HTML report
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to: team@example.com
subject: "Deployment Report — {{ ansible_date_time.date }}"
subtype: html
body: |
<html>
<body>
<h2>Deployment Report</h2>
<table border="1" cellpadding="5">
<tr><th>Host</th><th>Status</th></tr>
{% for host in ansible_play_hosts %}
<tr>
<td>{{ host }}</td>
<td style="color: green;">✅ Success</td>
</tr>
{% endfor %}
</table>
<p>Completed at {{ ansible_date_time.iso8601 }}</p>
</body>
</html>
delegate_to: localhost
Email with Attachments
- name: Send report with log attachment
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to: admin@example.com
subject: "Ansible Job Log"
body: "Please find the attached execution log."
attach:
- /var/log/ansible/playbook.log
- /tmp/reports/inventory.csv
delegate_to: localhost
Failure Notifications
Send Email on Playbook Failure
---
- name: Deploy application
hosts: webservers
become: true
tasks:
- name: Pull latest code
ansible.builtin.git:
repo: https://github.com/example/app.git
dest: /opt/app
version: main
- name: Restart application
ansible.builtin.service:
name: myapp
state: restarted
rescue:
- name: Send failure alert
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to: oncall@example.com
subject: "🚨 DEPLOYMENT FAILED on {{ inventory_hostname }}"
subtype: html
body: |
<h3>Deployment Failed</h3>
<p><b>Host:</b> {{ inventory_hostname }}</p>
<p><b>Error:</b> {{ ansible_failed_result.msg | default('Unknown') }}</p>
<p><b>Time:</b> {{ now() }}</p>
delegate_to: localhost
no_log: true
Send Summary After All Hosts
---
- name: Deploy and report
hosts: webservers
become: true
tasks:
- name: Deploy application
ansible.builtin.command: /opt/deploy.sh
register: deploy_result
- name: Send summary email
hosts: localhost
gather_facts: false
tasks:
- name: Send deployment summary
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to: team@example.com
subject: "Deployment Complete — {{ ansible_play_hosts | length }} hosts"
body: |
Deployment finished.
Hosts: {{ groups['webservers'] | join(', ') }}
Time: {{ now() }}
no_log: true
Multiple Recipients
- name: Send to multiple recipients
community.general.mail:
host: smtp.gmail.com
port: 587
username: "{{ vault_email_user }}"
password: "{{ vault_email_pass }}"
to:
- "Admin <admin@example.com>"
- "Ops <ops@example.com>"
cc:
- "Manager <manager@example.com>"
bcc:
- "Audit <audit@example.com>"
subject: "Weekly Infrastructure Report"
body: "See attached report."
Other SMTP Providers
| Provider | Host | Port | Secure |
|---|---|---|---|
| Gmail | smtp.gmail.com | 587 | starttls |
| Outlook/O365 | smtp.office365.com | 587 | starttls |
| Amazon SES | email-smtp.us-east-1.amazonaws.com | 587 | starttls |
| SendGrid | smtp.sendgrid.net | 587 | starttls |
| Mailgun | smtp.mailgun.org | 587 | starttls |
| Local relay | localhost | 25 | never |
Troubleshooting
Authentication Failed
fatal: "Authentication unsuccessful"
- Gmail: Use App Password, not your regular password
- Ensure 2FA is enabled for App Passwords to work
- Check
secure: starttlsfor port 587
Connection Timeout
# Increase timeout for slow SMTP servers
- community.general.mail:
host: smtp.example.com
timeout: 60
Certificate Errors
# For self-signed SMTP servers (not recommended for production)
- community.general.mail:
host: internal-smtp.example.com
port: 587
secure: try
Best Practices
- Always use Vault for SMTP credentials — never hardcode passwords
- Use
no_log: trueon mail tasks to hide credentials in output - Use
delegate_to: localhost— send from the controller, not remote hosts - Set
subtype: htmlfor rich reports with tables and formatting - Use
rescueblocks for failure notifications, not separate plays - Rate limit — don't send per-host emails; aggregate into summaries
- Test locally first — use
mailhogormailtrap.iofor development
Related Articles
- Ansible Vault Guide
- Ansible Callback Plugins Guide
- Ansible Error Handling Guide
- Ansible debug Module
Conclusion
The community.general.mail module sends email notifications directly from Ansible playbooks — deployment reports, failure alerts, and scheduled summaries. Use Gmail with App Passwords and Ansible Vault for secure SMTP authentication. Combine with rescue blocks for automatic failure notifications and HTML subtype for rich formatted reports.