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
email@example.com via the mail server with name
mail.mydomain.org. I own the two domain names
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
mail.mydomain.orgwhich means that all emails sent to
@mydomain.orgare directed to the mail server
mail.mydomain.org. This rule writes
IN MX 1 mail.mydomain.org.
DNS and PTR records must also be properly set: the DNS record associates the IP
XX.YYY.ZZZ.WWto the mail server
mail.mydomain.org. This rule is restricted to the domain name
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.orgmust have a PTR record which matches the IP
All these records (as well as IP blacklisting) can be checked at this link. In particular:
MX Lookup should return
mydomain.orgwhen queried on
Blacklisting Check should be OK for
Blacklisting Check should be OK for
DNS Lookup for
Reverse Lookup (PTR) for
myotherdomain.wfcan be checked for “Test Email Server” to find any anomaly in mail server configuration.
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 firstname.lastname@example.org) 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
myotherdomain.wf with the same policy which tells that the IP of
myotherdomain.wf are allowed to send emails as well as the MX of
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 email@example.com designates XX.YYY.ZZZ.WW as permitted sender) client-ip=XX.YYY.ZZZ.WW;
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
/etc/default/opendkim is editing and the following line is added:
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
127.0.0.1 localhost 192.168.0.1/24 *.mydomain.org *.myotherdomain.wf
and a file
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
*@mydomain.org mail._domainkey.mydomain.org *@myotherdomain.wf mail._domainkey.myotherdomain.wf
Finally, to generate the keys, create the following directories in
keys/myotherdomain.wf and run
sudo opendkim-genkey -s mail -d mydomain.org sudo chown opendkim:opendkim mail.private
sudo opendkim-genkey -s mail -d myotherdomain.wf sudo chown opendkim:opendkim mail.private
A DKIM record is then added to each of the two domain name:
mail._domainkey IN TXT "v=DKIM1; k=rsa; p=WWWWWWWWWWW"
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 firstname.lastname@example.org designates XX.YYY.ZZZ.WW as permitted sender) email@example.com; dkim=pass header.i=@firstname.lastname@example.org;
which tells that both DKIM and SPF filters have been successfully passed. Again, DKIM records can be checked at this link.
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
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
_dmarc IN TXT "v=DMARC1;p=none;sp=reject;pct=10;adkim=r;aspf=r;fo=1; ri=86400;rua=mailto:email@example.com"
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 firstname.lastname@example.org designates XX.YYY.ZZZ.WW as permitted sender) email@example.com; dkim=pass header.i=@firstname.lastname@example.org; dmarc=pass (p=NONE dis=NONE) email@example.com
DMARC records can be checked at this link.