使用 gmail-api 和 google-api-php-client 发送电子邮件

Posted

技术标签:

【中文标题】使用 gmail-api 和 google-api-php-client 发送电子邮件【英文标题】:send email using gmail-api and google-api-php-client 【发布时间】:2014-09-16 10:30:26 【问题描述】:

我正在使用https://github.com/google/google-api-php-client,我想使用用户的授权 gmail 帐户发送测试电子邮件。

这是我目前所拥有的:

$msg = new Google_Service_Gmail_Message();  
$msg->setRaw('gp1');  
$service->users_messages->send('me', $msg);  

这会导致退回电子邮件,因为我不知道如何设置原始邮件。我在经过身份验证的用户的收件箱中看到了退回邮件。我想学习如何为电子邮件的“收件人”、“抄送”、“密送”、“主题”和“正文”设置值。我相信我也需要对这些原始数据进行 64 位编码。我可能想在我的电子邮件正文中使用一些 html

请帮助提供一个的工作示例。

这是收件箱中退回的电子邮件:

Bounce -nobody@gmail.com- 12:58 PM(7 分钟前) 对我来说 发生错误。您的消息未发送。

‚ 日期:2014 年 7 月 24 日星期四 10:58:30 -0700 消息 ID:CABbXiyXhRBzzuaY82i9iODEiwxEJWO1=jCcDM_TH-

【问题讨论】:

【参考方案1】:

我问了a more specific question,这让我得到了答案。我现在正在使用 PHPMailer 来构建消息。然后我从 PHPMailer 对象中提取原始消息。示例:

require_once 'class.phpmailer.php';
$mail = new PHPMailer();
$mail->CharSet = "UTF-8";
$subject = "my subject";
$msg = "hey there!";
$from = "myemail@gmail.com";
$fname = "my name";
$mail->From = $from;
$mail->FromName = $fname;
$mail->AddAddress("tosomeone@somedomain.com");
$mail->AddReplyTo($from,$fname);
$mail->Subject = $subject;
$mail->Body    = $msg;
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$m = new Google_Service_Gmail_Message();
$data = base64_encode($mime);
$data = str_replace(array('+','/','='),array('-','_',''),$data); // url safe
$m->setRaw($data);
$service->users_messages->send('me', $m);

【讨论】:

我还决定将“Sender”、“ReturnPath”和“From”设置为空字符串,因为标头中的 Return-Path 正在我的服务器上自动填充,导致我的字节字符串无效。 刚刚在***.com/questions/25694923/… 和php.net/manual/en/function.base64-encode.php 的帮助下更新了我的答案【参考方案2】:

我也使用过这个解决方案,经过一些调整后效果很好:

创建 PHPMailer 对象时,默认编码设置为 '8bit'。 所以我不得不用以下方式推翻它:

$mail->Encoding = 'base64';

我必须做的另一件事是稍微调整 MIME 以使其 POST 为 Google API 做好准备,我使用了 ewein 的解决方案:

Invalid value for ByteString error when calling gmail send API with base64 encoded < or >

不管怎样,我就是这样解决你的问题的:

//prepare the mail with PHPMailer
$mail = new PHPMailer();
$mail->CharSet = "UTF-8";
$mail->Encoding = "base64";

//supply with your header info, body etc...
$mail->Subject = "You've got mail!";
...

//create the MIME Message
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$mime = rtrim(strtr(base64_encode($mime), '+/', '-_'), '=');

//create the Gmail Message
$message = new Google_Service_Gmail_Message();
$message->setRaw($mime);
$message = $service->users_messages->send('me',$message);

【讨论】:

【参考方案3】:

在本地环境中使用 phpmailer 创建邮件对我来说效果很好。在生产中我收到此错误:

Invalid value for ByteString

要解决这个问题,请删除以下行:

$mail->Encoding = 'base64';

因为邮件被两次编码。

另外,关于其他问题/问题,我发现了下一个:

使用

strtr(base64_encode($val), '+/=', '-_*')

而不是

strtr(base64_encode($val), '+/=', '-_,')

【讨论】:

确切错误:Error calling POST https://www.googleapis.com/gmail/v1/users/me/messages/send: (400) Invalid value for ByteString【参考方案4】:

我用过https://developers.google.com/gmail/api/v1/reference/users/messages/send

