exim4 - Why is rate limiting outbound mail to a smarthost only working with acl_not_smtp?

5,829

The acl_not_smtp is equivalent to acl_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 of accept so you won't see reject messages.) Discarding is rather drastic, and I would use defer or deny 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:

defer
  ratelimit = 7 / 1m / $recipients
  message = Rate limit exceeded for $recipients: \
            $sender_rate/$sender_rate_period (max $sender_rate_limit)

/usr/bin/mail runs the local sendmail 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.

Share:
5,829

Related videos on Youtube

billyw
Author by

billyw

Updated on September 18, 2022

Comments

  • billyw
    billyw almost 2 years

    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 [email protected] <<< ''
      mail -s testing [email protected] <<< ''
    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?

  • billyw
    billyw almost 10 years
    Thanks for your response. I followed your recommendation, but acl_smtp_rcpt and acl_smtp_data aren't applying the rate limit to the outgoing messages. Which leads me to the question: Why do SMTP-related ACLs not apply to outbound emails sent to a smarthost via /usr/bin/mail? Is it actually sending batched SMTP instead of SMTP?
  • BillThor
    BillThor almost 10 years
    @billw /usr/bin/mail runs the local sendmail program to deliver the mail rather than connecting over the network stack. In your case, exim4 is used as a dropin replacement for sendmail. The mail will be treated as a non-smtp deliviry. Rate limiting will need to be done using a non-smtp ACL.
  • billyw
    billyw almost 10 years
    Ah, that makes a lot more sense. This whole time I thought I was limiting outbound traffic to the smarthost, but I was actually limiting inbound traffic from /usr/bin/mail! If you word your comment into the main text of your answer, then I'll be happy to accept it.
  • BillThor
    BillThor almost 10 years
    @billyw I've added the sendmail process into the main answer.