2013-05-28 12 views
5

Gmail funkcja getAttachments wiadomość nie wraca inlineImages - podpunkt 2810 https://code.google.com/p/google-apps-script-issues/issues/detail?id=2810Parsing inlineImages z Gmaila surowej zawartości

muszę tego robić, więc napisałem poniższy kod do analizowania obrazu wbudowany w formacie blob z komunikatem surowa treść, znająca obraz znajdujący się w wiadomości, z góry.

Jednak obawiam się, że to parsowanie jest dość delikatne w sposobie, w jaki znajduję pierwszą i ostatnią postać w treści obrazu base64, czyż nie?

Czy jest lepszy sposób to zrobić?

Pozdrawiam, 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 

Odpowiedz

6

miałem ten problem kilka razy i myślę, że mam dość ogólne rozwiązanie sprawy. Problemem jest także uzyskanie nie osadzonych obrazów.

Nie jestem pewien, czy moje parsowanie jest mniej delikatne niż twoje. W końcu wysysam część multipart, chwytając otaczające linie zaczynające się od '--'. Wszystko inne polega na upewnieniu się, że mogę go użyć bez zbytniego modyfikowania kodu, kiedy będę go potrzebować. Otrzymałem kilka e-maili, które nie wyglądają na zgodne z \r\n i powodują problemy: na co zwrócić uwagę.

Funkcja pobiera surową treść wiadomości i zwraca tablicę obiektów. Każdy obiekt będzie miał src z tagu img i obiektu typu blob związanego z obrazem. Jeśli chcesz tylko obrazy wbudowane, możesz zignorować wszystko, co nie zaczyna się od "cid".

Funkcja getBlobFromMessage pobiera nieprzetworzoną treść wiadomości i src z tagu img (w tym "cid") i zwraca powiązany obiekt typu blob.

Możesz zobaczyć kod skomentowany here.

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

Można to ulepszyć, aby korzystać z wieloczęściowej granicy, zamiast sprawdzać tylko "-" na początku linii. – fooby