简体   繁体   中英

Gmail API - PHP - Sending email using service account

The Problem: I'm stuck with an HTTP 400 error that states "Precondition check failed." whenever I call the sendMessage() method.

I don't know what it can be considering that I have:

  1. Enabled Gmail API.
  2. Created a service account.
  3. Set up domain-wide delegation (for G-Suites).
  4. Enabled domain-wide delegation for the service.

As a note, I've successfully run quickstart.php so I know that the google library is installed correctly. Below is my code:

<?php
 require_once('../../vendor/autoload.php');

$client = new Google_Client();
$credentials_file = '../../vendor/google/auth/credentials.json';

$client->setAuthConfig($credentials_file);
$client->setApplicationName("no-reply mailing");
$client->setScopes(['https://www.googleapis.com/auth/gmail.send']);
$service = new Google_Service_Gmail($client);
$message = createMessage('me', 'some@email.com', 'This is but a test', 'Please work...');

// Email a user
sendMessage($service, 'me', $message);

/**
* @param $sender string sender email address
* @param $to string recipient email address
* @param $subject string email subject
* @param $messageText string email text
* @return Google_Service_Gmail_Message
*/
function createMessage($sender, $to, $subject, $messageText) {
 $message = new Google_Service_Gmail_Message();

 $rawMessageString = "From: <{$sender}>\r\n";
 $rawMessageString .= "To: <{$to}>\r\n";
 $rawMessageString .= 'Subject: =?utf-8?B?' . base64_encode($subject) . "?=\r\n";
 $rawMessageString .= "MIME-Version: 1.0\r\n";
 $rawMessageString .= "Content-Type: text/html; charset=utf-8\r\n";
 $rawMessageString .= 'Content-Transfer-Encoding: quoted-printable' . "\r\n\r\n";
 $rawMessageString .= "{$messageText}\r\n";

 $rawMessage = strtr(base64_encode($rawMessageString), array('+' => '-', '/' => '_'));
 $message->setRaw($rawMessage);
 return $message;
}

function sendMessage($service, $userId, $message) {
  try {
    $message = $service->users_messages->send($userId, $message);
    print 'Message with ID: ' . $message->getId() . ' sent.';
    return $message;
  } catch (Exception $e) {
    print 'An error occurred: ' . $e->getMessage();
  }
}
?>

Any help is greatly appreciated!

I contacted Google support for this and they've solved my issue!

Here's what I was told in the email from support: "You must impersonate the user on the code to be able to call the Gmail API with the Service Account." So the "Precondition check failed." error was caused by not authenticating properly.

So for completeness, I'll run through the process you must go through to allow your code to work. Note that you will need three things: G-Suites, access to the Google developer console and access to the G-Suites admin console.

Requirements before you start coding.

  1. Get the Google Client Library (Ensure that php is in your system's path > Install Composer > Install the library composer require google/apiclient:^2.0 )
  2. Enable Gmail API ( Google Developer console > Library > Search 'Gmail API' > Enable (if already enabled, you'll see the manage button)
  3. Create Service Account ( Google Developer console > IAM & Admin > Service Accounts > Click 'Create Service Account' > Fill in Step 1 as usual > For Step 2, I set my service account as project owner. > Step 3 I skipped.)
  4. Create a key ( Google Developer console > IAM & Admin > Service Accounts > Click on the 'Actions' menu for your newly created service account > Create Key > JSON > Store this in a spot that your code can access.)
  5. Set up domain-wide delegation ( Google Admin > Security > API Permissions > Scroll all the way down to find 'Manage Domain-wide Delegation' > Click 'Add New' > Enter the Client ID found in the json file you just downloaded > Enter in the scopes you need. For sending emails through gmail, look under 'Authorization' here .)
  6. Enable domain-wide delegation ( Google Developer console > IAM & Admin > Service Accounts > Click on newly created service account > Click 'Edit' > Show Domain-wide Delegation > Enable G-Suite Domain-wide Delegation)

If you have followed and completed these steps, you are all set to continue to the code portion!

The code itself.

<?php
// Library obtained from https://developers.google.com/gmail/api/quickstart/php
require_once('../../vendor/autoload.php');

// Some user within your G-Suites domain
$user_to_impersonate = "your@domain.com";

$sender = $user_to_impersonate;
$to = 'another@domain.com';
$subject = 'The subject of an email.';
$messageText = 'Finally this works!';

// The path to your service account credentials goes here.
putenv("GOOGLE_APPLICATION_CREDENTIALS=credentials.json");
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setSubject($sender);
$client->setApplicationName("Quickstart");
$client->setScopes(["https://mail.google.com/",
                    "https://www.googleapis.com/auth/gmail.compose",
                    "https://www.googleapis.com/auth/gmail.modify",
                    "https://www.googleapis.com/auth/gmail.send"]);
$service = new Google_Service_Gmail($client);

// Main Process
try {
  $msg = createMessage($sender, $to, $subject, $messageText);
  sendMessage($service, $sender, $msg);
} catch (Exception $e) {
  print "An error occurred: " . $e->getMessage();
}

function sendMessage($service, $sender, $msg) {
  $service->users_messages->send($sender, $msg);
}

function createMessage($sender, $to, $subject, $messageText) {
  $rawMsgStr = "From: <{$sender}>\r\n";
  $rawMsgStr .= "To: <{$to}>\r\n";
  $rawMsgStr .= 'Subject: =?utf-8?B?' . base64_encode($subject) . "?=\r\n";
  $rawMsgStr .= "MIME-Version: 1.0\r\n";
  $rawMsgStr .= "Content-Type: text/html; charset=utf-8\r\n";
  $rawMsgStr .= 'Content-Transfer-Encoding: quoted-printable' . "\r\n\r\n";
  $rawMsgStr .= "{$messageText}\r\n";

  // The message needs to be encoded in Base64URL
  $mime = rtrim(strtr(base64_encode($rawMsgStr), '+/', '-_'), '=');
  $msg = new Google_Service_Gmail_Message();
  $msg->setRaw($mime);
  return $msg;
}
 ?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM