Yes, you can do this in SpamAssassin. I'm not as much an exim expert, but iirc exim can do this as well (though it may have a hard recipient limitation that is agnostic to To/Cc vs Bcc).
This should do it:
header DTECH_TEN_TOCC_IN_SAME_DOM ToCc =~ /(\@[^,>;]{3,99}[a-z]\b)(?:[^\@.-][^\@]{0,99}\1){10}(?![.-])/
describe DTECH_TEN_TOCC_IN_SAME_DOM Ten consecutive recipients have the same domain
As I've written it, this only catches ten consecutive recipients with the same domain, which must all be in the same header (ToCc
means either To xor Cc; it does not merge the headers). If you change the third character class from [^\@]{0,99}
to .{0,999}
to match any character over a longer period of time, the rule will be good for more than just consecutively listed addresses, but note that this would make the regex far more expensive to compute.
You also have to make sure that SpamAssassin is looking at your internal and outbound mail, which is nonstandard. Finally, you'll have to score the rule. Please test copiously before you do that. Especially since this is not a spam rule (it will hit more non-spam than spam; consider a similar rule with testing stats: __TO_MANY).
You will not, however, be able to tell users why the message was rejected. An SMTP reject (e.g. from Exim) can have a custom "why this was rejected" prompt, which is highly useful for policing attachment sizes or even informing users that they're sending too much mail (perhaps they are infected). You can configure Exim to run SA at SMTP time (e.g. sa-exim), but then every spam rejection would have the same message to the end user. The other option would be to accept the message and then bounce it back, including the SpamAssassin rule hits. Be very very careful with that approach as it often leads to backscatter.