====== Exim4 - Reject emails with many To/Cc recipients ======
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 Smith"
===== Step 1: To header converted to a (colon-separated) list =====
$ exim -be '${addresses:"Test user" ,,"John Smith" }'
john@example.org:jsmith@example.com:johnsmith@example.net
===== step 2: Now count the number of list items =====
$ exim -be '${listcount:${addresses:"Test user" ,,"John Smith" }}'
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).