Using Gmail API with PHP: Connect to Gmail API Using OAuth 2.0

There’s an official quickstart guide over at Gmail docs for PHP but for some reason they’ve adapted the code to work only on command-line. Lets take a look at how you would achieve the same on a a web application:

Installation

Start with installing the Gmail API through Composer: composer require google/apiclient:^2.0

Generate Gmail API Keys

To generate the keys, create a new project at Google Developer Console

Create google project

Select APIs & Services -> Enabled API & Services from the left pane then click on “Gmail API” once in the APIs section and enable it.

Enable API In Google Console

Enable Gmail API

Click on Create Credentials and fill in the info like so:

Gmail API Info

Fill in other info as well but leave the scope section.

Next, choose the application type as Web application and add one of your local dev URLs under Authorized redirect URIs. Also, remember to update this section for production URLs and remove the dev ones when you deploy so the Gmail API can redirect to your production environment when users authenticate.

Once you’re done, you’ll see your newly created app under OAuth 2.0 Client IDs at Credentials. Click on it and select Download JSON option at the actions bar towards the top.

Connecting to Gmail

Place this credentials.json file somewhere accessible so you can use it in code.

Create a new PHP file say, GmailConnector.php:

<?php

require __DIR__ . '/vendor/autoload.php';

class GmailConnector
{
    public bool $isConnected;
    protected string $credentials;

    public function __construct()
    {
        $this->credentials = "path/of/credentials.json";
        $this->isConnected = false;
        $this->client = $this->createClient();
    }

    public function getClient()
    {
        return $this->client;
    }

    public function getCredentials()
    {
        return $this->credentials;
    }

    public function getUnauthenticatedData()
    {
        $authUrl = $this->client->createAuthUrl();

        echo "<a href='{$authUrl}'>Click here to link your account</a>";
    }

    private function credentialsInBrowser()
    {
        return isset($_GET['code']) ? true : false;
    }

    private function createClient()
    {
        $client = new Google_Client();
        $client->setApplicationName('Gmail API PHP Quickstart');
        $client->setScopes(Google_Service_Gmail::MAIL_GOOGLE_COM);
        $client->setAuthConfig($this->credentials);
        $client->setAccessType('offline');
        $client->setPrompt('select_account consent');

        // Load previously authorized token from a file, if it exists.
        // The file token.json stores the user's access and refresh tokens, and is
        // created automatically when the authorization flow completes for the first
        // time.
        $tokenPath = __DIR__ . "/tokens/token.json";
        if (file_exists($tokenPath)) {
            $accessToken = json_decode(file_get_contents($tokenPath), true);
            $client->setAccessToken($accessToken);
        }

        // If there is no previous token or it's expired.
        if ($client->isAccessTokenExpired()) {
            // Refresh the token if possible, else fetch a new one.
            if ($client->getRefreshToken()) {
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
            } elseif ($this->credentialsInBrowser()) {
                $authCode = $_GET['code'];

                // Exchange authorization code for an access token.
                $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
                $client->setAccessToken($accessToken);

                // Check to see if there was an error.
                if (array_key_exists('error', $accessToken)) {
                    throw new Exception(join(', ', $accessToken));
                }
            } else {
                $this->isConnected = false;

                return $client;
            }
            // Save the token to a file.
            if (!file_exists(dirname($tokenPath))) {
                mkdir(dirname($tokenPath), 0700, true);
            }
            file_put_contents($tokenPath, json_encode($client->getAccessToken()));
        }
        // echo 'not expired';

        $this->isConnected = true;

        return $client;
    }
}

Authenticating through OAuth 2.0

Create another file in the same directory and name it something like GmailAuthenticator.php:

<?php

require __DIR__ . '/vendor/autoload.php';

class GmailAuthenticator
{
    private GmailConnector $connector;

    public function __construct()
    {
        $this->connector = new GmailConnector();

        if (!$this->connector->isConnected) {
            $this->connector->getUnauthenticatedData();
        }
    }

    public function getGmailClient()
    {
        $gmail = $this->connector->getClient();
        return $gmail;
    }
}

Finally, initialize thie authenticator class in your controller or some other file that can be accessed through a URL like so:

$auth = new GmailAuthenticator();
$gmailClient = $auth->getGmailClient();

Make sure that this piece of code is available through some URL and then place the same URL under Authorized redirect URIs.

You may need to redownload the credentials.json file after updating the redirect URIs. An authenticated gmail client should be accessible through $gmailClient variable.