This post describes how to properly defines postfix server properties to prevent your emails from being falsely flagged as spams or even rejected (especially by Google). It lists the different policies and tools that have to be checked to ensure a maximum probability to pass all filters. This post is dedicated to my old buddy Stéphanie, whose email (gmail) address often rejected (maybe not wrongly) my emails.
As a use case example, we will consider that the user (me) wants to send email from the addresses tuxette@mydomain.org and samantha@myotherdomain.wf via the mail server with name mail.mydomain.org. I own the two domain names mydomain.org and myotherdomain.wf. mail.mydomain.org has for IP XX.YYY.ZZZ.WW which reverses to the server name chix.mydomain.org. In addition, my server only sends email via IPV4 (option inet_protocols = ipv4 in the file /etc/postfix/main.cf to avoid painful headaches in configuring properly DNS and PTR for IPV6).

MX, PTR and reverse

All these records must be set properly (in my case, they are managed through the OVH user interface because my domain names are rented by OVH:

  • MX records for myotherdomain.wf and mydomain.org points to mail.mydomain.org which means that all emails sent to @myotherdomain.wf and @mydomain.org are directed to the mail server mail.mydomain.org. This rule writes</p>
    IN MX 1 mail.mydomain.org.
    		
  • DNS and PTR records must also be properly set: the DNS record associates the IP XX.YYY.ZZZ.WW to the mail servermail.mydomain.org. This rule is restricted to the domain name mydomain.org and writes</p>
    mail IN A XX.YYY.ZZZ.WW
    		

    Also, a PTR has to be set for the IP address XX.YYY.ZZZ.WW. This PTR record associates a domain name to the IP, in my case chix.mydomain.org (hence, PRT does not necessarily points to the FQDN of the mail server but chix.mydomain.org must have a PTR record which matches the IP XX.YYY.ZZZ.WW). </li> </ul>

    All these records (as well as IP blacklisting) can be checked at this link. In particular:

    • MX Lookup should return mydomain.org when queried on mydomain.org or myotherdomain.wf;
    • Blacklisting Check should be OK for XX.YYY.ZZZ.WW;
    • Blacklisting Check should be OK for XX.YYY.ZZZ.WW;
    • DNS Lookup for mail.mydomain.org and chix.mydomain.org should return XX.YYY.ZZZ.WW;
    • Reverse Lookup (PTR) for XX.YYY.ZZZ.WW should return chix.mydomain.org;
    • finally, both mydomain.org or myotherdomain.wf can be checked for “Test Email Server” to find any anomaly in mail server configuration.

    SPF

    A SPF (Sender Policy Framework) record tells which servers/IP … are allowed to send emails for a given domain name. If no SPF is defined and an email is sent to a gmail address, you should see the following record in the headers:

    Received-SPF: neutral (google.com: XX.YYY.ZZZ.WW is neither permitted nor denied
      by best guess record for domain of samantha@myotherdomain.wf) 
      client-ip=XX.YYY.ZZZ.WW;
    

    This framework can be used to tell the receiver’s email server that the email has actually been sent by the expected mail server. In my case, I created a SPF record for both mydomain.org and myotherdomain.wf with the same policy which tells that the IP of mydomain.org and myotherdomain.wf are allowed to send emails as well as the MX of mydomain.org and myotherdomain.wf. Finally, I also explicitely authorized the IP XX.YYY.ZZZ.WW to send emails. This record writes

    600 IN TXT "v=spf1 a mx ip4:XX.YYY.ZZZ.WW ~all"
    

    in which the ~all tells that this is a soft policy (maybe emails can be sent by other servers although it is not expected). OVH interface allows to configure in a very intuitive manner SPF.

    Sending an email to a gmail account, the received header should now look like:

    Received-SPF: pass (google.com: domain of samantha@myotherdomain.wf designates 
      XX.YYY.ZZZ.WW as permitted sender) client-ip=XX.YYY.ZZZ.WW;
    

    More details about SPF at this link (in French). SPF records can be checked at this link.

    DKIM

    DKIM enables a domain name to be associated with an email message and thus to claim for responsibility for an email. DKIM is powered by asymmetric cryptography: a key is included in every email header which should match your DKIM record (TXT field corresponding to your domain name) in order to pass the DKIM filter. I installed it using the tutorial available at this link. First, opendkim tools have to be installed:

    sudo apt-get install opendkim opendkim-tools
    

    which configuration file /etc/opendkim.conf is edited to add

    AutoRestart             Yes
    AutoRestartRate         10/1h
    UMask                   002
    Syslog                  yes
    SyslogSuccess           Yes
    LogWhy                  Yes
    
    Canonicalization        relaxed/simple
    
    ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
    InternalHosts           refile:/etc/opendkim/TrustedHosts
    KeyTable                refile:/etc/opendkim/KeyTable
    SigningTable            refile:/etc/opendkim/SigningTable
    
    Mode                    sv
    PidFile                 /var/run/opendkim/opendkim.pid
    SignatureAlgorithm      rsa-sha256
    
    UserID                  opendkim:opendkim
    
    Socket                  inet:12301@localhost
    

    Then, /etc/default/opendkim is editing and the following line is added:

    SOCKET="inet:12301@localhost"
    

    To connect opendkim to postfix, edit the file /etc/postfix/main.cf and add the following two lines:

    milter_protocol = 2
    milter_default_action = accept
    

    Create a file /etc/opendkim/TrustedHosts with

    127.0.0.1
    localhost
    192.168.0.1/24
    
    *.mydomain.org
    *.myotherdomain.wf
    

    and a file /etc/opendkim/KeyTable with

    mail._domainkey.mydomain.org mydomain.org:mail:/etc/opendkim/keys/mydomain.org/mail.private
    mail._domainkey.myotherdomain.wf myotherdomain.wf:mail:/etc/opendkim/keys/myotherdomain.wf/mail.private
    

    and also a file /etc/opendkim/SigningTable
    with

    *@mydomain.org mail._domainkey.mydomain.org
    *@myotherdomain.wf mail._domainkey.myotherdomain.wf
    

    Finally, to generate the keys, create the following directories in /etc/opendkim : keys/mydomain.org keys/myotherdomain.wf and run

    sudo opendkim-genkey -s mail -d mydomain.org
    sudo chown opendkim:opendkim mail.private
    

    inside /etc/opendkim/keys/mydomain.org and

    sudo opendkim-genkey -s mail -d myotherdomain.wf
    sudo chown opendkim:opendkim mail.private
    

    inside /etc/opendkim/keys/myotherdomain.wf.

    A DKIM record is then added to each of the two domain name:

    mail._domainkey IN TXT "v=DKIM1; k=rsa; p=WWWWWWWWWWW"
    

    in which WWWWWWWWWWW has to be replaced by the (long) text key available in the file /etc/opendkim/keys/mydomain.org/mail.txt (and similarly for the record DKIM record for clementine.wf). Then, an email received by gmail includes the following text in the headers:

    Authentication-Results: mx.google.com;
           spf=pass (google.com: domain of samantha@myotherdomain.wf designates 
             XX.YYY.ZZZ.WW as permitted sender) 
             smtp.mailfrom=samantha@myotherdomain.wf;
           dkim=pass header.i=@samantha@myotherdomain.wf;
    

    which tells that both DKIM and SPF filters have been successfully passed. Again, DKIM records can be checked at this link.

    DMARC

    Finally, SPF and DKIM can be monitored using a DMARC record. DMARC, which stands for “Domain-based Message Authentication, Reporting & Conformance”, standardizes how email receivers perform email authentication using the well-known SPF and DKIM mechanisms. This means that senders will experience consistent authentication results for their messages.

    A DMARC rule can be recorded in a TXT field of your domain name (so, in the present use case for mydomain.org and myotherdomain.wf. A basic overview of how DMARC rules are created and work is available at this link. In my case, I created a DMARC record which takes no policy for domain mismatch, subject 10% of the messages to filter (this rule seems to be overridden by google anyway) and relaxed policy for alignment of SPF and DKIM records. Daily reports will be received at tuxette@mydomain.org :

    _dmarc IN TXT "v=DMARC1;p=none;sp=reject;pct=10;adkim=r;aspf=r;fo=1;
      ri=86400;rua=mailto:tuxette@mydomain.org"
    

    The reports can be checked and better understood using the tool available at this link. A proper DMARC record should lead to headers similar to:

    Authentication-Results: mx.google.com;
           spf=pass (google.com: domain of samantha@myotherdomain.wf designates 
             XX.YYY.ZZZ.WW as permitted sender) 
             smtp.mailfrom=samantha@myotherdomain.wf;
           dkim=pass header.i=@samantha@myotherdomain.wf;
           dmarc=pass (p=NONE dis=NONE) header.from=samantha@myotherdomain.wf
    

    DMARC records can be checked at this link.

    </div>