6

I'm looking to write a PHP script that scans my gmail inbox, and reads unread emails. There needs to be NO user interaction. This has to happen on a cronjob that executes a PHP file.

Is this even possible with the API? Googles documentation is absolutely terrible, and no-where does there seems to be any examples that allow you to authorize a log in programatically. They always require a user to physically press the allow button on an oauth request.

Has anybody got experience in trying to simply login and list your messages, without the need of human interaction?

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
simonw16
  • 960
  • 9
  • 25
  • 1
    you should be using the imap functions for this https://www.php.net/manual/en/ref.imap.php –  May 13 '19 at 23:30
  • Possible duplicate of [accessing my gmail inbox via php code](https://stackoverflow.com/questions/1385797/accessing-my-gmail-inbox-via-php-code) –  May 13 '19 at 23:30
  • A refresh token should last indefinitely or until the access has been revoked, according to their documentation - https://developers.google.com/gmail/api/auth/web-server – tshimkus May 13 '19 at 23:32
  • I looked at the API docs for gmail and they were almost unreadable. It took me over 3 hours to figure out I needed a service account, what a service account was, and that it didn't work with personal gmail accounts. Will be using imap for sure! – simonw16 May 14 '19 at 00:26
  • Being your own account, Imap is definitely the best option. –  May 14 '19 at 03:28

2 Answers2

5

client login

I think what you are trying to ask here is how to login to the api using your login and password. The anwser is you cant this was called client login and google shut down that option in 2015. You have not choice but to use the Oauth2 if you want to connect to the gmail api

service accounts

Normally i would say that you should use a service account. However service accounts only work with gmail if you have a gsuite account in which case you can set up domain wide delegation's here

// Load the Google API PHP Client Library.
require_once __DIR__ . '/vendor/autoload.php';
// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');
/**
 * Gets the Google client refreshing auth if needed.
 * Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
 * Initializes a client object.
 * @return A google client object.
 */
function getGoogleClient() {
    return getServiceAccountClient();
}
/**
 * Builds the Google client object.
 * Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
 * Scopes will need to be changed depending upon the API's being accessed. 
 * array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
 * List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
 * @return A google client object.
 */
function getServiceAccountClient() {
    try {   
        // Create and configure a new client object.        
        $client = new Google_Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope([YOUR SCOPES HERE]);
        return $client;
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}

oatuh2

In the event that you are not using gsuite. Then what you can do is authenticate your code once. Make sure to request off line access. A refresh token will be returned to you. If you save this refresh token you can then use that refresh token at anytime to request a new access token. In the example below you can see how the refresh token was simply stored in a session varable you could store it in a file and read from that when ever you need.

function getOauth2Client() {
    try {

        $client = buildClient();

        // Set the refresh token on the client. 
        if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
            $client->refreshToken($_SESSION['refresh_token']);
        }

        // If the user has already authorized this app then get an access token
        // else redirect to ask the user to authorize access to Google Analytics.
        if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

            // Set the access token on the client.
            $client->setAccessToken($_SESSION['access_token']);                 

            // Refresh the access token if it's expired.
            if ($client->isAccessTokenExpired()) {              
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $client->setAccessToken($client->getAccessToken()); 
                $_SESSION['access_token'] = $client->getAccessToken();              
            }           
            return $client; 
        } else {
            // We do not have access request access.
            header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
        }
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}

code ripped from Oauth2Authentication.php

smtp

You mentioned that you want to use the gmail api but have you considered going directly though the mail server? This would allow you to use login and password. or oauth -> Imap-smtp

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • This is very helpful. I've opted to use imap for ease. I think our company has a GSuite account and my email address would be part of that so I can probably go with that option should I wish to. Annoyingly, I was able to get similar code written, but whenever I tried to access anything in the Gmail library I got 400 Bad Request errors. Every time. I've never figured out why. I had the correct creds file and link to creds when setting up `useApplicationDefaultCredentials()` and my scopes were set up for gmail READONLY – simonw16 May 14 '19 at 18:28
  • 1
    the service account needs to be configured by the gsuite admin – Linda Lawton - DaImTo May 14 '19 at 20:33
0

You need to use three-legged OSuth, that is OAuth where the end-user (owner of the gmail account), logs in and authorizes your app to read their email. There is no other way to access a user's Gmail account via the API except with three-legged OAuth.

The end user needs to click on the first time. Once your app has received consent from the end user, the app can access the Gmail API on behalf of the user in the future without clicks. I find this documentation the clearest, look for grantOfflineAccess().

You could copy and paste a simple JavaScript Frontend from the documentation that allows you to do the log in, and write your backend logic in PHP.

user835611
  • 2,309
  • 2
  • 21
  • 29
  • OP, said "my" account so may as well just use imap, no need to use OAuth etc –  May 14 '19 at 03:27