2016-05-25 1 views
4

Ich mache eine Anfrage an den Endpunkt User.messages. Alle zurückgegebenen Objekte (die E-Mails) haben eine MimeType-Eigenschaft, die ich kaum verstehen kann.Google Mail-API: Wo finde ich den Hauptteil der E-Mail, je nach MIME-Typ

Genauer gesagt, ich mag der mimt je in die Lage sein, den Körper der E-Mail zu extrahieren, da ich in der Lage gewesen, dass auf dem mime abhängig zu bemerken, ist der Körper in der body Eigenschaft in payload sein wird, oder in das parts Array. Was sind die verschiedenen MimeTypes, die zurückgegeben werden können, und wo finde ich den Hauptteil der E-Mail für jeden von ihnen?

Antwort

5

denke ich, ist es sinnvoll, wenn Sie von der payload als part in sich selbst denken. Lassen Sie uns sagen, dass ich eine Nachricht mit nur einem Thema und einem einfachen Nachrichtentext senden:

From: [email protected] 
To: [email protected] 
Subject: Example Subject 

This is the plain text message 

Dies führt in der folgenden analysiert Nachricht:

{ 
"id": "154ecb53c10b74d8", 
"threadId": "154ecb53c10b74d8", 
"labelIds": [ 
    "INBOX", 
    "SENT" 
], 
"snippet": "This is the plain text message", 
"historyId": "38877", 
"internalDate": "1464260181000", 
"payload": { 
    "partId": "", 
    "mimeType": "text/plain", 
    "filename": "", 
    "headers": [ 
    ... 
    ], 
    "body": { 
    "size": 31, 
    "data": "VGhpcyBpcyB0aGUgcGxhaW4gdGV4dCBtZXNzYWdlCg==" 
    } 
}, 
"sizeEstimate": 355 
} 

Wenn ich eine Nachricht mit einem einfachen Textteil senden, ein hTML-Teil und ein Bild, wird es so aussehen, wenn analysiert:

{ 
"id": "154ed5ccaa12f3df", 
"threadId": "154ed5ccaa12f3df", 
"labelIds": [ 
    "SENT", 
    "INBOX", 
    "IMPORTANT" 
], 
"snippet": "This is a plain/html message with an image.", 
"historyId": "841379", 
"internalDate": "1464271162000", 
"payload": { 
    "mimeType": "multipart/mixed", 
    "filename": "", 
    "headers": [ 
    ... 
    ], 
    "body": { 
    "size": 0 
    }, 
    "parts": [ 
    { 
    "mimeType": "multipart/alternative", 
    "filename": "", 
    "headers": [ 
    { 
     "name": "Content-Type", 
     "value": "multipart/alternative; boundary=089e0122896c7c80d80533bf3205" 
    } 
    ], 
    "body": { 
    "size": 0 
    }, 
    "parts": [ 
    { 
     "partId": "0.0", 
     "mimeType": "text/plain", 
     "filename": "", 
     "headers": [ 
     { 
     "name": "Content-Type", 
     "value": "text/plain; charset=UTF-8" 
     } 
     ], 
     "body": { 
     "size": 47, 
     "data": "VGhpcyBpcyBhIHBsYWluL2h0bWwgKm1lc3NhZ2UqIHdpdGggYW4gaW1hZ2UuDQo=" 
     } 
    }, 
    { 
     "partId": "0.1", 
     "mimeType": "text/html", 
     "filename": "", 
     "headers": [ 
     { 
     "name": "Content-Type", 
     "value": "text/html; charset=UTF-8" 
     } 
     ], 
     "body": { 
     "size": 73, 
     "data": "PGRpdiBkaXI9Imx0ciI-VGhpcyBpcyBhIHBsYWluL2h0bWwgPGI-bWVzc2FnZTwvYj4gd2l0aCBhbiBpbWFnZS48L2Rpdj4NCg==" 
     } 
    } 
    ] 
    }, 
    { 
    "partId": "1", 
    "mimeType": "image/png", 
    "filename": "smile.png", 
    "headers": [ 
     ... 
    ], 
    "body": { 
    "attachmentId": "ANGjdJ-OrSy7VAYL-UbRyNtmySbZLlV-fV43zJF0_neNGZ8yKugsZAxb32eSb-CrbYIhF9NvjGwBVEjSkRrUWoCS7aDpgoQnt9WR7f2sa17qVEyOg_JVSbrGrunirvQw2dY-SxxB3Y0JP3aYDHSBXpNO6fFCByVFWQDw1et5Mh9di7bGO4AWOLKFVe_Yb2RmdDwuazGXGb8zA88TTMaiEPIacPTNiVtBrIWG0EKGxHBhep9j8ujyWeCS5P9X80dBHvBNj4T9XjUwcrN6FvwegRewRMM9cBupY7jQESR7915OcbhCNyi5l64x6vVh1ZU", 
    "size": 2002 
    } 
    } 
    ] 
}, 
"sizeEstimate": 3077 
} 

Sie werden sehen, es ist nur die RFC822-Nachricht analysiert, um JSON

