2013-05-28 6 views
5

Gmail Nachricht getAttachments Funktion Rückkehr inlineImages nicht - siehe Ausgabe 2810 https://code.google.com/p/google-apps-script-issues/issues/detail?id=2810Parsing inlineImages von Gmail Rohinhalt

ich das tun müssen, so schrieb ich den Code unten das Inline-Bild in Blob-Format aus der Nachricht zu analysieren roher Inhalt, im Voraus das Bild cid in der Nachricht zu wissen.

Ich fürchte jedoch, dass dieses Parsing ziemlich zerbrechlich ist, wenn ich das erste und letzte Zeichen im base64-Bildinhalt finde, oder?

Gibt es einen besseren Weg, dies zu tun?

Grüße, Fausto

var rawc = message.getRawContent(); 
var b64c1 = rawc.lastIndexOf(cid) + cid.length + 3; // first character in image base64 
var b64cn = rawc.substr(b64c1).indexOf("--") - 3; // last character in image base64 
var imgb64 = rawc.substring(b64c1, b64c1 + b64cn + 1); // is this fragile or safe enough? 
var imgblob = Utilities.newBlob(Utilities.base64Decode(imgb64), "image/jpeg", cid); // decode and blob 

Antwort

6

Ich habe dieses Problem einige Male hatte, und ich glaube, ich habe eine ziemlich allgemeine Fall Lösung. Nicht eingebettete Bilder zu bekommen war ebenfalls ein Problem.

Ich bin mir nicht sicher, ob meine Analyse fragiler ist als deine. Am Ende sauge ich den Teil des multipart heraus, indem ich die umgebenden Linien ergreife, die mit '--' beginnen. Alles andere stellt nur sicher, dass ich das verwenden kann, ohne den Code zu sehr zu ändern, wenn ich ihn als nächstes brauche. Ich hatte einige E-Mails, die nicht auf die \r\n folgen und Probleme verursachen: etwas, auf das man achten sollte.

Die Funktion getInlineImages übernimmt den unformatierten Inhalt der Nachricht und gibt ein Array von Objekten zurück. Jedes Objekt wird den src des img-Tags und den zum Bild gehörenden Blob enthalten. Wenn Sie nur Inline-Bilder haben wollen, können Sie wählen, alles zu ignorieren, das nicht mit 'cid' beginnt.

Die Funktion getBlobFromMessage übernimmt den unformatierten Inhalt der Nachricht und die Quelle des img-Tags (einschließlich 'cid') und gibt das zugehörige Blob zurück.

Sie können den Code kommentiert here sehen.

function getInlineImages(rawContent) { 
    var url = /^https?:\/\//, cid = /^cid:/; 
    var imgtags = rawContent.match(/<img.*?>(.*?<\/img>)?/gi); 
    return imgtags ? imgtags.map(function(imgTag) { 
    var img = {src: Xml.parse(imgTag,true).html.body.img.src}; 
    img.blob = url.test(img.src) ? UrlFetchApp.fetch(img.src).getBlob() 
      : cid.test(img.src) ? getBlobFromMessage(rawContent,img.src) 
      : null; 
    return img; 
    }) : []; 
} 

function getBlobFromMessage(rawContent,src) { 
    var cidIndex = src.search(/cid:/i); 
    if(cidIndex === -1) throw Utilities.formatString("Did not find cid: prefix for inline refenece: %s", src) 

    var itemId = src.substr(cidIndex + 4); 
    var contentIdIndex = rawContent.search("Content-ID:.*?" + itemId); 
    if(contentIdIndex === -1) throw Utilities.formatString("Item with ID %s not found.",src); 

    var previousBoundaryIndex = rawContent.lastIndexOf("\r\n--",contentIdIndex); 
    var nextBoundaryIndex = rawContent.indexOf("\r\n--",previousBoundaryIndex+1); 
    var part = rawContent.substring(previousBoundaryIndex,nextBoundaryIndex); 

    var contentTransferEncodingLine = part.match(/Content-Transfer-Encoding:.*?\r\n/i)[0]; 
    var encoding = contentTransferEncodingLine.split(":")[1].trim(); 
    if(encoding != "base64") throw Utilities.formatString("Unhandled encoding type: %s",encoding); 

    var contentTypeLine = part.match(/Content-Type:.*?\r\n/i)[0]; 
    var contentType = contentTypeLine.split(":")[1].split(";")[0].trim(); 

    var startOfBlob = part.indexOf("\r\n\r\n"); 
    var blobText = part.substring(startOfBlob).replace("\r\n",""); 
    return Utilities.newBlob(Utilities.base64Decode(blobText),contentType,itemId); 
} 
+0

Dies könnte weiter verbessert werden, um die mehrteilige Grenze zu verwenden, anstatt nur nach dem '-' am Anfang einer Zeile zu suchen. – fooby