【问题标题】:How to send a reply to an mail using Gmail API如何使用 Gmail API 回复电子邮件
【发布时间】:2016-11-25 07:29:16
【问题描述】:

我正在使用 gmail API 发送电子邮件。在此发送已成功完成。我想知道如何使用 php 回复那个人(已经发送)。

这里附上我的发送代码:

$line = "\n";
$strMailContent = $message;
$strMailTextVersion = strip_tags($strMailContent, '');

$strRawMessage = "";
$boundary = uniqid(rand(), true);
$subjectCharset = $charset = 'utf-8';

$strToMail = $to;

$strSubject = $subject;

$strRawMessage .= 'To: ' . ($strToMail)  . "\r\n";

if(!empty($_POST['cc']) || !empty($_POST['bcc'])){
    $cc = $_POST['cc'];
    $bcc = $_POST['bcc'];
    $strRawMessage .= "Cc: $cc". $line;
    $strRawMessage .= "Bcc: $bcc". $line;
}

$strRawMessage .= 'Subject: =?' . $subjectCharset . '?B?' . base64_encode($strSubject) . "?=\r\n";
$strRawMessage .= 'MIME-Version: 1.0' . "\r\n";
$strRawMessage .= 'Content-type: Multipart/Mixed; boundary="' . $boundary . '"' . "\r\n";



$filePath = $file_tmp_name;
$mimeType =  'text/plain; charset="UTF-8" ';
$fileName = $file_name;
$fileData = base64_encode(file_get_contents($filePath));

$strRawMessage .= "\r\n--{$boundary}\r\n";
$strRawMessage .= 'Content-Type: '. $mimeType .'; name="'. $fileName .'";' . "\r\n";            
$strRawMessage .= 'Content-Description: ' . $fileName . ';' . "\r\n";
$strRawMessage .= 'Content-Disposition: attachment; filename="' . $fileName . '"; size=' . filesize($filePath). ';' . "\r\n";
$strRawMessage .= 'Content-Transfer-Encoding: base64' . "\r\n\r\n";
$strRawMessage .= chunk_split(base64_encode(file_get_contents($filePath)), 76, "\n") . "\r\n";
$strRawMessage .= '--' . $boundary . "\r\n";



$strRawMessage .= $strMailContent;

$mime = rtrim(strtr(base64_encode($strRawMessage), '+/', '-_'), '=');

$base64 = base64_encode($mime);
$data = '{ "raw" : "'.$mime.'" }';
$send = Qassim_HTTP(1, $url, $header, $data);

在这里,我将收件人地址作为已发送的人员邮件 ID 传递,并且主题已使用主题。

如何更改此代码以发送回复。请帮帮我

【问题讨论】:

标签: php gmail-api


【解决方案1】:

您需要传递要回复的消息的线程 ID,并为新消息设置相同的主题。我更喜欢使用一些库来生成消息的原始字符串,而不是手动编写它以尽量减少出错的可能性。下面是一个使用 PHPMailer 的例子。

$gmail = new Google_Service_Gmail($client);
$message = new Google_Service_Gmail_Message();
$optParam = array();
$referenceId = '';
$thread = $gmail->users_threads->get($userId, $threadId);
$optParam['threadId'] = $threadId;
$threadMessages = $thread->getMessages($optParam);
$messageId = $threadMessages[0]->getId();
$messageDetails = $this->getMessageDetails($messageId); //omitted for simplicity: returns prepared message data.
$messageDetails = $messageDetails['data'];
$subject = $messageDetails['headers']['Subject'];
$mail = new PHPMailer();
$mail->CharSet = 'UTF-8';
$mail->From = $from_email;
$mail->FromName = $from_name;
$mail->addAddress($to);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$raw = $this->Base64UrlEncode($mime); //omitted for simplicity: Encodes the data in base 64 format for sending.
$message->setRaw($raw);
$message->setThreadId($threadId);
$response = $gmail->users_messages->send($userId, $message);

userId是登录用户的id,threadId是你要回复的消息的线程id。

我在使用 Google 的 PHP SDK 和缺乏适当的示例时遇到了很多困难,因此我编写了一个 PHP 包装器,它涵盖了 Gmail API 的大部分功能。它涵盖了上面的解释,如果您深入研究它,您会发现上面示例中省略的逻辑。你可以找到它here

