Last updated on March 26th, 2020 at 01:21 pm

In this post I will explain to you how we can send emails from the NGINX server. By default, NGINX does not allow us to send emails from the server.

Prerequisites

Before we start I hope you have complete access to servers with SSH and also have basic knowledge of terminal. You need the Ubuntu server (16 or greater) and one valid domain name. I am also using Cloudflare to add DNS details If you are not using cloud flare don’t worry you can add DNS on your domain account.

In this tutorial, I am using Postfix and other mail utils to send emails from the server. If you are using Apache then you don’t need to do anything to send an email.

Installing and configure Postfix on NGINX

Postfix is a mail server through which we can send and receive an email on our server. In this step, I will guide you on how we can install and configure Postfix on the NGINX server.

Note: Before we start you need to update your Hostname with your domain name you can update your Hostname using Filezilla. Open Filezilla go to /etc/hostname edit file with an editor and change default value with your domain name eg. In my case, I replace the default value with trinitytuts.com. I also update my droplet name but its not mandatory.

Step 1. Open terminal/putty and login to your server.

Step 2. Once logged in you need to run sudo apt update to update software and cache after that you need to run below commands to install Postfix.

sudo DEBIAN_PRIORITY=low apt install postfix

Step 3. Now when you run above command you will prompt to add some details to configure and install postfix.

  • General type of mail configuration?: select Internet Site and click ok
  • System mail name: add your email account eg. [email protected] or you can also leave empty.
  • Root and postmaster mail recipient:  add your default username in eg. root
  • Other destinations to accept mail for: If you want to add another domain you can add here or leave default value and enter.
  • Force synchronous updates on mail queue? Select No and enter.
  • Local networks: No need to change anything we do it later press enter to continue.
  • Mailbox size limit: Keep default value to 0 and continue.
  • Local address extension character: Again no need to change anything continue
  • Internet protocols to use: Select all and continue.

If you want to reconfigure above setting you can run below command

sudo dpkg-reconfigure postfix

Set up SPF and DKIM with Postfix on the Ubuntu server.

Now in this step, I will guide you how we can set up SPF and DKIM record on Ubuntu server so our email reaches to Inbox folder, not in the spam folder. SPF and DKIM are both txt record which you need to enter in your domain DNS setting.

Sender Policy Framework(SPF) is an email authentication method designed to detect forging sender addresses during the delivery of the email Wiki.

DomainKeys Identified Mail(DKIM) is an email authentication method designed to detect forged sender addresses in emails, a technique often used in phishing and email spam Wiki.

Add below SPF record in your DNS setting as shown in the below image.

TXT  @   v=spf1 mx ~all

Install and configure postfix in NGINX

Once you add DNS record to check you can run this command replaces trinitytuts.com with your domain.

dig trinitytuts.com txt

Now we need to install the SPF policy agent to tell the Postfix SMTP server to check for the SPF record of incoming emails. Now we need to configure this follow below steps to configure it correctly.

First, install SPF Agent

sudo apt install postfix-policyd-spf-python

Once installed we need to edit the Postfix master configuration file and add the below code at the end of the file.

sudo nano /etc/postfix/master.cf

Add the below code at the end of the file.

policyd-spf  unix  -       n       n       -       0       spawn
    user=policyd-spf argv=/usr/bin/policyd-spf

Save the file. Now we need to open the Postfix main.cf file and add some code.

sudo nano /etc/postfix/main.cf

Add below code at the end of file

policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
   permit_mynetworks,
   permit_sasl_authenticated,
   reject_unauth_destination,
   check_policy_service unix:private/policyd-spf

Now save the file and restart your Postfix using below command

sudo service postfix restart

Configure DKIM

Now before start configuring we need to install the OpenDKIM tool which free opensource project for the DKIM sender authentication system.

sudo apt install opendkim opendkim-tools

Add postfix user to OpenDKIM

sudo gpasswd -a postfix opendkim

Edit OpenDKIM configuration file and uncomment bellow specific line.

sudo nano /etc/opendkim.conf

Uncomment bellow lines

Canonicalization relaxed/simple
Mode sv
SubDomains no

Than add below code after uncommenting lines

AutoRestart yes
AutoRestartRate 10/1M
Background yes
DNSTimeout 5
SignatureAlgorithm rsa-sha256

Now you also need to add below code at the end of the same file you open

#OpenDKIM user
# Remember to add user postfix to group opendkim
UserID             opendkim

# Map domains in From addresses to keys used to sign messages
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Hosts to ignore when verifying signatures
ExternalIgnoreList  /etc/opendkim/trusted.hosts

# A set of internal hosts whose mail should be signed
InternalHosts       /etc/opendkim/trusted.hosts

Save and close the file.

Generate Public and Private Keys

First, we need to create a directory structure for OpenDKIM

sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys

Change the owner from root to opendkim and make sure only opendkim Users can read and write to the keys directory.

sudo chown -R opendkim:opendkim /etc/opendkim
sudo chmod go-rw /etc/opendkim/keys

Create the signing table.

sudo nano /etc/opendkim/signing.table

Add this line to file and remove trinitytuts.com with your domain

*@trinitytuts.com    default._domainkey.trinitytuts.com

Save and close the file.

Now open key.table file

sudo nano /etc/opendkim/key.table

