When managing Linux servers, we often need emails from system accounts (root, cron, backup) to be delivered to a centralized monitoring address. The default Exim configuration requires manual maintenance of /etc/email-addresses
:
root: alerts@example.com
cron: alerts@example.com
backup: alerts@example.com
nagios: alerts@example.com
This becomes problematic when:
- New system users are created during package installations
- Team members forget to update the mapping file
- You want consistent sender identification across all services
We'll modify Exim's rewrite configuration to implement a fallback mechanism. First, let's examine the default Debian configuration:
begin rewrite
.ifndef NO_EAA_REWRITE_REWRITE
*@+local_domains "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}fail}" Ffrs
*@ETC_MAILNAME "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}fail}" Ffrs
.endif
Replace the existing rewrite section with this enhanced version:
begin rewrite
# First try /etc/email-addresses lookup
*@+local_domains "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}{alerts@example.com}}" Ffrs
# Fallback to our default address
*@ETC_MAILNAME "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}{alerts@example.com}}" Ffrs
For more control, we can modify the SMTP transport directly in exim4.conf.template
:
begin transports
remote_smtp:
driver = smtp
headers_rewrite = *@+local_domains alerts@example.com frs : \
*@ETC_MAILNAME alerts@example.com frs
return_path = alerts@example.com
After making changes, test with:
exim4 -bt root@localhost
exim4 -bv nonexistent-user@localhost
Both commands should show the email being routed to alerts@example.com
.
For more complex scenarios where some senders need exceptions:
begin rewrite
.ifndef NO_EAA_REWRITE_REWRITE
*@+local_domains "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}{${if eq{$sender_host_address}{127.0.0.1}\
{alerts@example.com}{${local_part}@${domain}}}}}" Ffrs
.endif
In many server environments, we need to ensure all system-generated emails (from cron jobs, backups, services, etc.) are consistently sent from a single sender address like alert@example.com
. The traditional approach of maintaining /etc/email-addresses
with individual mappings becomes problematic when:
- New system users are added automatically by packages
- Multiple administrators manage the server
- You want to ensure no emails leak with default sender addresses
The most effective solution is to modify Exim's rewrite configuration. Here's how to implement a global sender address override while preserving the option for specific exceptions:
begin rewrite
# First keep existing per-user mappings from /etc/email-addresses
.ifndef NO_EAA_REWRITE_REWRITE
*@+local_domains "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}{alert@example.com}}" Ffrs
*@ETC_MAILNAME "${lookup{${local_part}}lsearch{/etc/email-addresses}\
{$value}{alert@example.com}}" Ffrs
.endif
# Then add catch-all rewrite rule
*@+local_domains alert@example.com Ffrs
*@ETC_MAILNAME alert@example.com Ffrs
The configuration implements a two-stage approach:
- First attempts to find a specific mapping in
/etc/email-addresses
- Falls back to
alert@example.com
if no mapping exists - Finally applies a global rewrite for any remaining cases
After making changes, verify with:
exim -bt testuser@yourdomain.com
exim -brw cron@yourdomain.com
For comprehensive coverage, you might also want to:
- Set
qualify_domain
in exim.conf to your domain - Configure SPF records for your catch-all address
- Monitor the sender address in your mail queue:
exim -bp | awk '{print $4}' | sort | uniq -c
If you prefer transport-level control, add this to your SMTP transport:
remote_smtp:
driver = smtp
return_path = alert@example.com
headers_remove = From
headers_add = "From: System Alerts "
The transport-level approach is more aggressive and will override all sender information, which may be preferable in some security-conscious environments.