GMail Api throws 400 Precondition failed using a service account

Created on 23 January 2023, over 1 year ago
Updated 24 January 2023, over 1 year ago

Can someone explain what I might be missing here. This is using a service account to retrieve a list email messages from the gmail api. To be clear, the Google side is setup correctly, the credential package works with both a D7 version I wrote using the PHP Google client and a Nodejs version. The Google API PHP Client module gets a token as well it's when making the call to $gmail->users_messages->listUsersMessages the error is happening. The response is the good ole 400: Precondition check failed:

  "error": {
    "code": 400,
    "message": "Precondition check failed.",
    "errors": [
      {
        "message": "Precondition check failed.",
        "domain": "global",
        "reason": "failedPrecondition"
      }
    ],
    "status": "FAILED_PRECONDITION"
  }

I can't figure out if I'm missing something in the setup or what. I've tried with two different service accounts, once that has been working in D7 for years so I know it's scoped correctly. Pertinent Drupal 9.5.2 & PHP 8.1.14 code is below. Any thoughts?

    $google_api_service_client = \Drupal::entityTypeManager()->getStorage('google_api_service_client')->load('stored_client_id');

    // Get the service.
    $googleService = \Drupal::service('google_api_service_client.client');
    
    // Set the account.
    $googleService->setGoogleApiClient($google_api_service_client);

    $gmailAddress = 'some_user@valid_domain.com';
    // Set optional parameters for the Gmail service
    $optParams = array(
      'labelIds' => 'INBOX',
      'q' => '@uncc.edu',
      'maxResults' => 10,
    );

    try {
      $gmail = new \Google_Service_Gmail($googleService->googleClient);
      $threads = $gmail->users_messages->listUsersMessages($gmailAddress, $optParams);
      dpm($threads);
    }
    catch (Exception $e) {
      ksm($e);
    }
💬 Support request
Status

Closed: won't fix

Version

4.3

Component

Code

Created by

🇺🇸United States RustedBucket

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @RustedBucket
  • 🇮🇳India sadashiv

    Hi,

    I found a similar thing reported at https://stackoverflow.com/questions/34678678/failedprecondition-error-wh...

    Can you try that solution i.e. use

    $client->setConfig('subject', 'you@email.com');
    

    If that solves the problem then report back so that I can think of some solution . I recommend using client_email from the credentials, if that doesn't work then use the account email and update me which one works, or both fail.

    Thanks,
    Sadashiv.

  • 🇺🇸United States RustedBucket

    Yep, that seemed to do the trick. Thanks.

    Below is my altered code. I just added the line $googleService->googleClient->setConfig('subject', $gmailAddress); Based on your find I also found an old issue from 2016 in the google clients issues that talks about it. https://github.com/googleapis/google-api-php-client/issues/891

    Looks like it's an undocumented change to the apis or if it is documented it's buried somewhere. I don't know if it's worth trying to make a "fix" for this vs maybe adding it to the documentation somewhere. Hopefully this is the only gotcha, I started with gmail for what I'm doing because I already had examples that worked. One would think this only applies to the GMail apis but who knows.

    And to answer your question about which email I used, it was the email address I'm trying to impersonate so NOT the one from the api credentials since this is intended to pull emails for a user logged into our Drupal.

    Thanks for the quick response.

    // Would normally be passed into this as a function parameter
    $gmailAddress = 'some_user@valid_domain.com';
    
    $google_api_service_client = \Drupal::entityTypeManager()->getStorage('google_api_service_client')->load('stored_client_id');
    
    // Get the service.
    $googleService = \Drupal::service('google_api_service_client.client');
    
    // Set the account.
    $googleService->setGoogleApiClient($google_api_service_client);
    
    // Define subject for impersonation
    $googleService->googleClient->setConfig('subject', $gmailAddress);
    
    // Set optional parameters for the Gmail service
    $optParams = array(
      'labelIds' => 'INBOX',
      'q' => '@uncc.edu',
      'maxResults' => 10,
    );
    
    try {
      $gmail = new \Google_Service_Gmail($googleService->googleClient);
      $threads = $gmail->users_messages->listUsersMessages($gmailAddress, $optParams);
      dpm($threads);
    }
    catch (Exception $e) {
      ksm($e);
    }
    
  • Status changed to Closed: won't fix over 1 year ago
  • 🇮🇳India sadashiv

    Thanks for updating this info, as you mentioned the email expected is of the end user I can't implement a genarilsed fix and all developers have to handle it in the code.

    Thanks,
    Sadashiv.

Production build 0.69.0 2024