Set Up Postfix Send-Only SMTP Server for Multiple Domains on Ubuntu 20.04, 18.04, 16.04
Kaynak: https://www.linuxbabe.com/mail-server/postfix-send-only-multiple-domains-ubuntu
In this article, I will show you how to set up Postfix as a send-only SMTP server on Ubuntu 20.04, 18.04, 16.04. I will first show you how to do it for a single domain, then you can apply the steps for multiple domains if you need to.
Use Case
You have a website/web application that needs to send transactional emails to users (such as password-reset email). Most likely, there’s no need for users to reply to these emails, or if they reply, the reply emails will be sent to your dedicated mail server. In this case, you can set up a send-only SMTP server on the web server using Postfix, which is a popular SMTP server software.
Prerequisites
In order to send emails from your server, port 25 (outbound) must be open. Many ISPs and hosting companies such as DigitalOcean block port 25 to control spam. I recommend using ScalaHosting, because it doesn’t block port 25 (outbound). Once you have a ScalaHosting server, install Ubuntu on it and follow the instructions below.
Setting up Postfix send-only SMTP server for multiple domains isn’t difficult actually. First, we need to configure it for one domain, then set it up for multiple domains.
Step 1: Install Postfix on Ubuntu
Run the following commands to install Postfix from the default Ubuntu repository.
sudo apt-get update sudo apt-get install postfix -y
You will be asked to choose a mail server configuration type. Press the Tab key, then press Enter.
In the next screen, press Enter to select the default option: Internet Site
.
Next, enter your domain name for the system mail name, i.e. the domain name after @ symbol.
Step 2: Configure Postfix
Setting the Postfix hostname
By default, Postfix SMTP server uses the OS’s hostname to identify itself when communicating with other SMTP server. However, the OS hostname might change, and some SMTP servers will reject your email if your hostname isn’t valid. So it’s a good practice to set the hostname directly in Postfix configuration file with the following command.
sudo postconf -e "myhostname = sendonly.yourdomain.com"
This hostname should have a DNS A record pointing to the IP address of your server.
Setting $mydomain Parameter
The $mydomain
parameter specifies the local internet domain name. The default is to use $myhostname
minus the first component. You can display the current value of $mydomain
with:
postconf mydomain
It should be your apex domain name, like
linuxbabe.com
If it’s not displaying your apex domain name, then set the $mydomain parameter with:
sudo postconf -e "mydomain = yourdomain.com"
Setting $myorigin Parameter
The $myorigin
parameter specifies the default domain
name that is appended to sender and recipient addresses that have no
@domain part. The default is to use the value of in the /etc/mailname
file, as can be seen with:
postconf myorigin
Output:
myorigin = /etc/mailname
Then you can display the value in the /etc/mailname file.
cat /etc/mailname
Its value should be yourdomain.com
without any subdomain.
echo "yourdomain.com" | sudo tee /etc/mailname
Restarting Postfix
Finally, we need to restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Step 3: Set PTR Record
You need to set a PTR record (aka, pointer record), which maps an IP address to an FQDN. It’s the counterpart to the A record. Many SMTP server will reject your email if your server’s IP address doesn’t have PTR record.
Because you get IP address from your hosting provider or ISP, not from your domain registrar, so you must set PTR record for your IP in the control panel of your hosting provider, or ask your ISP. For example, in ScalaHosting, you can set PTR record by opening a support ticket or use the live chat on their website. Although you can set PTR record to any hostname, for best practice, you should use the Postfix hostname in step 2
To see if your PTR record is set properly, run the following command. Replace 12.34.56.78 with your own IP address.
host 12.34.56.78
Note that if your server uses IPv6 address, it’s also a good idea to add AAAA record for your Postfix hostname and set PTR record for your IPv6 address.
Step 4: Install and Configure OpenDKIM
DKIM stands for DomainKeys Identified Mail. You can install OpenDKIM on your server and use it to add signatures to emails sent from your domain, with your private key. Receiving SMTP servers verify the signature by using the corresponding public key, which is published by you in the DNS. Adding DKIM signature is a must if you want your emails get into recipient’s inbox.
First install OpenDKIM from the default Ubuntu repository.
sudo apt-get install opendkim opendkim-tools
Then add postfix
user to opendkim
group.
sudo adduser postfix opendkim
Edit OpenDKIM main configuration file.
sudo nano /etc/opendkim.conf
Find the following lines.
#Canonicalization simple #Mode sv #SubDomains no
Uncomment them and replace simple
with relaxed/simple
. Change the mode from sv
to s
, because there’s no inbound email to verify signature.
Canonicalization relaxed/simple Mode s SubDomains no
Add the following lines at the end of this file. (On Ubuntu 18.04, the UserID is already set to opendkim
)
#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 # A set of internal hosts whose mail should be signed InternalHosts /etc/opendkim/trusted.hosts
Save and close the file.
Create Signing Table, key Table and Trusted Hosts File
Create a directory structure for OpenDKIM.
sudo mkdir /etc/opendkim sudo mkdir /etc/opendkim/keys
Change owner from root
to opendkim
and make sure only opendkim
user 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 the following line to the file. This means that if the From:
header in an email contains example.com
, then use the sendonly
DKIM selector. You can change sendonly
to your preferred DKIM selector name and it should be unique in your DNS.
*@example.com sendonly._domainkey.example.com
Save and close the file. Then create the key table.
sudo nano /etc/opendkim/key.table
Add the following line. This means that for the sendonly DKIM selector, use the private key saved in /etc/opendkim/keys/example.com/sendonly.private
to sign the email.
sendonly._domainkey.example.com example.com:sendonly:/etc/opendkim/keys/example.com/sendonly.private
Save and close the file. Next, create the trusted hosts file.
sudo nano /etc/opendkim/trusted.hosts
Add the following lines to the newly created file.
127.0.0.1
localhost
*.example.com
The above means that messages coming from the above IP addresses and domains will be trusted and signed.
Generate Private/Public Keypair
We need to generate a private key to sign outgoing emails and a public key for receiving SMTP servers to verify the DKIM signature. Public key will be published in DNS.
Create a separate folder for the domain.
sudo mkdir /etc/opendkim/keys/example.com
Generate keys using opendkim-genkey
tool.
sudo opendkim-genkey -b 2048 -d example.com -D /etc/opendkim/keys/example.com -s sendonly -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 and we use sendonly
as the selector (-s)
. Once the command is executed, the private key will be saved in sendonly.private
and sendonly.txt
will be the TXT record that contains public key.
Make opendkim
as the owner of the private key.
sudo chown opendkim:opendkim /etc/opendkim/keys/example.com/sendonly.private
Add Public Key in DNS Records
Display the public key
sudo cat /etc/opendkim/keys/example.com/sendonly.txt
The string after the p
parameter is the public key. In your DNS manager, create a TXT record for the second domain. Enter sendonly._domainkey
in the Name field. Copy everything in the parentheses and paste into
the value field. Delete all double quotes. (You can paste it into a text
editor first, delete all double quotes, the copy it to your DNS
manager. Your DNS manager may require you to delete other invalid
characters, such as carriage return.)
Once the DNS record is published, enter the following command on your Ubuntu server to test your key.
sudo opendkim-testkey -d example.com -s sendonly -vvv
If everything is OK, you will see
key OK
If you see key not secure
message, don’t panic. This is because DNSSEC isn’t enabled on your domain name.
Step 5: Connect Postfix with OpenDKIM
Postfix can talk to OpenDKIM via a Unix socket file. The default socket file used by OpenDKIM is /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 socket file.
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
Create a directory to hold the OpenDKIM socket file and only allow opendkim user and postfix group to access it.
sudo mkdir /var/spool/postfix/opendkim sudo chown opendkim:postfix /var/spool/postfix/opendkim
If you can find the following line in /etc/default/opendkim
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"
After that, we need to edit Postfix main configuration file.
sudo nano /etc/postfix/main.cf
Add the following lines at the end of this file to connect Postfix with OpenDKIM.
# 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. Restart OpenDKIM and Postfix.
sudo systemctl restart opendkim postfix
OpenDKIM won’t produce any message if it fails to restart. Run the following command to check its status. Make sure it’s running.
systemctl status opendkim
Step 6: Create SPF DNS Record
SPF (Sender Policy Framework) record specifies which hosts or IP addresses are allowed to send emails on behalf of a domain. In your DNS management interface, create a new TXT record like below. Use your own IPv4 address and IPv6 address of your server.
TXT @ v=spf1 mx ip4:12.34.56.78 ip6:2600:3c01::f03c:93d8:f2c6:78ad ~all
Step 7: Set the From Address, From Name and Return-Path
You can set custom From address, From name and Return-Path in your
website/web application. Let’s use WordPress as an example. You can add
the following lines in your WordPress theme’s functions.php
file to override the default From address, From name and return-path. Replace the red text as necessary.
// Function to change From email address function wpb_sender_email( $original_email_address ) { return 'notifications@linuxbabe.com'; } // Function to change sender name function wpb_sender_name( $original_email_from ) { return 'LinuxBabe'; } // Set return-path the same as From address function fix_my_email_return_path( $phpmailer ) { $phpmailer->Sender = $phpmailer->From; } // Hooking up our functions to WordPress filters add_filter( 'wp_mail_from', 'wpb_sender_email' ); add_filter( 'wp_mail_from_name', 'wpb_sender_name' ); add_action( 'phpmailer_init', 'fix_my_email_return_path' );
Save the file and you are done. (Be careful about the functions.php file. Do not add an empty line after ?>
at the end of this file, or your WordPress XML sitemap can be corrupted.)
Step 8: Enable TLS Encryption for Outgoing Emails
By default, Postfix doesn’t use TLS encryption when sending outgoing emails. To enable TLS encryption, open the /etc/postfix/main.cf
file and add the following two lines at the end of this file.
smtp_tls_security_level = may smtp_tls_loglevel = 1
The first line enables TLS encryption for the Postfix SMTP client. The second line will log the TLS connection in /var/log/mail.log
file, so you can check if TLS encryption is working. Save and close the file. Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Since Postfix doesn’t receive incoming emails, there’s no need to configure a valid TLS certificate for the Postfix SMTP daemon.
Some SMTP servers require you to use TLS. If not, they will reject your emails and you will see the following error message in the mail log.
Must issue a STARTTLS command first
Step 9: Testing Sender Score
Now go to https://www.mail-tester.com. You will see a unique email address. Send an email from your website on the Postfix SMTP server to this address and then check your score. As you can see, I got a perfect score. In the test result, you should check if your PTR record, SPF and DKIM record is valid.
You can also open the /var/log/mail.log
file to check if TLS encryption is used. For example, the following line shows the connection to mail-tester.com is encrypted.
Anonymous TLS connection established to mail-tester.com[94.23.206.89]:25: TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)
What if Your Emails Are Still Being Marked as Spam?
I have more tips on email deliverability for you in this article: How to stop your emails being marked as spam. Although it will take some time and effort, your emails will eventually be placed in the inbox after applying these tips.
How to Configure Postfix Send-only SMTP Server For Multiple Domains
By default, Postfix allows you to use any domain name in the From header and return path address to send outgoing emails. If your server hosts multiple websites, you just need to create SPF DNS record for your other domains, which is very easy to do, and configure OpenDKIM for your other domains.
To configure OpenDKIM for other domains, you need to add the other domains in the signing table, key table and trusted hosts file like below.
Signing table (/etc/opendkim/signing.table
)
*@example.com sendonly._domainkey.example.com *@example.net sendonly._domainkey.example.net
Key table (/etc/opendkim/key.table
)
sendonly._domainkey.example.com example.com:sendonly:/etc/opendkim/keys/example.com/sendonly.private sendonly._domainkey.example.net example.net:sendonly:/etc/opendkim/keys/example.net/sendonly.private
Trusted hosts (/etc/opendkim/trusted.hosts
)
127.0.0.1 localhost *.example.com *.example.net
Then generate the DKIM Private/Public keypair by following the same steps as mentioned above for other domains and add the DKIM public key in DNS. Restart OpenDKIM and you are done. Don’t forget to test your sender score.
Sending Emails From Another Server
There are two ways to allow other servers to send emails through your send-only Postfix SMTP server.
- Use port 25 without SMTP authentication: This method requires the other server doesn’t block port 25 (outbound).
- Use port 587 with SMTP authentication: If the other server blocks port 25 (outbound), you can use port 587.
Port 25 without SMTP Authentication
Run the following command to make Postfix listen on 0.0.0.0
, so other servers can connect to the send-only Postfix SMTP server.
sudo postconf "inet_interfaces = all"
Then you need to add the IP address of the other server to the Postfix mynetworks
parameter. Replace 12.34.56.78 with the real IP address.
sudo postconf "$(postconf mynetworks) 12.34.56.78"
Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Run the following commands to open port 25 (inbound) for the other server.
sudo ufw insert 1 allow in from 12.34.56.78 to any port 25 proto tcp
Now you can configure SMTP clients to use mta1.yourdomain.com
and port 25 to send emails. You don’t need to specify username/password in the SMTP client.
Port 587 with SMTP Authentication
Open port 587 and 80 in firewall.
sudo ufw insert 1 allow in from 12.34.56.78 to any port 25 proto tcp
sudo ufw allow 80/tcp
Run the following command to make Postfix listen on 0.0.0.0
, so other servers can connect to the send-only Postfix SMTP server.
sudo postconf "inet_interfaces = all"
Then you need to enable the submission service of Postfix so that the
email client can submit emails to Postfix SMTP server. Edit the master.cf
file.
sudo nano /etc/postfix/master.cf
In submission
section, uncomment or add the following lines. Please allow at least one whitespace (tab or spacebar) before -o
.
In postfix configurations, a preceding whitespace character means that
this line is continuation of the previous line. (By default the submission
section is commented out. You can copy the following lines and paste
them into the file, so you don’t have to manually uncomment or add new
text.)
submission inet n - y - - smtpd -o syslog_name=postfix/submission -o smtpd_tls_security_level=encrypt -o smtpd_tls_wrappermode=no -o smtpd_sasl_auth_enable=yes -o smtpd_relay_restrictions=permit_sasl_authenticated,reject -o smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject -o smtpd_sasl_type=dovecot -o smtpd_sasl_path=private/auth
The above configuration enables the submission daemon of Postfix and requires TLS encryption. Plain text authentication will be rejected. The submission daemon listens on TCP port 587. STARTTLS is used to encrypt communications between SMTP client and the submission daemon.
Save and close the file. To enable SMTP authentication, we need to install Dovecot.
sudo apt install dovecot-core
Edit the authentication config file.
sudo nano /etc/dovecot/conf.d/10-auth.conf
Uncomment the following line.
disable_plaintext_auth = yes
It will disable plaintext authentication when there’s no SSL/TLS encryption. And if you want to use full email address (username@your-domain.com) to login, add the following line in the file.
auth_username_format = %Ln
Otherwise, you are able to login with username only (without @your-domain.com). Next, find the following line.
auth_mechanisms = plain
This line only enables the PLAIN authentication mechanism. LOGIN is another authentication mechanism you probably want to add to support older email clients.
auth_mechanisms = plain login
Save and close the file. Then edit the following file.
sudo nano /etc/dovecot/conf.d/10-master.conf
Change service auth
section to the following so that Postfix can find the Dovecot authentication server.
service auth { unix_listener /var/spool/postfix/private/auth { mode = 0660 user = postfix group = postfix } }
Save and close the file. Restart Dovecot for the changes to take effect.
sudo systemctl restart dovecot
Next, we need to obtain a valid TLS certificate. We can easily obtain a free TLS certificate from Let’s Encrypt. Issue the following commands to install Let’s Encrypt client (certbot) on Ubuntu.
sudo apt install certbot
Then use the standalone plugin to obtain TLS certificate (assuming there’s no web server running on the Postfix SMTP server).
sudo certbot certonly --standalone --agree-tos --email you@example.com -d sendonly.yourdomain.com
After a while, you should see the following lines which means the certificate is successfully obtained. You can also see the directory under which your cert is stored.
Next, we need to run the following two commands to specify the
location of TLS certificate and private key in Postfix configuration
file. Your Let’s Encrypt certificate and private key are stored under /etc/letsencrypt/live/sendonly.your-domain.com/
directory.
sudo postconf "smtpd_tls_cert_file = /etc/letsencrypt/live/sendonly.your-domain.com/fullchain.pem" sudo postconf "smtpd_tls_key_file = /etc/letsencrypt/live/sendonly.your-domain.com/privkey.pem"
Restart Postfix for the changes to take effect.
sudo systemctl restart postfix
Now you can configure SMTP clients to use sendonly.yourdomain.com and port 587 to send emails. Use TLS
encryption type and plain
as authentication mode. You need to create email account on the SMTP server. That’s very simple. Use the adduser
command to add a user.
sudo adduser user1 --no-create-home
Then set a password for this user.
sudo passwd user1
The email address will be user1@yourdomain.com
.
Troubleshooting
Email not Signed by DKIM
If your message is not signed and DKIM check failed, you may want to check postfix log (/var/log/mail.log
) to see what’s wrong in your configuration. If you see the following message in the mail log,
warning: connect to Milter service local:opendkim/opendkim.sock: No such file or directory
you may want to check if the opendkim
systemd service is actually running.
systemctl status opendkim
If opendkim is running and you still see the above error, you might need to change smtpd_milters = local:opendkim/opendkim.sock
to smtpd_milters = local:/opendkim/opendkim.sock
in /etc/postfix/main.cf file.
Must Issue a STARTTLS Command First
If you see the following error in the mail log (/var/log/mail.log
), it’s probably because the TLS certificate is not specified correctly in /etc/postfix/main.cf
file.
Must issue a STARTTLS command first (in reply to MAIL FROM command))
fatal: no SASL authentication mechanisms
If you see the following error in the mail log (/var/log/mail.log
), it’s probably because you forgot to restart dovecot (sudo systemctl restart dovecot
).
warning: SASL: Connect to private/auth failed: No such file or directory fatal: no SASL authentication mechanisms
Also, check if Dovecot is running.
sudo systemctl status dovecot
Sending Bulk or Mass Emails
Can you use this SMTP server to send bulk or mass emails?
Yes, but you should send bulk email to legitimate subscribers only, that is to say, the recipients should have signed up for your mailing list. You should never send spam (unsolicited bulk email), or you SMTP server will surely be blacklisted. Before sending bulk email, I highly recommended following the advice in this article: How to Stop Your Emails Being Marked as Spam.
Disable Receiving Email in Postfix
By default, Postfix SMTP server listens on all active interfaces on the machine. Since the Postfix SMTP server is only used for sending transactional emails to users, you can block inbound connection to TCP port 25, so bad actors can’t send spam to it. Since we added the a whitelist for port 25, legitimate users won’t be affected.
Removing Sensitive Information from Email Headers
By default, Postfix SMTP server will add a Received:
email header, recording the IP address of the client, which can leak the
IP address of your website (If it’s behind CDN). You can tell Postfix
to ignore it. Create a header check file.
sudo nano /etc/postfix/smtp_header_checks
Put the following lines into the file.
/^Received:/ IGNORE
Save and close the file. Then edit the Postfix main configuration file.
sudo nano /etc/postfix/main.cf
Add the following line at the end of the file.
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
Save and close the file. Then run the following command to rebuild hash table.
sudo postmap /etc/postfix/smtp_header_checks
Reload Postfix for the change to take effect.
sudo systemctl reload postfix
Now Postfix won’t include that sensitive information in email headers.
Auto-Renew TLS Certificate
You can create Cron job to automatically renew TLS certificate. Simply open root user’s crontab file.
sudo crontab -e
Then add the following line.
@daily certbot renew --quiet
Save and close the file.
Conclusion
I hope this tutorial helped you set up a Postfix send-only SMTP server on Ubuntu for multiple domains. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