Gmail api oauth php

Sending emails using PHP with GMail API & OAuth2

If one ever writes an application that faces the end user, then one requirement is common across such apps, i.e. sending emails to verify email, order confirmation, notifications & updates, the list goes on.

If using PHP, then one is presented with the inbuilt mail() function, to send emails. Again there are downsides to using this (outside the scope of this article) so one moves on to PHPMailer which is an excellent library that will help one in a long way, but there’s a catch:

I used my email & password with SMTP authentication to send emails using PHPMailer, and everything was working just fine. But when I deployed the app to server, the script failed. I had turned on Less Secure App Access from my Google account settings and also clicked on Yes, it was me button when Google sent a notification to my device asking if it was me who tried to sign in from the server. But still no emails were being sent. The reason behind this is that, I had already logged in to the email from the browser of my development machine & hence I had no issues with authorization. Since I hadn’t logged in from server (why would I? & if I wanted to, how would I?) — thus blocking my sign in attempt.

This was the time when I finally decided to let go of PHPMailer and explore the GMail API. Here’s how I did it:

Prerequisite:
  • PHP 5.4 or greater with the command-line interface (CLI) and JSON extension installed
  • The Composer dependency management tool
  • A Google Cloud Platform project with the API enabled.
Sample Code:
Concept:

In Layman’s language, this is the OAuth2 concept:

  1. You ask the user to authorize your application to access their data.
  2. The user logs into their Google account and ‘Approves’ your application.
  3. Google then gives you a ‘access_token’ & a ‘refresh_token’
  4. You have to use the ‘access_token’ as an authorization while calling Google APIs.
  5. But ‘access_token’ is short-lived and is useless after it expires so you need new ‘access_token’
  6. So, you can send your ‘refresh_token’ & keep asking for more ‘access_tokens’
  7. User doesn’t need to authorize again and again until something changes, i.e either you want more data from their account or they change their Google account password, or remove access to your app from their account settings.
Client Library:

To make the above process easy for you to implement, Google provides client libraries that provide an interface for above steps. In case of PHP, the client library is google-api-php-client.

From inside your project directory, run

 composer require google/apiclient:^2.0 

Doing so will add the library to your composer.json and install it in vendor directory.

Читайте также:  Java skip lines in bufferedreader
Credentials:
  • Log in to Google Cloud Console > API & Services >Credentials page and create new OAuth Client ID .
  • Download the Client ID as json and put it in your project directory, renaming it as credentials.json
  • Enter http://localhost/project-path/ as redirect URI when creating the credentials.
  • DO NOT CREATE token.json — it is automatically created by the library.

Finally, code:

 // Refer: https://developers.google.com/gmail/api/quickstart/php // Filename: send_email.php $autoloadPath = "./vendor/autoload.php"; // remember keep credentials & token files outside public_html when deploying $credentialsPath = "credentials.json"; $tokenPath = "token.json"; require $autoloadPath; if (php_sapi_name() != 'cli')  throw new Exception('This application must be run on the command line.'); > /** * Returns an authorized API client. * @return Google_Client the authorized client object */ function getClient()  $client = new Google_Client(); $client->setApplicationName('Gmail API PHP Send Email'); $client->setScopes(Google_Service_Gmail::GMAIL_SEND); $client->setAuthConfig($credentialsPath); $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. 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()); > else  // Request authorization from the user. $authUrl = $client->createAuthUrl(); printf("Open the following link in your browser:\n%s\n", $authUrl); print 'Enter verification code: '; $authCode = trim(fgets(STDIN)); // 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)); > > // Save the token to a file. if (!file_exists(dirname($tokenPath)))  mkdir(dirname($tokenPath), 0700, true); > file_put_contents($tokenPath, json_encode($client->getAccessToken())); > return $client; > // Get the API client and construct the service object. $client = getClient(); $service = new Google_Service_Gmail($client); //The special value **me** can be used to indicate the authenticated user. $user = "me"; $subject = "Test mail using GMail API"; $rawMessage = "From: Sender Name \r\n"; $rawMessage .= "To: Receiver Name \r\n"; $rawMessage .= "Subject: =?utf-8?B?" . base64_encode($subject) . "?=\r\n"; $rawMessage .= "MIME-Version: 1.0\r\n"; $rawMessage .= "Content-Type: text/html; charset=utf-8\r\n"; $rawMessage .= "Content-Transfer-Encoding: quoted-printable" . "\r\n\r\n"; $rawMessage .= "You got this!"; // The message needs to be encoded in Base64URL $mime = rtrim(strtr(base64_encode($rawMessage), '+/', '-_'), '='); $msg = new Google_Service_Gmail_Message(); $msg->setRaw($mime); $service->users_messages->send($user, $msg); ?>

Next, create another file in your project directory that will enable you to collect the authorization code sent by Google upon successful user authentication. Google will send this code to the redirect URI you entered while creating the credentials.

// Filename: index.php > echo $_GET['code']; ?> 

Note that this script runs from the command line & will need modifications to be running as a webpage. Execute this script using:

When you run the script for the first time, you’ll get an authorization link from CLI. Open this link on the browser of your choice & log in to the account you want to send emails from. Remember, this account needs to be the same as the one you entered in the From: field of your email earlier. After logging in & clicking “Approve” you’ll be sent to redirect URI & the code will be displayed on http://localhost/project-path/ assuming you followed above steps.

Paste this code on the CLI & two things will happen:

From the next time onwards you execute the script, you won’t have to follow the same login process again. The access_token and refresh_token will be used by the client library for authorization.

On ending notes, you can also try out PHPMailer Using Gmail with XOAuth2 to combine mail utilities offered by PHPMailer with OAuth from Google API Client.

A web log about programming, software, technology, life and my thoughts in general.

Источник

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 :

 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 "$authUrl>'>Click here to link your account"; > 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 :

 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.

Источник

Оцените статью