Exim conditional logic

email-serverexim

I am trying to have exim check the domain of outgoing and incoming mails against a domainlist. If the FROM address of the outgoing mail and the TO/CC/BCC address of the incoming mail are not in the list of local domains, I want to reject/discard the message. Below is what I have come up with, placed in the "acl_not_smpt" section:

discard
condition = ${if and {{! match_domain{${domain:${address:$h_from:}}}{+local_domains}}\
{if or {\
{! match_domain{${domain:${address:$h_to:}}}{+local_domains}}}\
{! match_domain{${domain:${address:$h_cc:}}}{+local_domains}}}\
{! match_domain{${domain:${address:$h_bcc:}}}{+local_domains}}}\
}\
}\
}\
message = Mail discarded for spoofing

But I am getting the below error in my exim log:

unknown condition "if" inside "and{…}" condition

Very new to exim syntax, some help appreciated.

Best Answer

The second if is incorrect and in fact you don't need it: the and conditions can use any boolean function (cf. expansion conditions), while $if returns a string (cf. expansion items and expansion operators). There are also some additional }. A working condition becomes:

condition = ${if and {\
              {!match_domain{${domain:${address:$h_from:}}}{+local_domains}}\
              { or {\
                {! match_domain{${domain:${address:$h_to:}}}{+local_domains}}\
                {! match_domain{${domain:${address:$h_cc:}}}{+local_domains}}\
                {! match_domain{${domain:${address:$h_bcc:}}}{+local_domains}}\
              }}\
            }}

This condition has some bugs: it does check not for multiple recipients and From: addresses.

Remark also that the acl_not_smtp ACL is run only when a (local) user invokes exim4 with the -bm or -bS option. That means your ACL will block local users from sending outgoing mail.

If that's what you want to do, then your expression can be simplified:

  • The check on From: header can be done more effectively configuring Exim's trusted users.

  • Instead of checking separately for the To:, Cc: and Bcc:, you can use the $recipients variable, that contains all of them in a , separated string.

All of this amounts to two ACL stanzas:

  accept
    condition = ${if forall {<,${recipients}}\
                  {match_domain{${domain:${item}}}{+local_domains}}\
                }
  deny

In general you can debug your string expansions and non-SMTP ACLs by creating (or saving) and e-mail (lets say to email.eml) and running:

exim4 -d-all+acl+expand -bm -t < email.eml

as root (warning: this will attempt a real e-mail delivery), while to check just the expansions run:

exim4 -bem email.eml
Related Topic