Self host SMTP Server with haraka Feb 5th 2018 Words: 1.4k
This post is created 4 years ago, the content may be outdated.

DNS Configuration

Assume that the domain name is “”, with the mail server on “”, and an e-mail account for ““ is expected to work.

A/MX Record

MX record is for receiving mail, so this is not a solid requirement for an out-bounding server, set up only in case of some spam-filters check this.
A MX Record of domain name “” should be set pointing to “”. Multiple MX records with different priorities can be set for fail-over. An A record of “” is also required with the IP of the inbound mail server. After configuring this all mails send to ““ will be handled by the pointed mail server.


The Sender Policy Framework (SPF) is an open standard specifying a technical method to prevent sender address forgery. More precisely, the current version of SPF — called SPFv1 or SPF Classic — protects the envelope sender address, which is used for the delivery of messages. SPFv1 allows the owner of a domain to specify their mail sending policy, e.g. which mail servers they use to send mail from their domain. The technology requires two sides to play together: (1) the domain owner publishes this information in an SPF record in the domain’s DNS zone, and when someone else’s mail server receives a message claiming to come from that domain, then (2) the receiving server can check whether the message complies with the domain’s stated policy. If, e.g., the message comes from an unknown server, it can be considered a fake.

Add this string as TXT record of domain “”

v=spf1 a mx -all

This allows all IPs of’s A record and MX record to send emails, and consider all mails send from the other IPs fake.

You can also specific the mail server IP manually by following adding this string.

v=spf1 ip4:314.159.265.354 -all

For detailed SPF syntax please consult Official document.


DKIM attaches a new domain name identifier to a message and uses cryptographic techniques to validate authorization for its presence. The identifier is independent of any other identifier in the message, such in the author’s From: field.

The DKIM uses RSA key to sign the mail, to generate the key pair, openssl is recommended.

openssl genrsa -out DKIM-private.pem 2048

For better compatibility, please convert your private key from traditional format to PKCS#8 form as the following command shows.

openssl pkcs8 -topk8 -inform pem -outform pem -in DKIM-private -out DKIM-private-pkcs8 -nocrypt

Then extract the RSA public key from the private key.

openssl rsa -in DKIM-private-pkcs8 -pbout -outform pem -out DKIM-public

Deploy the DKIM public key to the DNS, TXT record of domain “”. Note that the “default” sub-domain is called the domain selector in DKIM, it can be replaced by any string as long as it is chosen correctly the signing process.

v=DKIM1; p=MIGftE2...Your RSA Public Key...iIb3DQEBA

It is recommend to have this in one TXT record. However if the DNS provider has a limit of text length for each TXT record, you can split it in two or more TXT records in syntax “(“First part” “Second Part”)”
First record:

("v=DKIM1; p=MIGftE2RHN...Your RSA..."

Second record:

"...Public Key...JuyiIb3DQEBA")

For more information, please see DKIM specifications.


DMARC, which stands for “Domain-based Message Authentication, Reporting & Conformance”, is an email authentication, policy, and reporting protocol. It builds on the widely deployed SPF and DKIM protocols, adding linkage to the author (“From:”) domain name, published policies for recipient handling of authentication failures, and reporting from receivers to senders, to improve and monitor protection of the domain from fraudulent email.

Add DNS TXT record of domain “”

v=DMARC1;p=reject;[email protected]
  • p: action when forgery is detected. can be “none” “quarantine” “reject”
  • rua: Email reporting URI for forensic reports
  • ruf: Email reporting URI of aggregate reports

For an official document of DMARC Click here.


In computer networks, a reverse DNS lookup or reverse DNS resolution (rDNS) is the querying of the Domain Name System (DNS) to determine the domain name associated with an IP address – the reverse of the usual “forward” DNS lookup of an IP address from a domain name. The process of reverse resolving an IP address uses PTR records. The reverse DNS database of the Internet is rooted in the arpa top-level domain.

The receiver or spam-filter will try to check the rDNS hostname of the sender’s IP to see whether it is same as the sender claims. The default rDNS is often set to something like “”, which is not correspond to the domain. You should change the rDNS to “”. The rDNS configuration different according to your host provider. Please contact them for support. Note that the configuration may take several hours to valid.

haraka Configuration

Haraka is a highly scalable node.js email server with a modular plugin architecture. Haraka can serve thousands of concurrent connections and deliver thousands of messages per second. Haraka and plugins are written in asynchronous JS and are very fast.

node.js and npm are dependencies of haraka and should be install first.
Install haraka:

npm install -g Haraka

Make configuration directory:

sudo haraka -i /etc/haraka

Run haraka for test:

sudo haraka -c /etc/haraka

The haraka may leave orphan process after shutdown and block the port, you can kill it manually:

pkill "node"

Configuring haraka as SMTP server

In “config/smtp.ini”
Change the listening port to [::0]:25,[::0]:465,[::0]:587
haraka should then listen on these three ports on both IPv4 and IPv6. haraka will automatically assign the port 25 to handle insecure connection, port 465 for TLS and port 587 for STARTTLS. Opening listening port below 1024 requires root privilege.

To enable TLS and authentication, configure the config/plugins file

echo "tls
auth/flat_file" > config/plugins

Edit the “config/auth_flat_file.ini” and add the SMTP users.
The “methods” specify the allowed login method.
Users filed syntax is username=password
An example as:

[email protected]

In default condition the TLS cert and key file is “config/tls_cert.pem” and “config/tls_key.pem”
This can be override by “config/tls.ini”


For more information about TLS plugin configuration see this document.

If you want to use the certificate which is issued by CA instead of self signed, you will need to concatenate the cert with the cert chain and the CA in order.

cat /path/to/your_cert.pem /path/to/cert_chain.pem /path/to/ssl/CA.cert > config/tls_cert.pem

You can test the TLS settings using openssl:

openssl s_client -connect localhost:587 -starttls smtp

Please note, in the actual situation, concatenating CA certificate might cause the TLS broken(no certificate provided by host). In such case, using the full chain instead may be help.

cat /etc/letsencrypt/live/ > config/tls_cert.pem

In case you want to debug, change the debug level by adding log level text to file “config/loglevel”
The valid log levels are:

  • DATA
  • INFO
  • WARN
  • CRIT

Mail Content Precautions

SPF, DKIM, DMARC and rDNS must be at No.1 priority.
In pursuit of higher mail delivery rate, here is a list of dos and don’ts.

  • Long string or long words should be avoid
  • There should be a text part of each HTML mail, and the content of text part should be as similar as the HTML’s.
  • Each image tag contains an attribute. If not necessary, using empty: alt=""
  • Do not include contents which often considered dangerous, such as JavaScript, iFrames, embedded content or applet.
  • Do not using short URL services.
  • The mail should contain a List-Unsubscribe header.
  • The mail should not contain any broken link.
  • Avoid reference resources of other domains