// Tutorial //

How To Use Gmail or Yahoo with PHP mail() Function

Published on August 2, 2013
Default avatar
By Jesin A
Developer and author at DigitalOcean.
How To Use Gmail or Yahoo with PHP mail() Function

What the Red Means

The lines that the user needs to enter or customize will be in red in this tutorial!

The rest should mostly be copy-and-pastable.

About PHP mail()

The PHP mail() function uses the program in sendmail_path configuration directive to send emails. This is set up as sendmail by default.

While most Linux installations have sendmail preinstalled, there is always a hassle of setting up SPF/PTR records, generating DKIM keys and a lot more to ensure that the email sent by your PHP script is not flagged as spam. A SMTP client called MSMTP can be used to send emails using third-party SMTP servers, this can also be used by PHP's mail() in the place of sendmail.

Installation

To install MSMTP on Fedora Linux use yum:

yum install msmtp

CentOS repository doesn't have a RPM package for MSMTP so we need to install it from source:

yum install make gcc pkgconfig
wget http://sourceforge.net/projects/msmtp/files/msmtp/1.4.31/msmtp-1.4.31.tar.bz2/download
tar -xvf msmtp-1.4.31.tar.bz2
cd msmtp-1.4.31
./configure
make
make install

The latest version is 1.4.31 at the time of this writing but it may change in future so to get the latest version, visit this sourceforge page.

On Ubuntu/Debian distribution use apt-get:

apt-get install msmtp

Arch Linux users:

sudo pacman -S msmtp

Configuring MSMTP

The configuration file of MSMTP is stored in ~/.msmtprc for each user and /etc/msmtprc is the system wide configuration file. Open the configuration file in your directory.

vi ~/.msmtprc

Add the following lines for a Yahoo account:

account yahoo
tls on
tls_starttls off
tls_certcheck off
auth on
host smtp.mail.yahoo.com
user user1
from user1@yahoo.com
password yourYahooPa5sw0rd

For Gmail, use the following settings:

account gmail
tls on
tls_certcheck off
auth on
host smtp.gmail.com
port 587
user user1@gmail.com
from user1@gmail.com
password yourgmailPassw0rd

This file can also have more than one account, just ensure that the "account" value is unique for each section. Save the file and use chmod to make this file readable only by the owner since it contains passwords. This step is mandatory because msmtp won't run if the permissions are more than 600.

chmod 600 ~/.msmtprc

Before implementing this in PHP, check from the command-line to ensure it works properly. To do this, create a plain text file containing a simple email:

echo -e "From: alice@example.com \n\
To: bob@domain.com \n\
Subject: Hello World \n\
\n\
This email was sent using MSMTP via Gmail/Yahoo." >> sample_email.txt

Now send this email:

cat sample_email.txt | msmtp --debug -a gmail bob@domain.com

Replace the word "gmail" with "yahoo" or whatever you entered for the "account" option. You'll see a lot of messages because of the "--debug" parameter. This is to make troubleshooting easy if things don't work as expected. If bob@domain.com receives this email, everything is setup correctly so copy this file to the /etc directory:

cp -p ~/.msmtprc /etc/.msmtp_php

Change the ownership to the username under which the web server is running. This can be "apache", "www-data", or "nobody" depending on the Linux distribution on your VPS and web server installed:

chown www-data:www-data /etc/.msmtp_php

Configuring PHP

Open the php.ini file, its location varies according to the OS and PHP type installed (PHP CGI, mod_php, PHP-FPM etc):

vi /etc/php5/php.ini

Find the following line:

sendmail_path =

Modify it by adding the path to the msmtp command:

sendmail_path = "/usr/bin/msmtp -C /etc/.msmtp_php --logfile /var/log/msmtp.log -a gmail -t"

Manually create a log file and change its ownership to the username your web server is running as:

touch /var/log/msmtp.log
chown www-data:www-data /var/log/msmtp.log

Restart your web server to apply the changes:

service httpd restart

In Arch Linux, this is done using the systemctl command:

systemctl restart httpd

Depending on your OS and web server, replace "httpd" with the appropriate name. If PHP is running as a separate process (like PHP-FPM), restart it instead:

service php5-fpm restart

Create a PHP script with a simple mail() to test this setup:

<?php
if(mail("receipient@domain.com","A Subject Here","Hi there,\nThis email was sent using PHP's mail function."))
print "Email successfully sent";
else
print "An error occured";
?>

Access this file from the web browser.

http://www.example.com/file.php

If this email wasn't sent you can check the msmtp log file for errors.

tail /var/log/msmtp.log

Common errors

If the email was not sent when using the PHP script, troubleshoot as follows:

  • Check if you edited the correct php.ini file. This can be confirmed by creating a phpinfo(); file and checking the "Loaded Configuration File" section.
  • The path to the msmtp configuration file might be wrong or the web server doesn't have permission to read this file.
  • Check if an email is sent by running the script using command-line PHP:
    php /var/www/html/file.php

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Jesin A

author

Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
10 Comments

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Ok … managed to nail the problem, droplet is in Singapore 1 with IPv6 enabled. It takes 3-5 minutes with IPv6 and after disabling IPv6 within OS (nothing else changed), it takes 2-4 seconds with IPv4.

I do not know if it is Google or DigitalOcean but I really hope that DigitalOcean will look into and check if there is a IPv6 routing or speed issue.

Thanks for the awesome tutorial! I have found tons of new and useful information here and it worked.

I’m close to getting this working, but can’t get the last step. This line sends the email just fine:

cat sample_email.txt | msmtp --debug -a gmail bob@domain.com

But when I try to execute it from a php file (either in the command line with “php /var/www/file.php” or in the web browser) it doesn’t send at all. Oddly, the command line returns “Email successfully sent” while the web browser says “An error occurred.” It seems like something is wrong with the php config. Any ideas?

Five years later and this article is still helpful. Incase anyone else is still reading and has any issues like with security warning, follow these steps:

  1. Setup HTTPS
  2. Setup UFW with correct ports
  3. Create an secondary email account (name it something like auto.response@gmail.com).
  4. Set PHP mail headers as follows:
  mail ( $to, $subject, $html_email, getMailHeaders() );
  function getMailHeaders() {
    $headers = "From: No-Reply <example@gmail.com>\r\n";
    $headers .= "Return-Path: Name <example@gmail.com>\r\n";
    $headers .= "Bcc: Name <example@gmail.com>\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-type: text/html; charset=iso-8859-1\r\n";
    $headers .= "X-Priority: 3\r\n";
    $headers .= "X-Mailer: PHP". phpversion() ."\r\n";
    return $headers;
  }

Following these steps all emails have no security warning and are not marked as spam.

Hi,

first of all thanks for this and all the other great tutorials!

However, with this one I have one issue I could not solve.

If I do: cat sample_email.txt | msmtp --debug -a gmail bob@domain.com

There is a lot of console output, ending with: reading recipients from the command line

If I wait long enough (approx. 2 minutes) I receive the mail. However, the problem propagates to phps mail function. This means, if a user fills out a contact form he has to wait for approx. 2 minutes until he receives feedback.

(When googling, I usually find that the /etc/hosts file needs to be properly set, however, this is not the issue here).

Any ideas?

Excellent tutorial!!! I followed the steps and worked like a charm. But I want to send emails from different senders from my website. eg. If the user goes to www.mypage.com/A.php I want to send a mail from mailA@gmail.com and If the user goes to www.mypage.com/B.php I want to send a mail from mailB@gmail.com

In /etc/.msmtp_php I defined both accounts

account gmailA
...
user mailA@gmail.com
from mailA@gmail.com
password XXXXX
account gmailB
...
user mailB@gmail.com
from mailB@gmail.com
password XXXXX

In sendpath I defined only gmailA

sendmail_path = "/usr/bin/msmtp -C /etc/.msmtp_php --logfile /var/log/msmtp.log -a gmailA -t"

and all the mails sends with FROM: mailA@gmail.com Which is fine but I want that sometimes the sender is mailB@gmail.com

I use this headers in mail()

 $header.= "From: mailB@gmail.com \r\n" .
    "Reply-To: mailB@gmail.com \r\n";  

but sender keep being mailA@gmail.com

is there any way to define another account in sendmail_path so I can “choose” which one to use??

Dear All,

I am a newbie and using Debian 8 and NGINX for my web server, just followed this tutorial step by step and finally I still unable to send an email. For testing, I run this command;

cat sample_email.txt | msmtp --debug -a gmail wahyu.wardana@yahoo.com

then I got this message:

-bash: /usr/bin/msmtp: Permission denied

What’s the problem, can you help me, please?

Thank you.

I’ve tried this method. It sends an email with this terminal command “cat sample_email.txt | msmtp --debug -a gmail bob@domain.com”, but when I implemented the mail() in php it does not send. Also, it does not send an error.

@jesin

account  gmail
host   smtp.gmail.com
port   587
from   xxxx@gmail.com
user   xxxx@gmail.com
password  xxxxxx
auth   on
tls   on
tls_trust_file /etc/ssl/certs/ca-certificates.crt

# Default account to use
account default : gmail

When tested echo Test mail | msmtp --debug -a gmail xxxx@gmail.com, mail was sent successfully.

However, I’m struggling to make my contact form script works.

<?php
if($_POST)
{
    $to_Email       = "xxxx@gmail.com";
    $subject        = 'Ah!! You got Mail...';

    $user_Name        = filter_var($_POST["userName"], FILTER_SANITIZE_STRING);
    $user_Email       = filter_var($_POST["userEmail"], FILTER_SANITIZE_EMAIL);
    $user_Message     = filter_var($_POST["userMessage"], FILTER_SANITIZE_STRING);
    
    $headers = 'From: '.$user_Email.'' . "\r\n" . 
    'Reply-To: '.$user_Email.'' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();
    
    $sentMail = @mail($to_Email, $subject, $user_Message .'  -'.$user_Name, $headers);
    
    if(!$sentMail)
    {
        $output = json_encode(array('type'=>'error', 'text' => 'Could not send mail! Please check your PHP mail configuration.'));
        die($output);
    }else{
        $output = json_encode(array('type'=>'message', 'text' => 'Hello, <b>'.$user_Name .'</b>, thank you for your email. Will get back to you as soon as possible.'));
        die($output);
    }
}
?>

What am I missing here? Any advice is much appreciated!

PS: This is the same script that works on the other shared hosting and I’m struggling to make it work here at DO.

Hi to everyone

Thanks for the tutorial, it’s very clear and easy to follow ,

Just one question Why take so long to send the email around 1-2 minutes?

Any suggestion to solve this?