. Wenn Sie nur die parts überqueren und die payload als part selbst behandeln, finden Sie, was Sie suchen.

var parts = [response.payload]; 

while (parts.length) { 
    var part = parts.shift(); 
    if (part.parts) { 
    parts = parts.concat(part.parts); 
    } 

    if(part.mimeType === 'text/html') { 
    var decodedPart = decodeURIComponent(escape(atob(part.body.data.replace(/\-/g, '+').replace(/\_/g, '/')))); 
    console.log(decodedPart); 
    } 
} 
5

Es gibt viele MIME-Typen, die zurückgegeben werden können, sind hier ein paar:

  • text/plain: Der Nachrichtentext nur im Klartext
  • text/html: der Nachrichtentext nur in HTML
  • mehrteiliger/alternative: werden zwei Teile enthalten, die alternativen für jeden othe sind, zum Beispiel:
    • a text/plain Teil für den Nachrichtentext in Klartext
    • a text/html Teil für den Nachrichtentext in HTML
  • multipart/mixed: viele unabhängige Teile enthalten, die sein kann:
    • mehrteiliger/alternative wie oben oder text/plain oder text/html wie oben
    • application/octet-stream oder andere applikation/* für anwendungsspezifische mime types für anlagen
    • image/png ot anderes image/* für bilder, die in die nachricht eingebettet werden könnten.

Die definitive Referenz für all dies ist RFC 2046 https://www.ietf.org/rfc/rfc2046.txt (Sie können auch 2044 und 2045 wollen vielleicht sehen)

Ihre Frage zu beantworten, einen Baum der Nachricht zu bauen, und schauen entweder für :

  • der erste text/plain oder text/html Teil (entweder in dem Nachrichtenkörper oder in einem multipart/mixed)
  • der ersten text/plain oder text/html innerhalb eines mehrteiligen/Alten rnative, die Teil eines mehrteiligen gemischten sein kann.

Ein Beispiel für eine komplexe Nachricht:

  • multipart/mixed

    • mehrteiliger/alternative
      • text/plain < - Nachrichtentext in Klartext
      • text/html < - Nachrichtentext in HTML
    • application/zip < - eine Zip-Datei-Anhang
  • -
+0

Hallo Tony - Vielen Dank für Ihre Antwort. Würden Sie sagen, dass 'text/html' und 'text/plain' die einzigen MimeTypes sind, die direkt Text enthalten? – jgozal

+1

Ja, aber nur der erste. Eine Nachricht könnte einen Text/einfachen Teil und 10 Anhänge Textdateien vom Typ text/plain enthalten. Oder ich könnte eine Nachricht mit multipart/mixed haben, wie oben, aber text/plain attachment statt application/zip. Meine Strategie (wenn ich HTML bevorzuge) ist, nach der ersten multipart/Alternative zu suchen, nach einem HTML-Teil darin zu suchen, wenn nicht gefunden nach einem Textteil darin suchen. Wenn es keine mehrteilige Alternative gibt, suche ich nach dem ersten von entweder einem Text/einfachen Teil oder einem Text/HTML-Teil. Ich benutze zuerst, weil, wenn Sie eine mehrteilige Mischung mit Text und HTML-Anhang haben, wollen Sie Text –

+0

Ja, es ist, was ich auch bemerkt habe. Danke nochmal für deine Hilfe! – jgozal

2

Ich weiß, diese Frage ist nicht neu, aber ich habe einen PHP-Skript geschrieben, das von Google Mail API gezogen Nachrichten korrekt analysiert, einschließlich der Art der Befestigung.

Das Skript enthält eine rekursive "iterateParts" -Funktion, die alle Nachrichtenteile iteriert, so dass wir sicher sein können, dass wir alle verfügbaren Daten aus jeder Nachricht extrahiert haben.

Script Schritte sind:

  1. Pull alle Nachrichten-IDs von API
  2. einige wichtige Header holen (je & von Adresse)
  3. Entweder Körper direkt auf Nutzlast oder Payload iterateParts senden
  4. iterateParts analysiert jede Nachricht zu $ ​​msgArr mit ihren Daten, base64 codiert
  5. Drücken Sie $ msgArr zum Master-Array $ allmsgArr
  6. Traverse Master-Array und jedes Teil als Datei speichern nach ist es MIME-Typ und den Dateinamen
 

    $maxToPull = 1; 
    $gmailQuery = "ALL"; 

    // Initializing Google API 
    $service = new Google_Service_Gmail($client); 

    // Pulling all gmail messages into $messages array 
    $user = 'me'; 
    $msglist = $service->users_messages->listUsersMessages($user, ["maxResults"=>$maxToPull, "q"=>$gmailQuery]); 
    $messages = $msglist->getMessages(); 

    // Master array that will hold all parsed messages data, including attachments 
    $allmsgArr = array(); 

    // Traverse each message 
    foreach($messages as $message) 
    { 
     $msgArr = array(); 
     $single_message = $service->users_messages->get('me', $message->getId()); 
     $payload = $single_message->getPayload(); 

     // Nice to have the gmail msg id, can be used to direct access the message in Gmail's web gui 
     $msgArr['gmailmsgid'] = $message->getId(); 

     // Retrieving the subject and "from" email address 
     foreach($payload->getheaders() as $oneheader) 
     { 
      if($oneheader['name'] == 'Subject') 
       $msgArr['subject'] = $oneheader['value']; 
      if($oneheader['name'] == 'From') 
       $msgArr['fromaddress'] = substr($oneheader['value'], strpos($oneheader['value'], '<')+1, -1); 
     } 

     // If body is directly in the message payload (only for plain text messages where there's no HTML part and no attachments, normally this is not the case) 
     if($payload['body']['size'] > 0) 
      $msgArr['textplain'] = $payload['body']['data'];  
     // Else, iterate over each message part and continue to dig if necessary 
     else 
      iterateParts($payload, $message->getId()); 

     // Push the parsed $msgArr (parsed by iterateParts) to master array 
     array_push($allmsgArr, $msgArr); 
    } 


    // Traverse each parsed message and saving it's content and attachments to files 
    foreach($allmsgArr as $onemsgArr) 
    { 

     $folder = "messages/".$onemsgArr['gmailmsgid']; 
     mkdir($folder); 

     if($onemsgArr['textplain']) 
      file_put_contents($folder."/textplain.txt", decodeData($onemsgArr['textplain'])); 
     if($onemsgArr['texthtml']) 
      file_put_contents($folder."/texthtml.html", decodeData($onemsgArr['texthtml'])); 
     if($onemsgArr['attachments']) 
     { 
      foreach($onemsgArr['attachments'] as $oneattachment) 
      { 
       if(!empty($oneattachment['filename'])) 
        $filename = $oneattachment['filename']; 
       else if($oneattachment['mimetype'] == "message/rfc822" && empty($oneattachment['filename'])) // email attachments 
        $filename = "noname.eml"; 
       else 
        $filename = "unknown"; 
       file_put_contents($folder."/".$filename, decodeData($oneattachment['data'])); 
      } 
     } 
    } 


    function iterateParts($obj, $msgid) { 

     global $msgArr; 
     global $service; 
     foreach($obj as $parts) 
     { 
      // if found body data 
      if($parts['body']['size'] > 0) 
      { 
       // plain text representation of message body 
       if($parts['mimeType'] == 'text/plain') 
       { 
        $msgArr['textplain'] = $parts['body']['data']; 
       } 
       // html representation of message body 
       else if($parts['mimeType'] == 'text/html') 
       { 
        $msgArr['texthtml'] = $parts['body']['data']; 
       } 
       // if it's an attachment 
       else if(!empty($parts['body']['attachmentId'])) 
       { 
        $attachArr['mimetype'] = $parts['mimeType']; 
        $attachArr['filename'] = $parts['filename']; 
        $attachArr['attachmentId'] = $parts['body']['attachmentId']; 

        // the message holds the attachment id, retrieve it's data from users_messages_attachments 
        $attachmentId_base64 = $parts['body']['attachmentId']; 
        $single_attachment = $service->users_messages_attachments->get('me', $msgid, $attachmentId_base64); 

        $attachArr['data'] = $single_attachment->getData(); 

        $msgArr['attachments'][] = $attachArr; 
       }  
      } 

      // if there are other parts inside, go get them 
      if(!empty($parts['parts']) && !empty($parts['mimeType']) && empty($parts['body']['attachmentId'])) 
      { 
       iterateParts($parts->getParts(), $msgid); 
      } 

     } 
    } 

    // All data returned from API is base64 encoded 
    function decodeData($data) 
    { 
     $sanitizedData = strtr($data,'-_', '+/'); 
     return base64_decode($sanitizedData); 
    } 

Dies ist, wie $ allmsgArr aussehen wird (wo nur eine Nachricht gezogen wurde):

 

Array 
(
    [0] => Array 
     (
      [gmailmsgid] => 25k1asfa556x2da 
      [fromaddress] => [email protected] 
      [subject] => Fwd: Sea gulls picture 
      [textplain] => UE5SIDQxQzAwMg0KDQpBUkJFTFRFU1QxDQoNCg0K 
      [texthtml] => PGRpdiBkaXI9Imx0ciI-PHNwYW4gc3R5bGU9ImZi 
      [attachments] => Array 
       (
        [0] => Array 
         (
          [mimetype] => image/png 
          [filename] => sea_gulls.png 
          [attachmentId] => ANGjdJ9tmy4d8vPXhU_BjNEFEaDODOpu29W2u5OTM7a0 
          [data] => iVBORw0KGgoAAAANSUhEUgAABSYAAAKWCAYAAABUP 
         ) 

        [1] => Array 
         (
          [mimetype] => image/jpeg 
          [filename] => Outlook_Signature.jpg 
          [attachmentId] => ANGjdJ-CgZTK0oK44Q8j7TlN_JlaexxGKZ_wHFfoEB 
          [data] => 6jRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEa 
         ) 

       ) 
     ) 
)