Do you need to send emails from your PHP application?
This complete guide will teach you how to setup and run the most used PHP email library: PHPMailer.
Learning how to send emails will take your PHP code to the next level. You will be able to write an alert daemon, receive an email when someone tries to log in and much more.
This tutorial covers all you need to know: the installation steps, the class functions, how to use SMTP authentication (including Gmail), how to handle errors and more. You will also find many code examples.
(You probably want to add this page to your Bookmarks to come back here for reference.)
Table of contents
- why use PHPMailer instead of mail() or other libraries?
- how to install PHPMailer on Windows and Linux (updated in 2018, with and without Composer)
- how to send your first email
- how to use the PHPMailer class
- how to use a custom SMTP server
- debugging and error handling
- how to use PHPMailer with Google (Gmail) SMTP
- conclusion

WHY USE PHPMAILER?
PHPMailer offers many functionalities over the PHP core function mail(), including SMTP SSL encryption and authentication, HTML messages, file attachments and more.
On top of that, PHPMailer is much easier to use than mail() and provides a clean, readable object-oriented syntax.
Let’s see in more detail why you should use PHPMailer instead of mail() or other third-party libraries.
WHY USE PHPMAILER INSTEAD OF mail()?
For at least two good reasons.
The first is that mail() relies on the server email subsystem to work. This means that if you want to change some settings like the SMTP server or the authentication parameters, you need to do it system wide.
That is usually a quite difficult operation, and unless you have a dedicated server or you are using a local PHP development environment, you are probably not even allowed to do it.
This also makes almost impossible to use different configurations at the same time, for example using multiple SMTP accounts and switching between them programmatically.
As you will see in a minute, with PHPMailer is very easy to change any parameter dynamically right in your PHP script.
The second reason is that mail() doesn’t offer any advanced functionality.
mail() is fine for sending simple, plain text emails, but it’s very limiting if you need to do anything more than that. Adding attachments or sending HTML emails, for example, is very difficult with mail(), while with PHPMailer it’s just a matter of a single line of code.

ARE THERE PHPMAILER ALTERNATIVES?
Yes, there are other libraries like Zend Mail, SwiftMailer and Zeta Components Mail, but PHPMailer is usually the first choice because of its popularity.
Of course, if you are already familiar with another mail extension and it works fine for you, you can just stick with it.
But if you want to start using one of them and you need to choose which one to go with, PHPMailer is probably the best choice because it’s the most used one.
Other extensions like Zend Mail, SwiftMailer or Zeta Components Mail are probably as good as PHPMailer, but look at the Google search results for “php mail library”:

And these are the results on YouTube:

As you can clearly see, PHPMailer dominates the first results. That doesn’t necessarily mean PHPMailer is better than other extensions, but it does mean it’s the most popular.
The main reason you want to go with the most used library is support: the more widely used a piece of software is, the easier is to find help and examples online.
I should also mention that I have been using PHPMailer for work for a few years now, sending up to 100 emails per day with it. I use it to send alerts using PHP daemons, to monitor my scripts’ memory usage and to receive warnings if SQL injection attacks are detected.
As far as I remember, I never had any trouble with it, so chances are you won’t either.
If you want to learn more about how to use the PHP mail() function, the Pear Mail extension or Swift Mailer, you can take a look at this detailed tutorial from Mailtrap.
HOW TO INSTALL PHPMAILER? (UPDATED IN 2018)
Older versions of PHPMailer (up to version 5) used to provide a “PHPMailerAutoload.php” file, and all you needed to do was to include it in your script.
Starting from version 6, however, this file is no longer provided. Now, to make the PHPMailer class available in your script you have two options:
- use Composer to download PHPMailer and automatically create an autoloader file;
- manually download the PHPMailer source code and include the required files yourself.
The first option is the recommended one, because Composer takes care of all the download, update and dependency check steps. This is especially useful if you need to install other libraries as well, like the one needed for XOAUTH2 Google authentication (I will tell you how to use XOAUTH2 with Google later in this post).
However, the second option may be useful if you don’t want to install Composer for some reason, for example if you are using PHPMailer on a testing environment.
Let’s see both installation options, starting with the one with Composer.
Installing Composer and PHPMailer on Windows (if you use XAMPP, WAMP etc.)
Composer is a dependency manager for PHP. It helps you download, install and keep up to date PHP extensions and libraries.
Installing Composer requires just a couple of minutes:
- first, make sure you have a web development environment already installed (XAMPP, WAMP, EasyPHP etc.) as Composer needs a PHP executable to work;
- download the Composer installation file from here (under “Windows Installer”) and run it;
- follow the installation instructions, and make sure you can select a PHP executable:

- once the installation is complete, you will be able to use the Composer command line tools to install PHPMailer.
Now you need to open a terminal (by executing “cmd.exe” or looking for “Command prompt” in the Start menu) and navigate to the directory where you want to install the Composer packages including PHPMailer (if you need help using the terminal just leave me a comment below).
For example, let’s use “C:\xampp\composer” as installation directory. First create the directory, then go back to the terminal and move into the directory by typing “cd C:\xampp\composer”.
Then, simply execute the command: “composer require phpmailer/phpmailer” as shown in the following image:

PHPMailer will be installed and you’ll be ready to use it.
Composer will generate an “autoload.php” file you can use to include the installed libraries, in this case PHPMailer. This file is located under the “vendor” directory by default, although you can configure Composer to use a different directory name.
So, assuming your installation directory is “C:\xampp\composer”, you need to include the “C:\xampp\composer\vendor\autoload.php” file.
Also, because now PHPMailer defines its classes under the PHPMailer\PHPMailer namespace, it’s a good idea to make use of the use directive at the beginning of your script, aliasing the PHPMailer\PHPMailer\PHPMailer and PHPMailer\PHPMailer\Exception classes:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$email = new PHPMailer(TRUE);
/* ... */
Installing Composer and PHPMailer on Linux
Many GNU/Linux distributions include the Composer package in their repositories.
On Debian-like systems (including Ubuntu), for example, you can simply use the “apt-get” command to install Composer (installing Composer from the source code is outside the scope of this guide, but if you need help with it feel free to ask me).
Once Composer is installed, you can use the Composer command line executable to install PHPMailer inside a directory of your choice, just like we already saw for the Windows installation (you can use the very same command):

Now PHPMailer is installed.
You can include the “autoload.php” file and set the namespace aliases just like for the Windows installation (changing the file path, of course).
Installing PHPMailer without Composer
If you prefer not to use Composer, you can just download the PHPMailer source files and include the required files manually.
You can download the ZIP file with the source code from the PHPMailer homepage, clicking on the “Clone or download” green button (on the right) and then selecting “Download ZIP”. Unzip the package inside the directory where you want to save the source files.
Then you just need to include the needed classes files in your PHP script.
As a minimum, you want to include the main PHPMailer class, the Exception class (for error handling) and probably the SMTP class too, if you are going to connect to an SMTP server for mail delivery.
You should also set the namespace aliases just like you saw before for the Composer installation.
Assuming your source code directory is “C:\PHPMailer”, this is how your PHP script will look like:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
/* Exception class. */
require 'C:\PHPMailer\src\Exception.php';
/* The main PHPMailer class. */
require 'C:\PHPMailer\src\PHPMailer.php';
/* SMTP class, needed if you want to use SMTP. */
require 'C:\PHPMailer\src\SMTP.php';
$email = new PHPMailer(TRUE);
/* ... */
Keeping PHPMailer up to date
If you choose the Composer installation method, you can keep your PHPMailer installation up to date by executing the “update” Composer command.
The syntax is the same on both Windows and Linux. Just go to the installation directory (where you issued the installation command) and execute the update:
composer update
If you choose not to use Composer, then you will need to manually download the new ZIP file from the PHPMailer homepage and overwrite the previous installation (following the same steps).
In either case, before updating your installation is a good idea to look at the changelog file and the update notes, just to be sure that your PHP applications are compatible with the new PHPMailer version.
HOW TO SEND YOUR FIRST EMAIL WITH PHPMAILER
To send an email with PHPMailer you need to create a PHPMailer object, set some parameters using its methods and attributes and finally call the send() method.
Let’s see a basic example so you can understand how this class works (don’t worry about the details for now, we will cover them in the next chapter).
In all the examples I will use the Windows installation path, because I am working on my local XAMPP development environment. If you are using Linux just change the include paths accordingly.
<?php
/* Namespace alias. */
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
/* Include the Composer generated autoload.php file. */
require 'C:\xampp\composer\vendor\autoload.php';
/* If you installed PHPMailer without Composer do this instead: */
/*
require 'C:\PHPMailer\src\Exception.php';
require 'C:\PHPMailer\src\PHPMailer.php';
require 'C:\PHPMailer\src\SMTP.php';
*/
/* Create a new PHPMailer object. Passing TRUE to the constructor enables exceptions. */
$mail = new PHPMailer(TRUE);
/* Open the try/catch block. */
try {
/* Set the mail sender. */
$mail->setFrom('darth@empire.com', 'Darth Vader');
/* Add a recipient. */
$mail->addAddress('palpatine@empire.com', 'Emperor');
/* Set the subject. */
$mail->Subject = 'Force';
/* Set the mail message body. */
$mail->Body = 'There is a great disturbance in the Force.';
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
/* PHPMailer exception. */
echo $e->errorMessage();
}
catch (\Exception $e)
{
/* PHP exception (note the backslash to select the global namespace Exception class). */
echo $e->getMessage();
}
See how PHPMailer uses a nice and easy OOP syntax?
The class’ constructor argument is set to TRUE to make PHPMailer use exceptions for error reporting.
If you prefer not to use exceptions, just omit the argument (or set it to FALSE). In this case you need to check the send() method return value and look for the error message in the $ErrorInfo attribute:
<?php
/* Namespace alias (don't need Exception this time). */
use PHPMailer\PHPMailer\PHPMailer;
/* Include the Composer generated autoload.php file. */
require 'C:\xampp\composer\vendor\autoload.php';
/* Create a new PHPMailer object. */
$mail = new PHPMailer();
/* Set the mail sender. */
$mail->setFrom('darth@empire.com', 'Darth Vader');
/* Add a recipient. */
$mail->addAddress('palpatine@empire.com', 'Emperor');
/* Set the subject. */
$mail->Subject = 'Force';
/* Set the mail message body. */
$mail->Body = 'There is a great disturbance in the Force.';
/* Finally send the mail. */
if (!$mail->send())
{
/* PHPMailer error. */
echo $mail->ErrorInfo;
}
It’s interesting to see how this script would look like if you were using the mail() function:
<?php
$from = 'Darth Vader <darth@empire.com>';
$to = 'Emperor <palpatine@empire.com>';
$subject = 'Force';
$message = 'There is a great disturbance in the Force.';
$headers = 'From: ' . $from;
if (!mail($to, $subject, $message, $headers))
{
echo "Error.";
}
else
{
echo "Message sent.";
}
Yes, the syntax is much worse 🙂
In the previous basic example, we did not tell PHPMailer to use a specific SMTP server. In this case PHPMailer uses the server email subsystem, just like mail() does.
Of course, you want to use your own SMTP connection parameters instead. Don’t worry: we’ll cover this in a minute.
Now let’s see how to use all the PHPMailer class functionalities.
Would you like to talk with me and other developers about PHPMailer, PHP and web development? Join my Facebook Group now: Alex PHP café
See you there 🙂
HOW TO USE THE PHPMAILER CLASS
Once you have created a PHPMailer object as seen in the previous examples, you can use the extensive PHPMailer class functionalities to set all the email parameters and attributes you need.
Let’s see the most useful PHPMailer methods.
- Set the sender (“From:”) address
This is probably the first thing you want to do. This method takes the sender address as first parameter, while the second parameter is optional and sets the sender name as will be seen by the recipients.
$mail->setFrom('darth@empire.com', 'Darth Vader');
- Add a recipient (“To:”) address
This is the second thing you want to do 🙂
Like for the sender, the second parameter is optional and specifies the name of the recipient.
$mail->addAddress('palpatine@empire.com', 'Emperor');
- Set the email subject
$mail->Subject = 'Force';
- Set the email body (the actual message)
The message body can include plain text and HTML code. If you want your email to be parsed as HTML, be sure to read the next point.
$mail->Body = 'There is a great disturbance in the Force.';
- Create an HTML email message
The isHTML() method sets the email body content type to HTML. You can also include an alternative, plain text body for those email clients that do not support HTML or that are configured not to display HTML messages.
It’s a good idea to always include a plain text alternative body to be sure everyone will be able to read your emails.
$mail->isHTML(TRUE);
$mail->Body = '<html>There is a great disturbance in the <strong>Force</strong>.</html>';
$mail->AltBody = 'There is a great disturbance in the Force.';
- Add an attachment
You can attach files to your email using the addAttachment() function.
This function takes two parameters: the first is the file path, and the second (optional) is the file name that the recipient will see. If not set, the same file name of the local file will be used.
Note that the file must be readable by the user running the PHP script (this is especially important under Linux systems).
$mail->addAttachment('/home/darth/star_wars.mp3', 'Star_Wars_music.mp3');
- Set a different reply-to address
You can specify which address the recipient will reply to when replying to your email. The default is the sender (“From:”) address, but you can change it.
$mail->addReplyTo('vader@empire.com', 'Lord Vader');
- Add CC and BCC recipientsAll CC (carbon-copy) and BCC (blind carbon-copy) recipients will receive the email, but BCC addresses will be invisible to other recipients.
$mail->addCC('admiral@empire.com', 'Fleet Admiral');
$mail->addBCC('luke@rebels.com', 'Luke Skywalker');
- Create an attachment from binary data
With PHPMailer you can create a “virtual” attachment from a binary stream, like a database binary field or a network stream. This means that you don’t have to save the data to a local file before sending it as an attachment.In the example below, we attach two files: the first contains the data from a “blob” (binary) SQL field and is named “db_data.db”, the second is created from a network stream (a PDF file) and is named “file.pdf”.
/* Binary stream from a database blob field */
$mysql_data = $mysql_row['blob_data'];
$mail->addStringAttachment($mysql_data, 'db_data.db');
/* Binary network stream */
$pdf_url = 'http://remote-server.com/file.pdf';
$mail->addStringAttachment(file_get_contents($pdf_url), 'file.pdf');
- Create an HTML message from a string
The msgHTML() method automatically reads an HTML string (or a local file, using file_get_contents() to read it) into an embedded HTML message. The second parameter tells the function where to look for images, so that they can be included inline in the message.
Note that this function will override both Body and AltBody attributes.
$mail->msgHTML(file_get_contents('contents.html'), __DIR__);
HOW TO USE A CUSTOM SMTP SERVER
PHPMailer lets you configure the SMTP connection parameters directly from your PHP script, using the PHPMailer class methods and attributes.
This is incredibly useful compared to mail(), which relies on the underlying system configuration instead.
The following example shows how you can use a specific SMTP server using SSL and authentication:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
/* SMTP parameters. */
/* Tells PHPMailer to use SMTP. */
$mail->isSMTP();
/* SMTP server address. */
$mail->Host = 'smtp.empire.com';
/* Use SMTP authentication. */
$mail->SMTPAuth = TRUE;
/* Set the encryption system. */
$mail->SMTPSecure = 'tls';
/* SMTP authentication username. */
$mail->Username = 'smtp@empire.com';
/* SMTP authentication password. */
$mail->Password = 'iamyourfather';
/* Set the SMTP port. */
$mail->Port = 587;
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
Of course, you need to use the correct connection parameters, including the server encryption capabilities and the TCP port it listens to.
A more advanced SMTP related attribute is the SMTPOptions array. If you are using SMTP encryption, PHPMailer passes this array to the underlying PHP stream_context_create() function.
You can use the SMTPOptions attribute to set advanced SSL context options. While you won’t need to use it most of the time, in some cases it can be really useful.
For example, if you have your own SMTP server which uses a self-signed certificate, the SMTP connection will probably fail for the lack of a valid certification authority signature. This is a quite common scenario in work environments.
In these cases, you can use the SMTPOptions attribute to tell PHPMailer (and the PHP SSL subsystem) to ignore this issue.
In the following example we set the verify_peer and verify_peer_name parameters to FALSE and the allow_self_signed parameter to TRUE in order to disable some security checks:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
/* SMTP parameters. */
$mail->isSMTP();
$mail->Host = 'smtp.empire.com';
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = 'tls';
$mail->Username = 'smtp@empire.com';
$mail->Password = 'iamyourfather';
$mail->Port = 587;
/* Disable some SSL checks. */
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
A PRACTICAL VIDEO EXAMPLE
Why don’t you look at a practical video example? This nice video from Mr. Digital shows how to create a PHPMailer script:
DEBUGGING AND ERROR HANDLING
If something goes wrong while trying to send the message, the PHPMailer object throws and exception (if TRUE is passed to the constructor) and saves the error information inside the $ErrorInfo attribute.
The best way to handle errors is to use a try/catch block to catch the exception, as shown in the previous examples. The PHPMailer/Exception class provides the errorMessage() method to retrieve the error message directly from the exception object.
SMTP DEBUG
You can set the SMTPDebug attribute to enable on screen SMTP connection debugging.
This kind of debugging output can be extremely useful in the development phase, because it lets you see if something goes wrong with the SMTP connection.
Note that the SMTPDebug output should be used for debugging purposes only, because it can expose sensitive data to remote clients.
The SMTPDebug argument can be set to an integer value between 0 (the default, no output is generated) and 4 (low-level info output is displayed). If your emails are not being sent, I suggest you set this value to 4 and see what happens:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'C:\xampp\composer\vendor\autoload.php';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom('darth@empire.com', 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
$mail->isSMTP();
$mail->Host = 'smtp.empire.com';
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = 'tls';
$mail->Username = 'smtp@empire.com';
$mail->Password = 'iamyourfather';
$mail->Port = 587;
/* Enable SMTP debug output. */
$mail->SMTPDebug = 4;
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
ERROR MESSAGES LOCALIZATION
PHPMailer supports error messages localization. You can use one of the many (48 at the moment of writing) already available translations (you can find the list here) or even create a customized language set by yourself.
To set the language, just call the setLanguage() method:
/* Set language to Italian using a default translation set. */
$mail->setLanguage('it');
/* Or use your own translation set
(in this case you need to specify the translation file path). */
$mail->setLanguage('klingon', 'C:\PHPMailer\myLanguages\');
If you want to use your own translation set, then you need to pass the translation file path to the function as second parameter (with a trailing directory separator). If you are using one of the default ones, then leave the second parameter empty.
HOW TO USE PHPMAILER WITH GOOGLE (GMAIL) SMTP
The Google SMTP server is smtp.gmail.com. It uses TLS-encrypted connections and listens to port 587.
The PHPMailer SMTP configuration should therefore use those settings:
/* Use SMTP. */
$mail->isSMTP();
/* Google (Gmail) SMTP server. */
$mail->Host = 'smtp.gmail.com';
/* SMTP port. */
$mail->Port = 587;
/* Set authentication. */
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
SMTP servers usually require clients to authenticate themselves with username and password before they are allowed to send messages. Google’s SMTP does too, but you may need to take additional steps to make it work.
Google’s SMTP authentication steps with PHPMailer depend on whether you have Google two-step verification enabled or not.
GMAIL AUTHENTICATION WITH 2-STEP VERIFICATION DISABLED
If you don’t have Google two-step verification enabled, you can try using your own username (in this case, your email address) and password to login:
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
/* Username (email address). */
$mail->Username = 'myusername@gmail.com';
/* Google account password. */
$mail->Password = 'mypassword';
That *may* work, however Google is very suspicious about unusual log in attempts and may refuse to authorize your PHPMailer script authentication process. This is also explained in this PHPMailer’s Troubleshooting document.
Google’s SMTP may ask the “client” (in this case, the PHPMailer script) to log in with the web browser first, or to follow this page‘s instructions.
If you don’t want to enable 2-step verification, you probably must tell Google to “Allow less secure apps” login attempts for the PHPMailer’s authentication to be accepted.
To do that you can follow these instructions, or just go here while logged in with the Google account you want to use.
After you have authorized “less secure apps” connections, you can try again and see if it works (you may need to wait for a couple of hours for the change to take effect).
If it still doesn’t work, you are left with two options: enable the 2-step verification and follow the instructions below or use the XOAUTH2 authentication process as described later in this tutorial.
Your choice 🙂
GMAIL AUTHENTICATION WITH 2-STEP VERIFICATION ENABLED
If you enabled two-step verification then you need to create an “App password” and use it to log in with PHP, because you won’t be able to use the second authentication factor with PHPMailer (which involves using an authentication app or authorizing the access with your smartphone).
An “app password” is a string you can use to login without the second authentication factor. To create one, just follow Google’s instructions at this page or just open this link.
From there, choose a name for your app (for example, “PHPMailer”) and press the “Generate” button as seen in this image:

After pressing the button, you will obtain a 16-chars string you can use to log in. Be sure to copy it right away, because you won’t be able to retrieve it later (if you lose it, you will need to create a new app password from scratch):

Now all you need to do is use this new string as password in your PHPMailer configuration (without spaces, those are there just for readability):
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Username = 'myusername@gmail.com';
/* App password. */
$mail->Password = 'eqwvrwlbbizcsdcz';
USING GMAIL WITH XOAUTH2 AUTHENTICATION
XOAUTH2 is Google’s recommended authentication method. While it’s a quite complex protocol, thanks to PHPMailer is possible to use it without much difficulty.
PHPMailer’s XOAUTH2 implementation relies on the league/oauth2-client library, that must therefore be installed on your system. Specifically, you need to install the league/oauth2-google package.
The easiest way to install it is to use Composer. If you chose to install PHPMailer with Composer, then you can do the same with the league/oauth2-google library: just go to the Composer installation directory and type “composer require league/oauth2-google”:

You can also install this library inside another directory, but in this case you will need to include two autoloader.php files. If you didn’t use Composer to install PHPMailer, just install the OAUTH2 library in a new directory.
Unfortunately, installing league/oauth2-google without Composer is a bit difficult, because it requires a few libraries to be installed as well. If you really hate Composer and don’t want to use it, you will need to download them all manually and include them in your scripts.
Once you have league/oauth2-google installed, you will need to perform some steps with the Google account you are going to use.
All these steps are explained in detail in this PHPMailer XOAUTH2 tutorial. Follow all the steps but stop before the last “Configure your email script” paragraph, because it’s outdated and the example code there no longer works.
Keep in mind that you will need to have a working development environment, because you will need to edit a PHPMailer file (get_oauth_token.php) and run it with a web browser.
After you have completed all the required steps, you will have three authentication strings:
- the Client ID
- the Client Secret
- and the Refresh Token
You need to use them in your PHPMailer XAUTH2 authentication process.
Next you need to configure the PHPMailer script, include the OAUTH2 library and set the authentication parameters. The required steps are:
- set namespace aliases for the PHPMailer OAuth and league Google classes;
- include the league library (if you used the same Composer installation directory then the autoloader.php file will take care of that);
- set the script time zone to UTC; this is needed for proper time synchronization with the Google server;
- set the PHPMailer class AuthType attribute to “XOAUTH2”;
- create a league/Google object and a PHPMailer/OAuth object with the authentication strings you got in the previous steps and use them for the authentication process.
In this final example you can see how this is done:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
/* New aliases. */
use PHPMailer\PHPMailer\OAuth;
use League\OAuth2\Client\Provider\Google;
/* Composer autoload.php file includes all installed libraries. */
require 'C:\xampp\composer\vendor\autoload.php';
/* If you installed league/oauth2-google in a different directory, include its autoloader.php file as well. */
// require 'C:\xampp\league-oauth2\vendor\autoload.php';
/* Set the script time zone to UTC. */
date_default_timezone_set('Etc/UTC');
/* Information from the XOAUTH2 configuration. */
$google_email = 'myaddress@gmail.com';
$oauth2_clientId = 'CliendIdString';
$oauth2_clientSecret = 'ClientSecret';
$oauth2_refreshToken = 'RefreshToken';
$mail = new PHPMailer(TRUE);
try {
$mail->setFrom($google_email, 'Darth Vader');
$mail->addAddress('palpatine@empire.com', 'Emperor');
$mail->Subject = 'Force';
$mail->Body = 'There is a great disturbance in the Force.';
$mail->isSMTP();
$mail->Port = 587;
$mail->SMTPAuth = TRUE;
$mail->SMTPSecure = 'tls';
/* Google's SMTP */
$mail->Host = 'smtp.gmail.com';
/* Set AuthType to XOAUTH2. */
$mail->AuthType = 'XOAUTH2';
/* Create a new OAuth2 provider instance. */
$provider = new Google(
[
'clientId' => $oauth2_clientId,
'clientSecret' => $oauth2_clientSecret,
]
);
/* Pass the OAuth provider instance to PHPMailer. */
$mail->setOAuth(
new OAuth(
[
'provider' => $provider,
'clientId' => $oauth2_clientId,
'clientSecret' => $oauth2_clientSecret,
'refreshToken' => $oauth2_refreshToken,
'userName' => $google_email,
]
)
);
/* Finally send the mail. */
$mail->send();
}
catch (Exception $e)
{
echo $e->errorMessage();
}
catch (\Exception $e)
{
echo $e->getMessage();
}
CONCLUSION
Mastering PHP email handling is a big advantage.
With this tutorial, you have learned all you need to know to use PHPMailer at its full potential: how to install it, how to use its functionalities, how to configure SMTPS connections (including Gmail’s), error handling and more.
Feel free to bookmark this page and return here for reference as needed.
If you have any issue, check the PHPMailer Troubleshooting guide or just leave me a comment below. You are also invited to join my Facebook Group (Alex PHP café) where me and my community will be very glad to help you!
Now, I’m curious: how do YOU use email in your web applications? I’m looking forward to hearing from you!
P.s. If this guide has been helpful to you, please spend a second of your time to share it… thanks!
Alex
C:\xampp\composer>composer require phpmailer/phpmailer
./composer.json has been updated
Running composer update phpmailer/phpmailer
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
Failed to download phpmailer/phpmailer from dist: The zip extension and unzip/7z commands are both missing, skipping.
The php.ini used by your command-line PHP is: C:\xampp\php\php.ini
Now trying to download from source
In GitDownloader.php line 82:
git was not found in your PATH, skipping source download
require [–dev] [–dry-run] [–prefer-source] [–prefer-dist] [–prefer-install PREFER-INSTALL] [–fixed] [–no-suggest] [–no-progress] [–no-update] [–no-install] [–no-audit] [–audit-format AUDIT-FORMAT] [–update-no-dev] [-w|–update-with-dependencies] [-W|–update-with-all-dependencies] [–with-dependencies] [–with-all-dependencies] [–ignore-platform-req IGNORE-PLATFORM-REQ] [–ignore-platform-reqs] [–prefer-stable] [–prefer-lowest] [–sort-packages] [-o|–optimize-autoloader] [-a|–classmap-authoritative] [–apcu-autoloader] [–apcu-autoloader-prefix APCU-AUTOLOADER-PREFIX] [–] […]
C:\xampp\composer>
doesnt install for me
Hey Alex,
I’m receiving the following on my Command Prompt after trying to install phpmailer…
” Failed to download phpmailer/phpmailer from dist: The zip extension and unzip/7z commands are both missing, skipping.
The php.ini used by your command-line PHP is: C:\xampp\php\php.ini
Now trying to download from source
In GitDownloader.php line 82:
git was not found in your PATH, skipping source download”
Could you please help?
Hello, try installing 7zip from here: https://7-zip.org/download.html
Then try again.
that solved my issue even though you were replying to someone else. thanks
Thanks for this great tutorial. Just a small note for others benefit that my SMTPSecure did not work with ‘ttl’ but worked when I defined it as ‘ssl’. Furthermore, SMTPAuth is case sensitive and should have ‘true’ (as seen below). It did not work with ‘TRUE’ for some reason.
$mail->SMTPAuth = true;
$mail->SMTPSecure = ‘ssl’;
Thank you for sharing your notes!
“ttl” is definitely not correct, but “tls” should be. The best way to set that option would be to use PHPMailer’s own constants: ENCRYPTION_SMTPS (which translates to ssl) or ENCRYPTION_STARTTLS (which translates to tls).
About true vs TRUE, that’s a bit odd because PHP should consider them as the same Boolean value. Let me know if you would like to investigate this further.
$result = $mail->Send();
if(!$result) {
// There was an error
// Do some error handling things here
} else {
echo “Email successful”;
}
Not displaying Error
To print the error, you need to enable SMTP debugging and print the Exception message.
Look at the “DEBUGGING AND ERROR HANDLING” section for a full-code example.
Hi there, great tutorials, I wanted to ask, the email sent are often considered SPAM by Gmail when I make some test, is there any solutions about that?
This happens when I try to send an email using my server’s email SMTP’s configurations ( including the login, authentification, etc…) which is not using google’s @gmail.com domain name. Can you give some explanations ( that I think will benefit some people in here ). Thank you
We are using this https://www.pakainfo.com/phpmailer-sending-emails-using-php-code/ code.
if (isset($_POST[‘submit’]))
{
include_once(‘class.phpmailer.php’);
$name = strip_tags($_POST[‘full_name’]);
$email = strip_tags ($_POST[’email’]);
$msg = strip_tags ($_POST[‘description’]);
$subject = “Contact Form from DigitDevs Website”;
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->CharSet = ‘UTF-8’;
$mail->Host = “mail.example.com”; // SMTP server example
//$mail->SMTPDebug = 1; // enables SMTP debug information (for testing)
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Port = 26; // set the SMTP port for the GMAIL server
$mail->Username = “info@example.com”; // SMTP account username example
$mail->Password = “password”; // SMTP account password example
$mail->From = $email;
$mail->FromName = $name;
$mail->AddAddress(‘info@example.com’, ‘Information’);
$mail->AddReplyTo($email, ‘Wale’);
$mail->IsHTML(true);
$mail->Subject = $subject;
$mail->Body = $msg;
$mail->AltBody = ‘This is the body in plain text for non-HTML mail clients’;
if(!$mail->Send()) {
echo ‘Message could not be sent.’;
echo ‘Mailer Error: ‘ . $mail->ErrorInfo;
exit;
}
echo ‘Message has been sent’;
Hello,
Do you get any error message at all?
Try setting the SMTPDebug property to 4 and check the SMTP messages. These messages often help.
I do not know where to start debugging this test file as it is essentially a carbon copy of your file with SMTP and HTML body thrown in.
My code But It’s Not working!!
$mail = new PHPMailer();
// Settings
$mail->IsSMTP();
$mail->CharSet = ‘UTF-8’;
$mail->Host = “mail.example.com”; // SMTP server example
$mail->SMTPDebug = 0; // enables SMTP debug information (for testing)
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Port = 25; // set the SMTP port for the GMAIL server
$mail->Username = “username”; // SMTP account username example
$mail->Password = “password”; // SMTP account password example
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = ‘Here is the subject’;
$mail->Body = ‘This is the HTML message body in bold!‘;
$mail->AltBody = ‘This is the body in plain text for non-HTML mail clients’;
$mail->send();
Hello, if you get no errors but no email is coming through, then I suggest you set the SMTPDebug debug variable to 4 and look at the error message. It may be SMTP related. Read the “SMTP Debug” chapter from this tutorial for all the details.
Hi Alex
I have been using php mailer and all was working fine . I have setup a webform where i collect the data and send it to specific email adress. But since last two days the form on the website is getting submitted but the recipient does not receive it at all. This is happening for all the website in my server. Just to highlight that there was no changes made in either.
Could you please help.
Hello,
I suggest you enable SMTP debugging and look at the PHPMailer debug messages. From there you can get a clue about the problem.
Hi Alex,
Below is my script and it works together with include.
How can I split it, so I add the main code with require in the beginning of scripts where I want to send emails, where i just use a function like:
f_send_mail(@email,$subject,$body)?
—————————————————————————-
// Use
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
// Require
require ‘./PHPMailer/src/Exception.php’;
require ‘./PHPMailer/src/PHPMailer.php’;
require ‘./PHPMailer/src/SMTP.php’;
// Generate email
$mail = new PHPMailer;
$mail->isSMTP();
$mail->CharSet = ‘UTF-8’;
$mail->SMTPDebug = 2;
$mail->Host = ‘websmtp.myisp.com’;
$mail->Port = 587;
$mail->SMTPSecure = ‘tls’;
$mail->SMTPAuth = true;
$mail->Username = ‘post@mywebsite.dk’;
$mail->Password = ‘mypassword’;
$mail->setFrom(‘post@mywebsite.dk’);
$mail->addAddress($email);
$mail->Subject = $subject;
$mail->msgHTML($body);
if(!$mail->send()) {
echo “Mailer Error: ” . $mail->ErrorInfo;
} else {
echo “Message sent!”;
}
Hello John,
I have removed the duplicated post.
What you can do is create a separate PHP script, for example “f_send_mail.php”. In that file you will put the PHPMailer “require” and “use” directives:
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require ‘./PHPMailer/src/Exception.php’;
require ‘./PHPMailer/src/PHPMailer.php’;
require ‘./PHPMailer/src/SMTP.php’;
Also, you will define the f_send_mail(@email,$subject,$body) function. The body of this function is basically all the code from “$mail = new PHPMailer;” up to $mail->send.
Finally, when you want to use this function, you just need to include the f_send_mail.php file and call the function.
Great work but how to I make this work on my webserver?
I tried to use one of this examples and I am getting a fatal error require_once() Failed opening required and the path.
Hello,
If require_once() fails it means the file path is wrong. Can you check that?
I’m struggling to understand how to send emails with PHPMailer.
I have multiple website clients and I have implemented a contact form for each of them. I can send emails to my own email address but not to theirs.
This is the function I wrote to do it.
function sendSMTP($host, $usr, $pwd, $port, $fromAddr, $fromName,
$replyAddr, $replyName, $addr, $subject, $body)
{
$mail = new PHPMailer(true);
$mail->SMTPDebug = 1;
$mail->isSMTP();
$mail->Host = $host;
$mail->SMTPAuth = true;
$mail->Username = $usr;
$mail->Password = $pwd;
$mail->SMTPSecure = ‘ssl’;
$mail->Port = $port;
$mail->setFrom($fromAddr, $fromName);
$mail->addReplyTo($replyAddr, $replyName);
$mail->addAddress($addr);
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $body;
}
I have a feeling it’s not working because of something to do with the first 4 parameters (host, user, password, port). I started this months ago and sat on it and now I’m totally lost on how to fix it.
Do I have to authenticate various sender accounts for each client? I’m stuck. What is the correct way to use this function?
Hello (sorry for the late reply).
Which SMTP server and from address are you using for your clients? I’m asking because, if you want to send an email using a specific from address, then you need to use the proper SMTP server and authentication. The TO address is not relevant, but the FROM address is.
copy paste your url but display error on my sever like – I am getting a fatal error require_once() Failed opening required and the path.
Hello,
The file path used for require() is probably wrong. Can you double check that?
I need instruction on how to connect the PHPMailer SMTP to Microsoft 365 Email.
Hello,
You need to find out the SMTP settings for your Microsoft account. Try searching for “Microsoft SMTP”.
On top of that, you must check which security protocol you need to use (TLS, probably). Finally, if you are using 2-factor authentication you probably need to create an “app password” to use with PHPMailer.
Hello Alex,
This is a well written tutorial. But am still completely new to Composer and have only been working with PHP for a few months. I managed to set up a local server (LAMP) and have quite a few files loaded into the localhost site, including a small MySQL database. After some struggle, those seem to be working OK.
I need to get PHPMailer and another API working with NowPayments. After looking into how to set up composer and pull libraries into my project, I attempted to do this in my directory /var/www/bookcorner where my other files are. When trying to used Composer to bring in the libraries, I got a nasty error so I used a folder outside the root directory called ComposerDirectory. Here I used Composer require to bring in PHPMailer and some other packages I will need. Then I copied this vendor file into my actual project folder. I do not know if that is equivalent or would give a working library.
Then, I followed your tutorial to create a phpmailerTest.php file with SMTP with my SMTP mail settings, host, password, port (465), etc. When attempting to launch this file I get a 500 error. “This page isn’t working. Localhost is currently unable to handle this request.” Other php pages accessing my local database are working and the index.php page with phpinfo(); work as they should.
I do not know where to start debugging this test file as it is essentially a carbon copy of your file with SMTP and HTML body thrown in.
I am on a long project to completely integrate the customer checkout with NowPayments and PHPMailer for sending confirmation of the order, Thank You, etc..
The code I’m attempting to use is here — https://pastebin.com/4fBP0E9A
Cheers!
Michael J. Scharen
Hello Michael,
Thank you for sharing your problem and for attaching the code (which is always very helpful).
A 500 error usually means there is a fatal error in the PHP code. Can you check that the autoload.php path, used in the require ‘vendor\autoload.php’; statement, is correct?
Dear Alex
Need to change in “php.ini” file. Because I got an error message, please advise.
2021-12-17 02:30:04 Connection: opening to smtp.gmail.com:587, timeout=300, options=array()
2021-12-17 02:30:25 Connection failed. Error #2: stream_socket_client(): unable to connect to smtp.gmail.com:587 (A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.) [PHPMailer\vendor\phpmailer\phpmailer\src\SMTP.php line 388]
2021-12-17 02:30:25 SMTP ERROR: Failed to connect to server: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (10060)
SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting
Error while sending Email.
Hey Siva,
It seems like a connection issue. Maybe your PHP script is being blocked by a firewall or a network configuration.
Are you working on your local computer or on a remote server?
First I test on my local computer, then I upload it into my remote server.
Thank you.
Does the error appear on your local computer or on the remote server (or both)?
In any case, please check whether you can connect to the Gmail’s smtp server on the 587 port. You can use a tool such as Putty or Telnet to test the connection.
If the connection cannot be established then there may be a firewall or a network policy blocking the route.
Thank you Alex. A web host directed me to your website. I want to install PHPMailer to my website directory. I was able to manually access PHPMailer on my localhost manually, however it did not work on my website directory. I was having the error failed to open stream: no such file or directory.
Also, failed opening required PHPMailer/src/exception.php
Include_path=.:/opt/alt/php72/usr/share/pear
Hello Joseph,
You are probably using the wrong path for the Exception.php file.
Note that the first “E” is uppercase, this does make a difference. Can you try and change that and see if it works?
I am using PHP on a website and I want to add emailing functionality.
I have PHPMailer installed.
How do I send an email using PHP?
Well, this is exactly what this tutorial is about 🙂
Are you getting stuck somewhere applying the tutorial’s steps?
Awesome article Alex, I had some issues authenticating with my google account but now everything is working perfectly. Cheers mate!
Thanks for the comment.
I’m glad to know you made it work!