1

我正在修改 Google Apps 脚本中的邮件合并项目。我面临的问题是如何使电子邮件正文显示内联图像。目前,在调用 GmailApp.sendEmail() 后,原始电子邮件模板中存在的所有内联图像都显示为附件。

我的猜测是,如果我找到某种方法将 imgVars 数组转换为这样的 JSON 对象(取自GAS 文档中的示例),则可以显示内联图像:

  MailApp.sendEmail(
    "sg.appsscript@gmail.com",
    "Logos",
    "", 
    { htmlBody: 
      "inline Google Logo<img src='cid:googleLogo'> images! <br/> inline YouTube Logo   <img src='cid:youTubeLogo'>",
     inlineImages: 
     { googleLogo: googleLogoBlob,
       youTubeLogo: youtTubeLogoBlob
     }
    }
  );

所以我想做的是像这样转换一个数组:

var array = { item1, item2, item3 };

对于这样的 JSON 对象:

var json = { item1Name: item1,
             item2Name: item2,
             item3Name: item3
           };

这是我正在处理的邮件合并的代码片段:

  //---------------------------------------------------------------
  // If there are inline images in the body of the email
  // Find them and store them in an array, imgVars
  //---------------------------------------------------------------
  if(emailTemplate.search(/<\img/ != -1)) {  
  var inlineImages = {};

  // Extract all images from the email body
  var imgVars = emailTemplate.match(/<img[^>]+>/g);

  // For each image, extract its respective title attribute
  for (i in imgVars) {
    var title = imgVars[i].match(/title="([^\"]+\")/);
    if (title != null) {
    title = title[1].substr(0, title[1].length-1);
    for (j in attachments) {
       if (attachments[j].getName() == title) {
        inlineImages[title] = attachments[j].copyBlob();
        attachments.splice(j,1);
       }
    }
    var newImg = imgVars[i].replace(/src="[^\"]+\"/,"src=\"cid:"+title+"\"");
    emailTemplate = emailTemplate.replace(imgVars[i],newImg);
    }
  }
 }

 objects = getRowsData(dataSheet, dataRange);
 for (var i = 0; i < objects.length; ++i) {   
   var rowData = objects[i];
   if(rowData.emailSent != "EMAIL_SENT") {

     // Replace markers (for instance ${"First Name"}) with the 
     // corresponding value in a row object (for instance rowData.firstName).

     var emailText = fillInTemplateFromObject(emailTemplate, rowData);     
     var emailSubject = fillInTemplateFromObject(selectedTemplate.getSubject(), rowData);

     GmailApp.sendEmail(rowData.emailAddress, emailSubject, emailText,
                      {name: e.parameter.name, 
                       attachments: attachments, 
                       htmlBody: emailText, 
                       cc: cc, 
                       bcc: bcc, 
                       inlineImages: inlineImages});      
4

3 回答 3

1

一些评论:

> var array = { item1, item2, item3 };

这在语法上是不正确的,数组文字应该是:

var array = [ item1, item2, item3 ];

[...]

> if (emailTemplate.search(/<\img/ != -1)) {

前面的反斜杠img是不必要的,模式应该更好地使用尾随空格并且不区分大小写(因为 HTML 不区分大小写并且通常以大写字母显示标签名称),所以/<img /i

> var imgVars = emailTemplate.match(/<img[^>]+>/g);

用正则表达式解析 HTML 不是一个好主意,最好将 HTML 转换为文档片段并处理它。

>  var imgVars = emailTemplate.match(/<img[^>]+>/g);

注意String.prototype.match返回一个数组。

> for (i in imgVars) {

出于多种原因,不建议将 for..in 与数组一起使用,例如成员可能不会以任何特定顺序返回(在不同的浏览器中可能会有所不同),并且 for..in 将返回数组的所有可枚举属性数组和它[[Prototype]],所以如果你在一个已经Array.prototype被“垫片”或“猴子补丁”修改过的浏览器中,那么这些属性也将被枚举,所以:

> var title = imgVars[i].match(/title="([^\"]+\")/);

很可能试图在其值为对函数的引用的属性上调用match并因此引发错误。至少应该包含一个hasOwnProperty测试,但最好只使用一个普通的 for 循环。

> for (j in attachments) {

似乎附件也是一个数组,因此出于与上述相同的原因,此处也使用普通的 for 循环。将 for..in (可能以意外顺序访问属性)与splice一起使用也不是一个好主意,这表明您期待特定的顺序。请注意,在某些浏览器中,for..in 将按照数组成员添加到数组的顺序访问数组成员,而不是按数字顺序。其他浏览器将始终以特定顺序访问数字属性,而其他浏览器则不会。

如果将 HTML 转换为文档片段,其中大部分会简单得多,然后可以使用 DOM 方法提取 img 元素并访问它们的属性以构建对象。然后,如果需要,可以使用本机方法将对象转换为 JSON。

于 2012-08-01T01:02:42.463 回答
1

100% 保真度来自草稿或预设响应是完全可行的。此代码片段来自我扩展以支持内联图像(嵌入的 blob 和外部引用)和附件的工作邮件合并:

...
//selectedTemplate is a Gmail Message (draft/canned response) 
var emailTemplate = selectedTemplate.getBody(); 
var attachments = selectedTemplate.getAttachments();
var to = selectedTemplate.getTo();
var cc = selectedTemplate.getCc();
var bcc = Session.getActiveUser().getEmail();

if(emailTemplate.search(/<\img/ != -1)){  
    var inlineImages = {};
    var imgVars = emailTemplate.match(/<img[^>]+>/g);
    for(i in imgVars){
      var title = imgVars[i].match(/title="([^\"]+\")/);
      if (title) {
        title = title[1].substr(0, title[1].length-1);
        var titleEncoded = title.replace(/ /g,"-");
        for(j in attachments){
          if(attachments[j].getName() == title){
            inlineImages[titleEncoded] = attachments[j].copyBlob().setName(titleEncoded);
            attachments.splice(j,1);
          }
        }
        var newImg = imgVars[i].replace(/src="[^\"]+\"/,"src=\"cid:"+titleEncoded+"\"");
        emailTemplate = emailTemplate.replace(imgVars[i],newImg);
      }
    }
  }
...
GmailApp.sendEmail(....,
                  {attachments: attachments, ...,
                   inlineImages: inlineImages});

我每天都在与域用户一起工作。希望这可以帮助。

于 2012-08-02T01:31:23.707 回答
0

不幸的是,内嵌图像没有标题。它们有一个 alt=Inline Image 1,但这与附件的名称不同。img 标签中的唯一项目是 alt 和 src。

鉴于此,除了希望第一个内联图像是第一个附件等之外,似乎没有任何方法可以将内联图像与附件联系起来。

我应该注意,我正在使用 Gmail 网络界面来创建草稿,并通过“插入图像”实验室插入图像。

于 2012-08-03T22:34:39.157 回答