并且能够成功发送电子邮件。

【讨论】:

放链接而不是解释是一种不好的风格。请在此处描述解决方案。【参考方案5】:

也许这有点超出最初的问题,但至少在我的情况下,“测试电子邮件”已经发展为定期“从”各个帐户发送自动欢迎电子邮件。虽然我在这里找到了很多有用的东西,但我不得不从各种来源拼凑起来。

为了帮助其他人完成这个过程,这里是我提出的一个提炼版本。

以下代码的几点说明:

    这假设您已经完成了为 Google 服务帐户创建和下载 JSON 的过程(在 developer dashboard 的凭据下,它位于底部。) 为清楚起见,我将您需要在“用您自己的数据替换”部分中设置的所有位进行了分组。 send() 方法中的 me 是一个关键字,意思是“使用当前帐户发送此电子邮件”。
// This block is only needed if you're working outside the global namespace
use \Google_Client as Google_Client;
use \Google_Service_Gmail as Google_Service_Gmail;
use \Google_Service_Gmail_Message as Google_Service_Gmail_Message;

// Prep things for PHPMailer
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;

// Grab the needed files
require_once 'path/to/google-api/vendor/autoload.php';
require_once 'path/to/php-mailer/Exception.php';
require_once 'path/to/php-mailer/PHPMailer.php';

// Replace this with your own data
$pathToServiceAccountCredentialsJSON = "/path/to/service/account/credentials.json";
$emailUser = "sender@yourdomain.com"; // the user who is "sending" the email...
$emailUserName = "Sending User's Name"; // ... and their name
$emailSubjectLine = "My Email's Subject Line";
$recipientEmail = "recipient@somdomain.com";
$recipientName = "Recipient's Name";
$bodyHTML = "<p>Paragraph one.</p><p>Paragraph two!</p>";
$bodyText = "Paragraph one.\n\nParagraph two!";

// Set up credentials and client
putenv("GOOGLE_APPLICATION_CREDENTIALS=$pathToServiceAccountCredentialsJSON");
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
// We're only sending, so this works fine
$client->addScope(Google_Service_Gmail::GMAIL_SEND);
// Set the user we're going to pretend to be (Subject is confusing here as an email also has a "Subject"
$client->setSubject($emailUser);

// Set up the service
$mailService = new Google_Service_Gmail($client);

// We'll use PHPMailer to build the raw email (since Google's API doesn't do that) so prep it
$mailBuilder = new PHPMailer();
$mailBuilder->CharSet = "UTF-8";
$mailBuilder->Encoding = "base64";

// Not set up the email you want to send
$mailBuilder->Subject = $emailSubjectLine;
$mailBuilder->From = $emailUser;
$mailBuilder->FromName = $emailUserName;
try 
    $mailBuilder->addAddress($recipientEmail, $recipientName);
 catch (Exception $e) 
    // Handle any problems adding the email address here

// Add additional recipients, CC, BCC, ReplyTo, if desired

// Then add the main body of the email...
$mailBuilder->isHTML(true);
$mailBuilder->Body = $bodyHTML;
$mailBuilder->AltBody = $bodyText;

// Prep things so we have a nice, raw message ready to send via Google's API
try 
    $mailBuilder->preSend();
    $rawMessage = base64_encode($mailBuilder->getSentMIMEMessage());
    $rawMessage = str_replace(['+', '/', '='], ['-', '_', ''], $rawMessage); // url safe
    $gMessage = new Google_Service_Gmail_Message();
    $gMessage->setRaw($rawMessage);
    // Send it!
    $result = $mailService->users_messages->send('me', $gMessage);
 catch (Exception $e) 
    // Handle any problems building or sending the email here


if ($result->labelIds[0] == "SENT") echo "Message sent!";
else echo "Something went wrong...";

【讨论】:

以上是关于使用 gmail-api 和 google-api-php-client 发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 java 和 google gmail-api 获取收到的邮件? [关闭]

请求 gmail-api 时出现 HttpError 429:超出用户速率限制

如何在 python 中向 Gmail-API 发送批处理请求?

Gmail-api 附带电子邮件时如何收到通知

如何仅为社交电子邮件创建 gmail-api 访问范围

在我们的谷歌云 Pub/Sub 发布者权限之外提供 Gmail-API