Gmail邮件getAttachments功能未返回内联图片 - 请参阅问题2810 https://code.google.com/p/google-apps-script-issues/issues/detail?id=2810
我需要这样做,所以我编写了下面的代码,以消息原始内容解析blob格式的内嵌图像,事先知道消息中的图像cid。
但是,我觉得这个解析在我找到base64图像内容中的第一个和最后一个字符的方式上非常脆弱,不是吗?
有更好的方法吗?
问候,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
答案 0 :(得分:6)
我已经多次遇到过这个问题了,我想我有一个非常普遍的案例解决方案。获取非嵌入式图像也是一个问题。
我不确定我的解析是否比你的解析更脆弱。最后,我通过抓住以multipart
开头的周围行来吮吸'--'
的部分。其他一切只是确保我可以使用它而不需要在下次需要时修改代码。我收到了一些电子邮件,这些电子邮件似乎没有跟随\r\n
并导致问题:需要注意的事项。
getInlineImages
函数将获取消息的原始内容并返回一个对象数组。每个对象都有img标签的src和与图像一起的blob。如果您只想要内嵌图像,则可以选择忽略任何不以“cid”开头的内容。
getBlobFromMessage
函数将获取消息的原始内容和img标记的src(包括'cid')并返回关联的blob。
您可以看到评论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);
}
答案 1 :(得分:0)
针对此问题的最新方法。
问题
例如,这是使用.getBody()
检索的电子邮件正文<div dir="ltr"><div><img src="?view=att&th=1401f70d4881e07f&attid=0.3&disp=emb&realattid=ii_1401f6fc7824ebe1&zw&atsh=1" alt="Inline image 4" width="200" height="180"><br></div><div><br></div><img src="?view=att&th=1401f70d4881e07f&attid=0.2&disp=emb&realattid=ii_1401f6e6c1d46c4b&zw&atsh=1" alt="Inline image 2" width="200" height="65"><div><br></div><div>
jtykuykyu</div><div><br></div><div><img src="?view=att&th=1401f70d4881e07f&attid=0.1&disp=emb&realattid=ii_1401f6e9df3a4b1c&zw&atsh=1" alt="Inline image 3" width="200" height="82"><br><div><br></div><div><br></div></div></div>
以下是电子邮件的附件列表(其中包括我们的内联图片):
[13-07-30 08:28:08:378 CEST]截图2013-07-12 at 1.54.31 PM.png
[13-07-30 08:28:08:379 CEST]截图2013-07-23 at 5.38.51 PM.png
[13-07-30 08:28:08:380 CEST]截图2013-07-25 at 9.05.15 AM.png
[13-07-30 08:28:08:381 CEST] test2.png
正如您所看到的,这些图片的名称与img标签中提供的信息之间没有任何关联,因此没有安全的方法来重建只包含这些信息的正确电子邮件。
解决方案
如何解决?我们可以使用方法.getRawContent()来获取实际的电子邮件并解析它以获取我们需要的信息。具体来说,这种方法为我们提供了一个附件名称和“realattid”之间的关系。可在电子邮件正文中找到:
内容类型:image / png; name =&#34; Screen Shot 2013-07-25 at 9.05.15 AM.png&#34;
Content-Transfer-Encoding:base64
Content-ID:
X-Attachment-Id:ii_1401f6e9df3a4b1c
代码段
这是一个代码段:
- 检查身体和身体电子邮件的附件
- 获取正文中的所有img标记,并查看哪些标记链接到电子邮件中的附件
- 获得&#39; realattid&#39;每个图像的使用.getRawContent()来链接这个&#39; realattid&#39;正确的附件
- 更换img标签以正确将其链接到正确的附件
- 表示此附件不再是简单附件,而是内嵌图像
- 完成所有操作后,您将获得发送此电子邮件副本所需的所有数据,并显示正确的内嵌图像。
//////////////////////////////////////////////////////////////////////////////
// Get inline images and make sure they stay as inline images
//////////////////////////////////////////////////////////////////////////////
var emailTemplate = selectedTemplate.getBody();
var rawContent = selectedTemplate.getRawContent();
var attachments = selectedTemplate.getAttachments();
var regMessageId = new RegExp(selectedTemplate.getId(), "g");
if (emailTemplate.match(regMessageId) != null) {
var inlineImages = {};
var nbrOfImg = emailTemplate.match(regMessageId).length;
var imgVars = emailTemplate.match(/<img[^>]+>/g);
var imgToReplace = [];
if(imgVars != null){
for (var i = 0; i < imgVars.length; i++) {
if (imgVars[i].search(regMessageId) != -1) {
var id = imgVars[i].match(/realattid=([^&]+)&/);
if (id != null) {
var temp = rawContent.split(id[1])[1];
temp = temp.substr(temp.lastIndexOf('Content-Type'));
var imgTitle = temp.match(/name="([^"]+)"/);
if (imgTitle != null) imgToReplace.push([imgTitle[1], imgVars[i], id[1]]);
}
}
}
}
for (var i = 0; i < imgToReplace.length; i++) {
for (var j = 0; j < attachments.length; j++) {
if(attachments[j].getName() == imgToReplace[i][0]) {
inlineImages[imgToReplace[i][2]] = attachments[j].copyBlob();
attachments.splice(j, 1);
var newImg = imgToReplace[i][1].replace(/src="[^\"]+\"/, "src=\"cid:" + imgToReplace[i][2] + "\"");
emailTemplate = emailTemplate.replace(imgToReplace[i][1], newImg);
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
var message = {
htmlBody: emailTemplate,
subject: selectedTemplate.getSubject(),
attachments: attachments,
inlineImages: inlineImages
}