How to Send Email using Gmail API in PHP

When it comes to a website, we have to send emails to the users for various reasons. PHP provides a mail() function but there are limitations with it. Using this method, your emails most probably end up in spam. You’ll never like it. In the real world, we hardly check spam. If your emails go into spam, your users will probably miss your important emails.

To resolve this problem, we choose the SMTP server. It also has one drawback. While integrating SMTP, you need to pass your login details in plain text format. This can create a security problem. If your server gets compromised, your login credentials can get exposed.

Instead of going for the SMTP server, I’d recommend using the Gmail API which adds extra security. The Gmail API requires you to follow the OAuth 2.0 flow instead of your login credentials. Once you complete the Google OAuth steps, it generates the access token which will be used to send your application emails.

In this article, we study how to integrate Gmail API with the Symfony Mailer library. The Symfony Mailer is a component-based library for sending emails from PHP applications. It allows you to integrate third-party providers like Google to send your emails.

That being said, let’s take a look at how to send email using Gmail API in PHP.

Register an Application and Create Credentials

You first need to grab your OAuth client id and client secret. These credentials are required to build the Google OAuth flow.

Follow the steps below to get your keys.

  • Go to the Google Developer Console.
  • Create a new project. You can also select an existing project.
  • Add a name to your project. Google Console will generate a unique Project ID for it.
  • Your project will appear on top of the left sidebar.
  • Click on Library. You will see a list of Google APIs.
  • Enable Gmail API.
  • Click on the Credentials. Select Oauth Client id under Create credentials. Choose the radio button for Web Application.
  • Give the Name. In the ‘Authorized redirect URIs’ add the link of the redirect URL. In my case, I passed the URL http://localhost/mailer/callback.php
  • Click on the Create button. You will get a client ID and client secret in the pop-up. Copy these details. We will need it in a moment.
gmail-api-redirect-url

Basic Configuration

As I mentioned before, we need to generate an access token. This token should store in the database for later use. Each time our application sends an email, we need to fetch this token and use it.

Let’s create a MySQL table using the following query.

CREATE TABLE `google_oauth` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `provider` varchar(255) NOT NULL,
 `provider_value` text NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Next, create a DB class that will interact with the database and retrieves, store, update token information in the table.

class-db.php

<?php
class DB {
    private $dbHost     = "DB_HOST";
    private $dbUsername = "DB_USERNAME";
    private $dbPassword = "DB_PASSWORD";
    private $dbName     = "DB_NAME";
      
    public function __construct(){
        if(!isset($this->db)){
            // Connect to the database
            $conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
            if($conn->connect_error){
                die("Failed to connect with MySQL: " . $conn->connect_error);
            }else{
                $this->db = $conn;
            }
        }
    }
 
    public function is_token_empty() {
        $result = $this->db->query("SELECT id FROM google_oauth WHERE provider = 'google'");
        if($result->num_rows) {
            return false;
        }
 
        return true;
    }
 
    public function get_access_token() {
        $sql = $this->db->query("SELECT provider_value FROM google_oauth WHERE provider='google'");
        $result = $sql->fetch_assoc();
        return json_decode($result['provider_value']);
    }
 
    public function get_refersh_token() {
        $result = $this->get_access_token();
        return $result->refresh_token;
    }
 
    public function update_access_token($token) {
        if($this->is_token_empty()) {
            $this->db->query("INSERT INTO google_oauth(provider, provider_value) VALUES('google', '$token')");
        } else {
            $this->db->query("UPDATE google_oauth SET provider_value = '$token' WHERE provider = 'google'");
        }
    }
}

We will require a few packages to accomplish our task. Those packages are – Symfony Mailer, Symfony’s Google Mailer, and HybridAuth. Install these packages using the below commands.

composer require symfony/mailer
composer require symfony/google-mailer
composer require hybridauth/hybridauth

Generate OAuth Access Token for Gmail API

You have installed the HybridAuth library which will generate an access token. For this, you have to follow their configuration setup. Create a config.php file and add the below code to it.

<?php
require_once 'vendor/autoload.php';
require_once 'class-db.php';
 
define('GOOGLE_CLIENT_ID', 'PASTE_CLIENT_ID_HERE');
define('GOOGLE_CLIENT_SECRET', 'PASTE_CLIENT_SECRET_HERE');
 
