【问题标题】:Apps Script: Add attachment to a mail mergerApps 脚本:将附件添加到邮件合并
【发布时间】:2021-10-13 08:49:23
【问题描述】:

问题:

在@Cooper 的出色帮助下,我能够使用 html 模板(“emailEinladung.html”)和收件人列表(“terminBestaetige”)优化我的邮件合并脚本。每个收件人都会收到一封基于 html 模板的个性化电子邮件,只要他/她在第 11 列(因此,“K”)中的状态未设置为“EMAIL SENT”。现在我想为每封发送的电子邮件添加一个或多个附件。

尝试的解决方案:

function terminEinladungVersendenWithAttachments() {
  // variables to reference the sheet and its content
  const anrede = 2;
  const nachname = 3;
  const emailAdresse = 5;
  const terminTag = 6;
  const terminUhrzeit = 8;
  const terminURL = 9;
  let emailTemp = HtmlService.createTemplateFromFile('emailEinladung');
  const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("terminBestaetigen");

  // variables for "Betreff" (in English: "subject") coming from the google Sheet named "Vorlagen"
  var wsVorlagen = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Vorlagen");
  var betreff = wsVorlagen.getRange("B1").getValue();

  const sr = 3;//start row of data
  const data = sh.getRange(sr, 1, sh.getLastRow() - sr + 1, 11).getValues();
  data.forEach((row, i) => {
    if (row[10] == "EMAIL NOT SENT YET") {
      emailTemp.anrede1 = (row[anrede]);
      emailTemp.nachname1 = (row[nachname]);
      emailTemp.emailAdresse1 = (row[emailAdresse]);
      emailTemp.terminTag1 = (row[terminTag]);
      emailTemp.terminUhrzeit1 = (row[terminUhrzeit]);
      emailTemp.terminURL1 = (row[terminURL]);
  // including attachements to each email being sent.
      var attachment1 = DriveApp.getFileById("[FILE_ID1]")
      var attachment2 = DriveApp.getFileById("[FILE_ID2]")
      var blob1 = attachment1.getBlob()
      var blob2 = attachment2.getBlob()
      var htmlMessage = emailTemp.evaluate().getContent();
      GmailApp.sendEmail(row[emailAdresse],
        betreff, "Dies ist eine Nachricht im HTML-Format. Sie müßen Ihre Email-Software entsprechend einrichten.",
        { htmlBody: htmlMessage, replyTo: "f.dore@skillgainer.de", attachments: [blob1, blob2]});
      sh.getRange(i + sr, 11).setValue("EMAIL SENT");//stops emails from being sent again
    }
  });
}

问题:

我的脚本有什么需要改进的地方吗?如果是,那将是什么改进?您的脚本会是什么样子?

非常感谢您的帮助。

【问题讨论】:

  • 我能问一下您期望的more efficient的详细信息吗?我能问一下您当前的剧本问题吗?
  • @Tanaike:感谢您与我们联系。该脚本运行良好,因为它可以向我的谷歌表格列表中的每个收件人发送带有附件的电子邮件。但是一旦列表变长(因此,包含超过 500 个收件人!),脚本的执行时间就会变长。这就是问题的原因:有没有办法重新编写脚本,以便它可以运行得更快?谢谢:)
  • 感谢您的回复。在您的脚本中,我认为 blob1blob2 可以排除在循环之外。我认为这样,工艺成本可能会有点低。但是,当发送 500 封电子邮件时,此过程成本会很高。所以我测试了降低这种情况的成本。但不幸的是,我仍然找不到它。这是因为我的技术不好。我对此深表歉意。但是当我找到它时,我想回答它。
  • 我想到了一种解决方法来降低发送电子邮件的流程成本。所以我提出了一个答案作为解决方法。你能确认一下吗?这个方法是我的尝试。所以我不确定这是否是您问题的直接解决方案。我为此道歉。所以请测试我提出的脚本。如果这没有用,我很抱歉。

标签: google-apps-script google-sheets gmail


【解决方案1】:

我相信你的目标如下。

  • 您希望降低脚本的处理成本。

修改点:

  • 当我看到你的脚本时,我认为blob1blob2 可以排除在循环之外。我认为这样一来,流程成本可能会有点低。
  • 但是,当GmailApp.sendEmail循环发送500封邮件时,这个过程成本会很高。我认为这个成本比上述的要大。
  • 为了减少发送 500 封电子邮件的流程成本,在这个答案中,作为一种变通方法,我想建议使用 Gmail API 和批处理请求。但我不确定这是否是您问题的直接解决方案。所以请测试以下脚本。

修改后的脚本如下。

修改脚本:

在你使用这个脚本之前,请先安装a Google Apps Script library of BatchRequest。您可以在here 了解如何安装此库。

还有,please enable Gmail API at Advanced Google services

请设置[FILE_ID1][FILE_ID2]的文件ID。

const convert_ = ({ to, subject, textBody, htmlBody, attachmentfile1, attachmentfile2 }) => {
  const boundary1 = "boundaryboundary001";
  const boundary2 = "boundaryboundary002";
  const mailData = [
    `MIME-Version: 1.0`,
    `To: ${to}`,
    `Subject: =?UTF-8?B?${Utilities.base64Encode(subject, Utilities.Charset.UTF_8)}?=`,
    `Content-Type: multipart/mixed; boundary=${boundary1}`,
    ``,
    `--${boundary1}`,
    `Content-Type: multipart/alternative; boundary=${boundary2}`,
    ``,
    `--${boundary2}`,
    `Content-Type: text/plain; charset=UTF-8`,
    ``,
    textBody,
    `--${boundary2}`,
    `Content-Type: text/html; charset=UTF-8`,
    `Content-Transfer-Encoding: base64`,
    ``,
    Utilities.base64Encode(htmlBody, Utilities.Charset.UTF_8),
    `--${boundary2}--`,
    `--${boundary1}`,
    `Content-Type: image/png; charset=UTF-8; name="sample1.png"`,
    `Content-Transfer-Encoding: base64`,
    ``,
    attachmentfile1,
    `--${boundary1}`,
    `Content-Type: image/png; charset=UTF-8; name="sample2.png"`,
    `Content-Transfer-Encoding: base64`,
    ``,
    attachmentfile2,
    `--${boundary1}--`,
  ].join("\r\n");
  return Utilities.base64EncodeWebSafe(mailData);
};

// Please run this function.
function terminEinladungVersendenWithAttachments() {
  const anrede = 2;
  const nachname = 3;
  const emailAdresse = 5;
  const terminTag = 6;
  const terminUhrzeit = 8;
  const terminURL = 9;
  let emailTemp = HtmlService.createTemplateFromFile('emailEinladung');
  const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("terminBestaetigen");
  var wsVorlagen = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Vorlagen");
  var betreff = wsVorlagen.getRange("B1").getValue();
  const sr = 3;
  const data = sh.getRange(sr, 1, sh.getLastRow() - sr + 1, 11).getValues();
  var attachmentfile1 = Utilities.base64Encode(DriveApp.getFileById("[FILE_ID1]").getBlob().getBytes());
  var attachmentfile2 = Utilities.base64Encode(DriveApp.getFileById("[FILE_ID2]").getBlob().getBytes());

  var {requests, sent} = data.reduce((o, row, i) => {
    if (row[10] == "EMAIL NOT SENT YET") {
      emailTemp.anrede1 = (row[anrede]);
      emailTemp.nachname1 = (row[nachname]);
      emailTemp.emailAdresse1 = (row[emailAdresse]);
      emailTemp.terminTag1 = (row[terminTag]);
      emailTemp.terminUhrzeit1 = (row[terminUhrzeit]);
      emailTemp.terminURL1 = (row[terminURL]);
      var htmlMessage = emailTemp.evaluate().getContent();
      const obj = {
        to: row[emailAdresse],
        subject: betreff,
        textBody: "Dies ist eine Nachricht im HTML-Format. Sie müßen Ihre Email-Software entsprechend einrichten.",
        htmlBody: htmlMessage,
        attachmentfile1, attachmentfile2
      };
      o.requests.push({method: "POST", endpoint: "https://gmail.googleapis.com/gmail/v1/users/me/messages/send", requestBody: { raw: convert_(obj) }});
      o.sent.push("K" + (i + 3));
    }
    return o;
  }, {requests: [], sent: []});
  if (sent.length > 0) sh.getRangeList(sent).setValue("EMAIL SENT");
  const res = BatchRequest.EDo({ batchPath: "batch/gmail/v1", accessToken: ScriptApp.getOAuthToken(), requests: requests });
  console.log(res)
}

注意:

  • 这个方法是我的尝试。所以请测试上面的脚本。

参考资料:

【讨论】:

  • 非常感谢您为我指明了正确的方向。我问了一个关于不同问题的新问题。你介意看看吗?这是链接:stackoverflow.com/questions/69613959/…。非常感谢提前!!!
  • @Bob Hardball 感谢您的回复。我很高兴你的问题得到了解决。关于你的新问题,我想检查一下。当我找到解决方案时,我想回答它。
猜你喜欢
  • 1970-01-01
  • 2022-11-16
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
相关资源
最近更新 更多