【讨论】:

  • 感谢您的回复。以上代码是否需要任何插件或库。
  • 如果您将它与作曲家一起使用,它将自行设置所需的一切。否则,您需要手动执行此操作。它使用 Google 的 PHP SDK 和 PHPMailer。与 composer 一起去加载文件也会更好。
  • 我正在尝试使用此代码发送回复。如何将线程 id 传递给这个 $line = "\n"; $raw = "收件人:$to".$line; if(!empty($_POST['recc']) || !empty($_POST['rebcc'])){ $cc = $_POST['recc']; $bcc = $_POST['rebcc']; $raw .= "抄送:$cc"。 $线; $raw .= "密件抄送:$bcc"。 $线; } $raw .= "主题:$subject".$line.$line; $raw .= $消息; $base64 = base64_encode($raw); $data = '{ "raw" : "'.$base64.'" }'; $send = Qassim_HTTP(1, $url, $header, $data);
  • @trajchevska 我想问题更多是关于:为什么从那里调用这个方法?它需要一个类上下文。我想这是你提到的包装类的一部分。该行至少应该是这样的: $messageDetails = $gmail->users_messages->get($userId, $messageId);之后,当然必须从返回的对象中提取所需的信息。
  • @n.r.嗯,你是对的,答案是 2 岁,我不记得了 :) 如果该部分包含在代码中,它将增加示例的复杂性:它应该替换为已经存在的消息详细信息准备发送。我会添加评论,感谢您注意到这一点!
【解决方案2】:

@trajchevska 的上述回答非常好,我很高兴我找到了它(!) - 但它不会“揭示全部真相”。因此,我尝试将我的见解整合在一起,以创建一个可以按原样工作的 sn-p。

$user = 'me'; // or user@example.com
$emailId = 12301839123180983123;
$from = 'johndoe@foobar.com';
$fromName = 'John Doe';

// this is for first authentification of this app to the Google-universe in general
$client = getClient();

// an this is to actually start working with Gmail
$googleService = new Google_Service_Gmail($client);

try {

    // receive the message body and extract it's headers
    $message = $googleService->users_messages->get($user, $emailId);
    $messageDetails = $message->getPayload();
    $messageHeaders = $messageDetails->getHeaders();

    // get the subject from the original message header
    $subject = 'Re:'.$getMessageHeaderValue($messageHeaders, 'Subject');

    // if you use the from header, this may contain the complete email address like John Doe <john.doe@foobar.com> - phpMailer will not accept that, the tricky thing is: you will not notice it, because it will be left blank and the Gmail API will return an "Recipient address required"
    preg_match('/.*<(.*@.*)>/', $getMessageHeaderValue($messageHeaders, 'From'),$to);

    // now use the PHPMailer to build a valid email-body
    $mail = new PHPMailer();
    $mail->CharSet = 'UTF-8';
    $mail->From = $from;
    $mail->FromName = $fromName;
    $mail->addAddress($to[1]);
    $mail->Subject = $subject;
    $mail->Body = $body;
    // preSend will build and verify the email
    $mail->preSend();

    $mime = $mail->getSentMIMEMessage();
    // the base64-url-encode is important, otherwise you'll receive an "Invalid value for ByteString" error
    $raw = base64url_encode($mime);

    // now use the Gmail-Message object to actually 
    // for me it is not clear, why we cannot use Class Google_Service_Gmail for this
    $message = new Google_Service_Gmail_Message();

    $message->setRaw($raw);

    $message->setThreadId($emailId);

    // and finally provide encoded message and user to our global google service object - this will send the email
    $response = $googleService->users_messages->send($user, $message);

} catch (Exception $e) {

    print($e->getMessage());

}

function getMessageHeaderValue($headers, $headerName) {

        foreach ($headers as $header) {

            if ($header->name == $headerName) {

                return $header->value;

            }
        }

        return NULL;
    }

// this function comes from https://developers.google.com/people/quickstart/php
/**
 * Returns an authorized API client.
 * @return Google_Client the authorized client object
 */
function getClient()
{
    // first get a credentials.json from here:
    // https://console.developers.google.com/apis/
    //
    // if you change scope or before first use, run the script on CLI
    // it will return an URL that you need to call 
    // which will return an access token that you can use for future use
    $client = new Google_Client();
    $client->setApplicationName('Gmail API');

    // see scopes: https://developers.google.com/gmail/api/auth/scopes
    $client->setScopes(array(Google_Service_Gmail::GMAIL_READONLY,Google_Service_GMail::GMAIL_COMPOSE));

    $client->setAuthConfig('credentials.json');

    $client->setAccessType('offline');

    // Load previously authorized credentials from a file.
    $credentialsPath = 'token.json';
    if (file_exists($credentialsPath)) {
        $accessToken = json_decode(file_get_contents($credentialsPath), true);
    } 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);

        // Store the credentials to disk.
        if (!file_exists(dirname($credentialsPath))) {
            mkdir(dirname($credentialsPath), 0700, true);
        }
        file_put_contents($credentialsPath, json_encode($accessToken));
        printf("Credentials saved to %s\n", $credentialsPath);
    }
    $client->setAccessToken($accessToken);

    // Refresh the token if it's expired.
    if ($client->isAccessTokenExpired()) {
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
    }
    return $client;
}

function base64url_encode($mime) {
    return rtrim(strtr(base64_encode($mime), '+/', '-_'), '=');
}

【讨论】:

    猜你喜欢
    • 2017-12-06
    • 2021-04-17
    • 2019-04-08
    • 2018-05-11
    • 2018-07-21
    • 2014-08-27
    • 2018-02-23
    • 2021-01-24
    • 2018-11-03
    相关资源
    最近更新 更多