$config = [
    'callback' => 'YOUR_DOMAIN_URL/callback.php',
    'keys'     => [
                    'id' => GOOGLE_CLIENT_ID,
                    'secret' => GOOGLE_CLIENT_SECRET
                ],
    'scope'    => 'https://mail.google.com',
    'authorize_url_parameters' => [
            'approval_prompt' => 'force', // to pass only when you need to acquire a new refresh token.
            'access_type' => 'offline'
    ]
];
 
$adapter = new Hybridauth\Provider\Google( $config );

You may have noticed I passed the scope https://mail.google.com which is required to get the access token for Gmail API.

The callback.php file will perform the authorization flow and store the access token in the database table.

<?php
require_once 'config.php';

try {
    $adapter->authenticate();
    $token = $adapter->getAccessToken();
    $db = new DB();
    $db->update_access_token(json_encode($token));
    echo "Access token inserted successfully.";
}
catch( Exception $e ){
    echo $e->getMessage() ;
}

Go to the browser, run the YOUR_DOMAIN_URL/callback.php, complete the authentication and you should get your access token in your google_oauth table.

Send Email using Gmail API in PHP

Once we get the access token, it becomes easy to use Gmail API to send our emails. All we need to do is grab the token from the database, build transport for Symfony Mailer and shoot the emails. Using Symfony Mailer, with the combination of your Google email and access token, your emails will be sent through Gmail API.

In the code below we are doing the following steps.

  • Get the access token from the Database.
  • Setup a transport to use Gmail API.
  • Regenarate access token if expired using a refresh token.
  • Store newly creates access token into the database.
  • Send the Email.
<?php
use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email;

send_email_to_user('ADD_RECIPIENT_EMAIL');

function send_email_to_user($email) {
    require_once 'config.php';

    $db = new DB();
    $arr_token = (array) $db->get_access_token();

    try {
        $transport = Transport::fromDsn('gmail+smtp://'.urlencode('GOOGLE_EMAIL').':'.urlencode($arr_token['access_token']).'@default');

        $mailer = new Mailer($transport);

        $message = (new Email())
            ->from('SENDER_NAME <SENDER_EMAIL>')
            ->to($email)
            ->subject('Email through Gmail API')
            ->html('<h2>Email sent through Gmail API</h2>');

        // Send the message
        $mailer->send($message);

        echo 'Email sent successfully.';
    } catch (Exception $e) {
        if( !$e->getCode() ) {
            $refresh_token = $db->get_refersh_token();

            $response = $adapter->refreshAccessToken([
                "grant_type" => "refresh_token",
                "refresh_token" => $refresh_token,
                "client_id" => GOOGLE_CLIENT_ID,
                "client_secret" => GOOGLE_CLIENT_SECRET,
            ]);
            
            $data = (array) json_decode($response);
            $data['refresh_token'] = $refresh_token;

            $db->update_access_token(json_encode($data));

            send_email_to_user($email);
        } else {
            echo $e->getMessage(); //print the error
        }
    }
}

Make sure to replace the placeholders with their actual values. Here, I used the single parameter of email in the method send_email_to_user. You can change it as per your flow. The basic code would remain the same.

It’s all about sending emails using Gmail API with Symfony Mailer in PHP. Through this approach, you can build a reliable system and avoid using your login credentials directly. Give it a try and share your thoughts and suggestions in the comment section below.

Related Articles

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

9 thoughts on “How to Send Email using Gmail API in PHP

  1. Notice: Undefined property: stdClass::$refresh_token

    Fatal error: Uncaught Hybridauth\Exception\HttpRequestFailedException: Unable to refresh the access token. HTTP error 400. Raw Provider API response: { “error”: “invalid_request”, “error_description”: “Missing required parameter: refresh_token” }

    How to resolve the above issues

  2. i have question
    how to fill this part
    $transport = Transport::fromDsn(‘gmail+smtp://’.urlencode(‘GOOGLE_EMAIL’).’:’.urlencode($arr_token[‘access_token’]).’@default’);
    i have no any idea please help me ..

  3. on the send Email page there is a $adapter->refreshAccessToken <- this stuff, I wrote everything what you coded. However, the adapter is the undefined variable. I need some help on that one.
    Thanks a lot

    1. 15. urlencode(‘GOOGLE_EMAIL’) should change GOOGLE_EMAIL to the email address you activated the API on.
      20. ->from(‘SENDER_NAME ‘) change SENDER_EMAIL to the same old email address

    1. Technically, if it’s working on a local server, it should be working on a live server. Did you turn on PHP debug mode? It gives an idea about errors and you can track them.

Leave a Reply

Your email address will not be published.