How to prevent emails being sent to huge mailing lists or stopping messages when users have used reply-all against a massive list of users.
WARNING: An email with 1 address in the To header can actually be sent to multiple email addresses if the email system is abused. For instance a group email address. Counting the number of email addresses in the To: or Cc: header therefore does not guarantee that you'll block emails that are being sent to many people.
In the DATA ACL (only in the DATA ACL!), you can check the number of email addresses in the To or Cc header by a two step process. To test these headers, you access it with $h_To: and $h_Cc: NOTE: The trailing colon is required. Let's assume that the To: header is:
"Test user" <john@example.org>,<jsmith@example.com>,"John Smith" <johnsmith@example.net>
$ exim -be '${addresses:"Test user" <john@example.org>,<jsmith@example.com>,"John Smith" <johnsmith@example.net>}' john@example.org:jsmith@example.com:johnsmith@example.net
$ exim -be '${listcount:${addresses:"Test user" <john@example.org>,<jsmith@example.com>,"John Smith" <johnsmith@example.net>}}'
With current versions of Exim (4.82), what this will ultimately look like in your DATA ACL will be something like this:
deny message = Too many recipients condition = ${if >{ ${listcount:${addresses:$h_To:,$h_Cc:}} }{10} {yes}{no}}
If you are using an older version you can use an older version that iterates over the list and increments a counter:
deny message = Too many recipients condition = ${if >{ ${reduce {${addresses:$h_To:,$h_Cc:}} {0} {${eval:$value+1}}}} {10} {yes}{no}}
Note that in both cases above, the {yes}{no} portion is superfluous. The return of the ${if…} statement is always going to be a true or false, so with this in mind, you can leave it off if you want. I prefer to explicitly put it in because it makes it more readable (to me, and to any who might follow me and have to read this code).