13. Exempting Forwarded Mail

After adding all these checks in the SMTP transaction, we may find ourselves indirectly creating collateral spam as a result of rejecting mails forwarded from trusted sources, such as mailing lists and mail accounts on other sites (see the discussion on Forwarded Mail for details). We now need to whitelist these hosts in order to exempt them from SMTP rejections -- at least those rejections that are caused by our spam and/or virus filtering.

In this example, we will consult two files in response to each RCPT TO: command:

If your mail users do not have local user accounts and home directories, you may want to modify the file paths and/or lookup mechanisms to something more suitable for your system (e.g. database lookups or LDAP queries).

If the sender host is found in one of these whitelists, we save the word accept in $acl_m0, and clear the contents of $acl_m1, as described in the previous section on Selective Delays. This will indicate that we should not reject the mail in subsequent statements.

In the acl_rcpt_to, we insert the following statement after validating the recipient address, but before any accept statements pertaining to unauthenticated deliveries from remote hosts to local users (i.e. before any greylist checks, envelope signature checks, etc):

  # Accept the mail if the sending host is matched in the global
  # whitelist file.  Temporarily set $acl_m9 to point to this  file. 
  # If the host is found, set a flag in $acl_m0 and clear $acl_m1 to 
  # indicate that we should not reject this mail later.
  # 
  accept
    set acl_m9  = /etc/mail/whitelist-hosts
    hosts       = ${if exists {$acl_m9}{$acl_m9}}
    set acl_m0  = accept
    set acl_m1  = 


  # Accept the mail if the sending host is matched in the ".forwarders" 
  # file in the recipient's home directory.  Temporarily set $acl_m9 to
  # point to this file.  If the host is found, set a flag in $acl_m0 and
  # clear $acl_m1 to indicate that we should not reject this mail later.
  #
  accept
    domains     = +local_domains
    set acl_m9  = /home/${extract{1}{=}{${lc:$local_part}}}/.forwarders
    hosts       = ${if exists {$acl_m9}{$acl_m9}} 
    set acl_m0  = accept
    set acl_m1  = 

In various statements in the acl_data ACL, we check the contents of $acl_m0 to avoid rejecting the mail if this is set as per above. For instance, to avoid rejecting mail from whitelisted hosts due to a missing RFC2822 header:

  deny
    message     = Your message does not conform to RFC2822 standard
    log_message = missing header lines
    !hosts      = +relay_from_hosts
    !senders    = : postmaster@*
    condition   = ${if !eq {$acl_m0}{accept}{true}}
    condition   = ${if or {{!def:h_Message-ID:}\
                           {!def:h_Date:}\
                           {!def:h_Subject:}} {true}{false}}

The appropriate checks are embedded in the Final ACLs, next.