克隆邮件并使用原始“发件人”标头发送邮件

I'm trying to develop a PHP script resting on the Gmail API that would make possible to snooze my messages at a specific time, i.e. archive and un-archive a message at a specific datetime.

Everything is in place and works but a detail, that is I cannot keep the "From" headers of the original message. More specifically:

  1. The ID of the message to snooze is retrieved at a specific time thanks to a CRON job;
  2. Using the message ID, the message in raw format is retrieved and cloned;
  3. The original message is deleted and the cloned message is sent (and received) => This ensures that the email is displayed at the top of the inbox.

Problem: the cloned email is a perfect copy of the original one but the "From" headers which display the email address of the authenticated user, i.e. myself (username@gmail.com).

//[...] object $this->message

private function cloneMail() {

   // GET RAW message
   $this->message->raw = $this->gmail->users_messages->get(
                                        $this->message->user, 
                                        $this->message->id,
                                        array('format'=>'raw')
                                       );

   try {

     // INSERT original message
     $inserted = $this->gmail->users_messages->delete(
                                              $this->message->user,
                                              $this->message->id
                                                 );

        // ONCE DELETED, SEND CLONED EMAIL    
        if ($deleted->getId()) {
            try {
                $this->gmail->users_messages->send(
                                           $this->message->user, 
                                           $this->message->raw
                                           );
                } catch (Exception $e) {
                    // -- Fallback...
                }
          }

    } catch(Exception $e) {}
}

[Updated] Working solution using messages.insert()

private function cloneMail() {

   // GET RAW message
   $this->message->raw = $this->gmail->users_messages->get(
                                        $this->message->user, 
                                        $this->message->id,
                                        array('format'=>'raw')
                                       );

   try {

     // DELETE original message
     $deleted = $this->gmail->users_messages->delete(
                                              $this->message->user,
                                              $this->message->id
                                                 );

        // ONCE DELETED, SEND CLONED EMAIL    
        if ($deleted->getId()) {
            try {
                $this->gmail->users_messages->insert(
                                           $this->message->user, 
                                           $this->message->raw
                                           );
                } catch (Exception $e) {
                    // -- Fallback...
                }
          }

    } catch(Exception $e) {}
}

messages.send() requires that the From: address be under the control of the authenticated user. Use messages.import() instead.

I am successfully using import() and getting thread support.

I had a major issue when I was doing multi-part upload for large messages, though (how I landed on this post) with

"code": 400, "message": "Expected a single 'From' header"

while Import wants you to use raw (base64 encoded message), Google_Http_MediaFileUpload() wants you to use the ASCII version so you have to decode your raw message and do something like:

$ret = $service->users_messages->import( $user, $newMessage, array( 'internalDateSource' => "dateHeader", 'uploadType'=>"multipart" ) );

$media = new Google_Http_MediaFileUpload( $client, $ret, 'message/rfc822', $textMessage, true, $chunkSize );

$media->setFileSize( strlen( $rawMessage ) );

// upload
$status = false;
while( $status == false ) {
        try {
                $status = $media->nextChunk();
        }  catch( Exception $e ) {
                echo "An error occurred: {$e->getMessage()} 
";

                exit();

        }
}

$newMessage has all the metadata including the labels and such but none of the actual data.

Thanks to http://michiel.vanbaak.eu/2016/02/27/sending-big-email-using-google-php-api-client-and-gmail/

I do think that using just import() when we can get away with it is better because it does save on API calls.