In an effort to rate limit outgoing emails per recipient (all emails are sent by the same user), I've been doing some testing in a very simple environment:
The Webs
^
|
+-------------------+ SMTP? +--------+---------+
| +---------------> | mail.example.com |
| billyw.localhost | | (smarthost) |
| (exim4) | | |
+-------------------+ +------------------+
billyw.localhost
is a Debian machine. Using dpkg-reconfigure exim4-config
, I set it up to use mail.example.com
as a smarthost.
Currently, I'm rate limiting by adding an ACL to acl_not_smtp
:
acl_not_smtp = acl_check_not_smtp
acl_check_not_smtp:
# Rate limit based on the recipient address
discard
ratelimit = 7 / 1m / per_mail / $recipients
log_message = Rate limit exceeded for $recipients: $sender_rate/$sender_rate_period (max $sender_rate_limit)
accept
I'm testing this with the following command on billyw.localhost
:
for i in {1..10}; do
mail -s testing billyw@mypersonalemail.com <<< ''
mail -s testing billyw@myotherpersonalemail.com <<< ''
done
This configuration seems to work as intended; it allows 7 emails through to each recipient and discards the final 3 per recipient.
However, if I try to use this same configuration in an SMTP-related ACL, such as:
acl_smtp_connect
acl_smtp_rcpt
acl_smtp_mail
Then the rate limiting entry of the ACL isn't hooked and all 10 messages are sent.
Why isn't the rate limiting being applied when it's put in an smtp-related ACL?
Best Answer
The
acl_not_smtp
is equivalent toacl_data
for SMTP traffic. Try rate limiting in that ACL. SMTP connections give you more ACL options where you can place the message. (Note:discard
is a blackhole variant ofaccept
so you won't see reject messages.) Discarding is rather drastic, and I would usedefer
ordeny
for SMTP traffic.Rate limiting is covered in chapter 42 section 38 of the Exim Specification. You can test with modified configuration so you can rate limit harder while testing than you would once you implement. Allow time for the test limits to clear before implementing.
Try adding the following to your
acl_smtp_rcpt
:/usr/bin/mail
runs the localsendmail
program to deliver the mail rather than connecting over the network stack. In your case, exim4 is used as a drop-in replacement for sendmail. The mail will be treated as a non-smtp delivery. Rate limiting will need to be done using a non-smtp ACL.