Apps 脚本:将附件添加到邮件合并
Apps Script: Add attachment to a mail merger
问题:
在@Cooper 的大力帮助下,我能够使用 html 模板(“emailEinladung.html”)和收件人列表(“terminBestaetige”)优化我的邮件合并脚本。每个收件人都会收到一封基于 html 模板的个性化电子邮件,只要第 11 列(因此,“K”)中的 his/her 状态未设置为“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
}
});
}
问题:
我的脚本有什么地方应该改进以提高效率吗?如果是,那改进是什么?您的脚本会是什么样子?
非常感谢您的帮助。
我相信你的目标如下。
- 您想减少脚本的处理成本。
修改点:
- 当我看到你的脚本时,我认为
blob1
和 blob2
可以退出循环。我觉得这样一来,工艺成本可能会有点低。
- 但是,当
GmailApp.sendEmail
循环发送500封邮件时,这个过程成本会很高。我以为这个成本比上面那点要大
- 为了减少发送 500 封电子邮件的过程成本,在这个答案中,作为一种解决方法,我想建议使用 Gmail API 和批量请求。但我不确定这是否是您问题的直接解决方案。所以请测试下面的脚本。
修改后的脚本如下
修改后的脚本:
在使用此脚本之前,请先安装a Google Apps Script library of BatchRequest. You can see how to install this library at 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)
}
注:
- 这个方法是我的尝试。所以请测试上面的脚本。
参考文献:
问题:
在@Cooper 的大力帮助下,我能够使用 html 模板(“emailEinladung.html”)和收件人列表(“terminBestaetige”)优化我的邮件合并脚本。每个收件人都会收到一封基于 html 模板的个性化电子邮件,只要第 11 列(因此,“K”)中的 his/her 状态未设置为“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
}
});
}
问题:
我的脚本有什么地方应该改进以提高效率吗?如果是,那改进是什么?您的脚本会是什么样子?
非常感谢您的帮助。
我相信你的目标如下。
- 您想减少脚本的处理成本。
修改点:
- 当我看到你的脚本时,我认为
blob1
和blob2
可以退出循环。我觉得这样一来,工艺成本可能会有点低。 - 但是,当
GmailApp.sendEmail
循环发送500封邮件时,这个过程成本会很高。我以为这个成本比上面那点要大 - 为了减少发送 500 封电子邮件的过程成本,在这个答案中,作为一种解决方法,我想建议使用 Gmail API 和批量请求。但我不确定这是否是您问题的直接解决方案。所以请测试下面的脚本。
修改后的脚本如下
修改后的脚本:
在使用此脚本之前,请先安装a Google Apps Script library of BatchRequest. You can see how to install this library at 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)
}
注:
- 这个方法是我的尝试。所以请测试上面的脚本。