In this article we are going to install and configure Postfix to allow our applications to use the PHP mail() function. Tested and working on Ubuntu 20.04, 18.04 & 16.04.
1. Install Postfix
Let’s update the package database first.
sudo apt-get update
Install mailutils, which will automatically install Postfix.
sudo apt install -y mailutils
On the first Postfix configuration screen, select OK by pressing TAB and ENTER
Select Internet Site and press ENTER.
System mail name should be your domain name eg. example.com, press ENTER.
Package should now be installed.
2. Configure Postfix
For security reasons, you should instruct Postfix only to process requests to send emails from the server on which it is running.
Edit the Postfix configuration file.
sudo nano /etc/postfix/main.cf
Towards the bottom of the file, find the line inet_interfaces = all. (Press CTRL + W to search) Change it to:
inet_interfaces = loopback-only
Save file and exit. (Press CTRL + X, press Y and then press ENTER)
Lastly, let’s restart Postfix.
sudo systemctl restart postfix
If you intend on sending email to your own domain, Postfix requires some additional configuration. For example, I want my PHP app to send emails to [email protected]. This will fail if you don’t make some additional changes to your main.cf file.
Can’t send mail to own domain. Postfix: status=bounced (unknown user: “user”)
Having problems sending email to your own domain? You may need to change your postfix configuration.
I was experiencing a problem sending mail to an address at my own domain. I wanted my PHP app to send notification emails to [email protected] but they kept bouncing with “status=bounced (unknown user: “user”)”.
Accessing the log:
sudo tail /var/log/mail.log -n 200
This will return the last 200 lines of the log.
Log output:
May 24 12:28:04 example postfix/pickup[30776]: DC48FC0927: uid=33 from= May 24 12:28:04 example postfix/cleanup[32746]: DC48FC0927: message-id=<[email protected]> May 24 12:28:04 example postfix/qmgr[1711]: DC48FC0927: from=<[email protected]>, size=9136, nrcpt=1 (queue active) May 24 12:28:04 example postfix/local[32748]: DC48FC0927: to=<[email protected]>, relay=local, delay=0.06, delays=0.03/0.01/0/0.01, dsn=5.1.1, status=bounced (unknown user: "user") May 24 12:28:04 example postfix/cleanup[32746]: E7413C0928: message-id=<[email protected]> May 24 12:28:04 example postfix/qmgr[1711]: E7413C0928: from=<>, size=10993, nrcpt=1 (queue active) May 24 12:28:04 example postfix/bounce[32749]: DC48FC0927: sender non-delivery notification: E7413C0928 May 24 12:28:04 example postfix/qmgr[1711]: DC48FC0927: removed May 24 12:28:04 example postfix/local[32748]: E7413C0928: to=<[email protected]>, relay=local, delay=0.01, delays=0/0/0/0, dsn=2.0.0, status=sent (delivered to mailbox) May 24 12:28:04 example postfix/qmgr[1711]: E7413C0928: removed May 24 12:28:04 example postfix/pickup[30776]: EBC48C0927: uid=33 from= May 24 12:28:04 example postfix/cleanup[32746]: EBC48C0927: message-id=<[email protected]> May 24 12:28:04 example postfix/qmgr[1711]: EBC48C0927: from=<[email protected]>, size=8898, nrcpt=1 (queue active)
I’m not sure if others have experienced this issue, but if your email server is hosted on another domain and you use postfix and SMTP to send local emails from a PHP web form for example, then you need to setup the following in your postfix configuration.
Open your Postfix config file.
sudo nano /etc/postfix/main.cf
Scroll down and look for the entries for myhostname and mydestination. Change them so they look like this.
. . . smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination myhostname = localhost alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases myorigin = /etc/mailname mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain . . .
This forces postfix to always use the external email server, even in a case the email recipient is under your local domain name, like [email protected].
Lastly, let’s restart Postfix.
sudo systemctl restart postfix
You can send a test email to see if it works.
echo "Test Email message body" | mail -s "Email test subject" [email protected]
3. Test Postfix
We’ll now send a test email message. Make sure to replace [email protected] with your own email address.
echo “Test Email message body” | mail -s “Email test subject” [email protected]
Don’t forget to check your spam folder.
If you still haven’t received any mail after a few minutes, check the mail error log.
sudo tail /var/log/mail.log
If the mail log is empty or doesn’t give enough information, try parsing the syslog. This will return the last 50 entries for postfix.
sudo tail -f -n 50 /var/log/syslog | grep postfix
If the syslog is empty and you still haven’t received any test email, it’s possible that the test email was rejected by the recipient server. You should check to see if anything has bounced back to your mail folder.
sudo less /var/mail/$(whoami)
Press uppercase G to scroll to the bottom of the file and lowercase q to quit. The $(whoami) variable returns the currently logged in user.
4. Test PHP mail()
If Postfix is working correctly, you should now be able to send mail via PHP mail().
Mail Never Received / Spam Issues
If emails are being rejected by the remote mail provider (such as Gmail), or mail is going straight to your email client’s spam folder, you may need to do some additional configuration on your domain (SPF, DKIM, DMARC records) to get past spam filters.