Add the following line, which tells the location of your private key.

default._domainkey.trinitytuts.com  your-domain.com:default:/etc/opendkim/keys/trinitytuts.com/default.private

Save and close the file. Next, create the trusted host’s file.

sudo nano /etc/opendkim/trusted.hosts

Add the following lines to the newly created file. This tells OpenDKIM that if an email is coming from the localhost or from the same domain, then OpenDKIM should not perform DKIM verification on the email.

127.0.0.1
localhost
YOU_SERVER_IP_ADDRESS
*.trinitytuts.com

Save and close the file.

We need to generate a private key for signing Incoming and Outgoing email. DKIM is used to sign outgoing messages and verify incoming messages. The generated public key will add in your domain DNS.

Create a separate folder for the domain.

sudo mkdir /etc/opendkim/keys/trinitytuts.com

Generate keys using opendkim-genkey tool.

sudo opendkim-genkey -b 2048 -d trinitytuts.com -D /etc/opendkim/keys/trinitytuts.com -s default -v

The above command will create 2048 bits keys.

  •  -d (domain) specifies the domain.
  •  -D (directory) specifies the directory where the keys will be stored.
  • -s (selector)We use default as the selector.

Once the command is executed, the private key will be written to default.private file and the public key will be written to default.txt file.

Make opendkim as the owner of the private key.

sudo chown opendkim:opendkim /etc/opendkim/keys/trinitytuts.com/default.private

Publish Your Public Key in DNS Records

Get a public key from default.txt file using the below command.

sudo cat /etc/opendkim/keys/trinitytuts.com/default.txt

Your public key look like this:-

You need to remove all inverted commas and space after v= and add into your DNS setting of the domain as shown in below image.

Test DKIM Key

Run below command in terminal to verify your DKIM key.

sudo opendkim-testkey -d trinitytuts.com -s default -vvv

If everything is OK, you will see

opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key 'default._domainkey.trinitytuts.com'
opendkim-testkey: key secure
opendkim-testkey: key OK

If you see “Key not secure”, don’t panic. This is because DNSSEC isn’t enabled on your domain name. DNSSEC is a security standard for the secure DNS query. Most domain names haven’t enabled DNSSEC. You can continue to follow this guide.

Connect Postfix to OpenDKIM

Postfix can talk to OpenDKIM via a Unix socket file. The default socket file used by OpenDKIM /var/run/opendkim/opendkim.sock, as shown in /etc/opendkim.conf file. But the postfix SMTP daemon shipped with Ubuntu runs in a chroot jail, which means the SMTP daemon resolves all filenames relative to the Postfix queue directory (/var/spool/postfix). So we need to change the OpenDKIM Unix socket file.

Create a directory to hold the OpenDKIM socket file and allow only opendkim user and postfix group to access it.

sudo mkdir /var/spool/postfix/opendkim

sudo chown opendkim:postfix /var/spool/postfix/opendkim

Then edit the OpenDKIM main configuration file.

sudo nano /etc/opendkim.conf

Find the following line:

Socket local:/var/run/opendkim/opendkim.sock

Replace it with the following line. (If you can’t find the above line, then add the following line.)

Socket local:/var/spool/postfix/opendkim/opendkim.sock

If you can find the following line in /etc/default/opendkim the file.

SOCKET="local:/var/run/opendkim/opendkim.sock"

or

SOCKET=local:$RUNDIR/opendkim.sock

Change it to

SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"

Save and close the file.

Next, we need to edit the Postfix main configuration file.

sudo nano /etc/postfix/main.cf

Add the following lines at the end of this file, so Postfix will be able to call OpenDKIM via the milter protocol.

# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

Save and close the file. Then restart opendkim and postfix service.

sudo systemctl restart opendkim postfix

Now after that, we need to allow some port to send email run bellow command to open specific ports

sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 465/tcp

If you want to add TLS encryption on your sending mail you edit your postfix main.cf file and add below code in it

smtpd_tls_auth_only = no
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_received_header = yes
smtpd_tls_security_level = encrypt
smtpd_tls_session_cache_timeout = 3600s
smtp_tls_note_starttls_offer = yes 
smtp_tls_security_level = may
tls_random_source = dev:/dev/urandom

after adding this code my configure file look like this:-

# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
# fresh installs.
compatibility_level = 2

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = trinitytuts.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = 
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
smtpd_tls_auth_only = no
smtpd_tls_loglevel = 1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_received_header = yes
smtpd_tls_security_level = encrypt
smtpd_tls_session_cache_timeout = 3600s
smtp_tls_note_starttls_offer = yes 
smtp_tls_security_level = may
tls_random_source = dev:/dev/urandom
policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service unix:private/policyd-spf
# Milter configuration
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

Now you need to send email to check if email is send or not I am using mailutils to send email you can install it using bellow command

apt install mailutils

To send email to run this command

echo "body of your email" | mail -s "This is a Subject" -a "From: [email protected]" [email protected]

I am using mail-tester.com to test send email scores which helps me to identify that my email reaches in the inbox folder or in a spam folder.

You also need to add PTR record in your DNS as shown in below image

And also create MX record as shown in the below image

Send Email from NGINX server

that’s It. Now you can test that email is sent from your NGINX server.

You also like to read:- Redirect www site traffic to non-www website in NGINX.