How To Get PHP mail() Working On Ubuntu 22.04, 20.04, 18.04 & 16.04

Last updated on | 31 replies

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.

Introduction

If you’re running your own webserver and expect it to send email via PHP mail() without issue, you are going to have a bad time.

Since I wrote this article in 2017, email providers have become very strict on who they will receive email from. Back in 2017, the massive email services such as Gmail and Office 365 would reluctantly accept emails from cloud instances such as DigitalOcean.

I have observed over the past years a tightening of spam filters, preventing PHP mail() emails from ever reaching their recipients, despite checking all the boxes my end.

So, while this guide will indeed enable your server to send emails out into the ether, the problem now is whether the receiving mail servers will accept or reject them.

Personally, I now relay all emails through a mail provider, be it Mailgun, Sendgrid, or Gmail. You can configure Postfix to send email through an SMTP provider of your choice, which is now my recommendation to guarantee mail delivery.

Please see Step 5 below if your test PHP mail()s are not being delivered to your recipient.

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

If you see the information screen below, 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:

/etc/postfix/main.cf
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.

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.

UPDATE Feb 2020: If you are sending to Gmail, Outlook or other large email providers, you may get a bounce error. Please see Step 5 below for possible solutions.

4. Test PHP mail()

If Postfix is working correctly, you should now be able to send mail via PHP mail().

<?php
$to      = '[email protected]';
$subject = 'the subject';
$message = 'hello';
$headers = 'From: [email protected]' . "\r\n" .
    'Reply-To: [email protected]' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);
?>

5. Mail Never Received / Spam Issues

If emails are being rejected by the remote mail provider (such as Gmail or Office 365), 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. Please see:

You may never be able to guarantee delivery of mail via Postfix if you do not route mail through a trusted, external SMTP server. Having had many issues myself over the years sending PHP mail()s from my own cloud server, my recommendation now is to relay mail from Postfix to an external SMTP provider in order to guarantee delivery.

Let me know if this helped. Follow me on Twitter, Facebook and YouTube, or 🍊 buy me a smoothie.

31 replies

Leave a reply

Your email address will not be published. Required fields are marked *

  1. Postfix installed successfully. But mail not sent to any recipient. Every try it returns with

    “Mar 2 14:49:32 ip-172-26-0-195 postfix/smtp[1160171]: 2EE3140328: to=, relay=none, delay=30, delays=0.02/0.01/30/0, dsn=4.4.1, status=deferred (connect to mail.moiboo.com[43.255.154.47]:25: Connection timed out)”

    “Mar 2 14:51:34 ip-172-26-0-195 postfix/smtp[1160172]: E41D14031F: to=, relay=none, delay=627, delays=477/0.01/150/0, dsn=4.4.1, status=deferred (connect to alt2.gmail-smtp-in.l.google.com[2a00:1450:4013:c16::1a]:25: Connection timed out)”

    I don’t know how to proceed next. can you please help me in this

  2. this solution partially worked

    the website said mail was successfully sent
    But I got a message bounce back on the email
    said: 550 5.7.1
    Authentication Required (in reply to end of DATA command)
    as I have to authenticate with username / password
    before sending emails

    how do I authenticate
    ubuntu 20.04
    php 7.4

  3. Hi,
    Excellent tutorial and thank you very much.

    I’m hoping you can help with www-data@ when I send with Postfix. This is how it appears now: www-data
    I would simply like my email address to show here.

  4. Hey, So I’m seeing some good reviews on this and I would like to try it out. I just have one question (if I may): Why is ‘inet_interfaces’ set to ‘loopback-only’?

    1. It’s for security. We configure Postfix to send and receive emails only from the server on which it is running on—that is, from localhost.

      For that to happen, Postfix needs to be configured to listen only on the loopback interface, the virtual network interface that the server uses to communicate internally.

  5. THANK YOU SO MUCH!!!! YOU ARE A GOD SENT PERSON!! i was totally going crazy already its been a week ive been trying to figure this out BUT I just saw this blog post today and omg!!! Thank you!!! You are a life saver! 🙂 But there is one problem, like its not a verified email like google says: “Be careful with this message
    Gmail could not verify that it actually came from [email protected]. Avoid clicking links, downloading attachments, or replying with personal information.” If you can help me on how to fix this? Anyways 1000000 times Thank you!!!!!!!!!!!!!!!!

  6. postfix/smtp[21099]: connect to mx01.mail.icloud.com[17.57.154.6]:25: Connection timed out im seeing this in AWS

  7. Ubuntu 16.04 in July 2020:
    ignores -y in “sudo apt install -y mailutils” (man apt lacks mention of -y)
    the postfix configuration screen fails to appear.
    main.cf does not exist in /etc/postfix (instead it’s main.cf.proto)
    Same findings after sudo apt-get install mailutils”

    1. Thanks Tom. I’ll need to test this on 16.04 again when I get the chance.

      What happens if you run sudo apt install postfix

  8. Hi got this message:
    host ASPMX.L.GOOGLE.COM[2a00:1450:400c:c09::1a] said: 550-5.7.1 [2a00:6d40:72:6d28::1] Our system has detected that this message does 550-5.7.1 not meet IPv6 sending guidelines regarding PTR records and 550-5.7.1 authentication. Please review 550-5.7.1 https://support.google.com/mail/?p=IPv6AuthError for more information 550 5.7.1 . o7si15131076wrm.214 – gsmtp (in reply to end of DATA command))

    Any idea how to solve this?

  9. This worked for me to get my WordPress site to send contact form messages to our e-mail address! Thanks so much for the help!

  10. Hey. When are you going to post article for ” How to get PHP mail() working on Ubuntu “18.04”

  11. Thank you for this guide. However, I cannot send to Gmail from my DigitalOcean droplet.

    This is the mail system at host example.com.

    I’m sorry to have to inform you that your message could not
    be delivered to one or more recipients. It’s attached below.

    For further assistance, please send mail to postmaster.

    If you do so, please include this problem report. You can
    delete your own text from the attached returned message.

    The mail system

    : host gmail-smtp-in.l.google.com[108.177.119.26] said:
    550-5.7.1 [128.199.51.22 1] Our system has detected an unusual rate
    of 550-5.7.1 unsolicited mail originating from your IP address. To protect
    our 550-5.7.1 users from spam, mail sent from your IP address has been
    blocked. 550-5.7.1 Please visit 550-5.7.1
    https://support.google.com/mail/?p=UnsolicitedIPError to review our 550
    5.7.1 Bulk Email Senders Guidelines. x4si1208017edl.361 – gsmtp (in reply
    to end of DATA command)

    1. You’ll need to consult your domain host about setting up Domain Keys and SPF records.

      Domain Keys is an e-mail authentication system that allows for incoming mail to be checked against the server it was sent from to verify that the mail has not been modified. This ensures that messages are actually coming from the listed sender and allows abusive messages to be tracked with more ease.

      SPF will specify which machines are authorized to send email from your domain. This means that only mail sent through this server will appear as valid mail from your domain when the SPF records are checked.

      You could also route mail through an external SMTP server or route mail through Gmail’s SMTP server, but you’ll be limited on how many emails you can send per day.

    2. 1) postfix configuration did not appear
      so what to do ?
      2) wish to send emails externally

      using ubuntu 17.10 & php7.1