同じドメインのメール受信者を一括送信するために使用している Google Apps Script があります。スクリプトは基本的に、月次レポートを含む Google ドキュメントへのリンクを送信します。レポートの値は、スプレッドシートから取得されます。
- 16 列 750 行のスプレッドシートにアクセスする
- EMAIL 列からメールアドレスを読み取ります
- 基本的に月次レポートのテンプレートである Google Doc にアクセスし、スプレッドシートから取得した各メール アドレスのテンプレートのコピーを作成し、列の値を使用して基本的に Doc の置換を検索します。私のアプリでは、ユーザーがテンプレートを選択できるようにしてから、その templateId を ScriptDB に保存します。
- 月次レポートへのリンクを含む各受信者に電子メールを送信します。列の値はユーザーを表すため、各レポートは一意です。
このスクリプトの最大の問題は、実行から 5 分後にタイムアウトになることです。前回実行しようとしたとき、750 通のメール ターゲットのうち 145 通のメールが送信されました。
テンプレート セレクタ コード
function selectTemplate() {
var app = UiApp.createApplication().setTitle("Select Template").setHeight(400).setWidth(500);
var doclisthandler = app.createServerHandler('templateSelectionHandler');
var closeHandler = app.createServerHandler('closeSelectionHandler');
app.createDocsListDialog().showDocsPicker().addSelectionHandler(doclisthandler).addCloseHandler(closeHandler);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
/**
Function to retrieve the template ID from ScriptDb
**/
function setTemplateId(){
var db = ScriptDb.getMyDb();
/**we dont query for a specific ID because by default we only store one template so we will
always have one record
**/
var results = db.query({});
while (results.hasNext()) {
var result = results.next();
var jsonResults = Utilities.jsonStringify(result);
}
Logger.log(jsonResults);
var jsonTemplate = Utilities.jsonParse(jsonResults);
var templateId = jsonTemplate.template_id;
return templateId;
}
これは、電子メールを送信するコードです。
function sendEmail(){
var mySheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = mySheet.getDataRange();
var myRange = range.offset(1, 0, range.getNumRows()-1);
var curFeatures = range.getValues();
var curCols = new ColNumbers(curFeatures[0], COLS_KEYAPPCOLS);
var currentTime = new Date();
var payrollYear = currentTime.getYear();
var payMonth = mySheet.getSheetName();
var hours = currentTime.getHours();
var minutes = currentTime.getMinutes();
try{
//check if folder exists before you create one
var monthFolder = DocsList.getFolder("Report-" + mySheet.getSheetName() + "," + payrollYear);
}catch(e){
//create a folder to hold the current pay slips
var monthFolder = DocsList.createFolder("Report-" + mySheet.getSheetName() + "," + payrollYear);
Logger.log(monthFolder.getName());
}
myRange.getValues().forEach( function( recipient, index, data ){
var staffNumber = recipient[curCols.staffNumber];
Logger.log("staff Number " + staffNumber);
var staffName = recipient[curCols.name];
Logger.log("staffName " + staffName);
var subject = "Report - " + staffName + ", " + payMonth + "-" + payrollYear;
var emailAddress = recipient[curCols.email];
var adminAllowance = recipient[curCols.admin];
var respAllowance = recipient[curCols.resp];
var topUpAllowance = recipient[curCols.topup];
var arrears = recipient[curCols.arrears];
var overtime = recipient[curCols.overtime];
var grossPay = recipient[curCols.gross];
var paye = recipient[curCols.paye];
var mubasa = recipient[curCols.mubasa];
var loan = recipient[curCols.loan];
var rent = recipient[curCols.rent];
var nssf = recipient[curCols.nssf];
var net = recipient[curCols.net];
var totalDed = recipient[curCols.totalded];
var templateid = setTemplateId(); // get template file id
if(templateid == ""){
Browser.msgBox("No template has been selected. Please select the correct template");
return;
}
var docName = "Report details - " + staffNumber;
//if email address is not empty do all the cool stuff like sending the data
if(emailAddress != ""){
var copyDoc = DocsList.getFileById(templateid).makeCopy(docName);
copyDoc.addToFolder(monthFolder);
var docid = copyDoc.getId();
Logger.log("Document ID " + docid);
var doc = DocumentApp.openById(docid);
//set permissions for the doc
Logger.log("permission to view doc " + docid + " assigned to " + emailAddress);
doc.addViewer(emailAddress);
var docURL = doc.getUrl();
var body = doc.getActiveSection();
body.replaceText("%MONTH%", payMonth);
body.replaceText("%YEAR%", payrollYear);
body.replaceText("%STAFFNAME%", staffName);
body.replaceText("%PAYE%", paye);
body.replaceText("%OVERTIME%", overtime);
body.replaceText("%GROSS%", grossPay);
body.replaceText("%NSSF%", nssf);
body.replaceText("%MUBASA%", mubasa);
body.replaceText("%NET%", net);
body.replaceText("%ARREARS%", arrears);
body.replaceText("%TOTALDED%", totalDed);
body.replaceText("%LOAN%", loan);
body.replaceText("%RENT%", rent);
body.replaceText("%ADMIN%", adminAllowance);
body.replaceText("%RESP%", respAllowance);
body.replaceText('%TOPUP%', topUpAllowance);
//email message
doc.saveAndClose();
Logger.log("Sending email to " + emailAddress + " at " + hours + ":" + minutes);
try{
MailApp.sendEmail(emailAddress,
subject, "",
{htmlBody: message
},
attachment: docName,
name: "Report"
});
}catch(e){
Logger.log(e);
}
}else{
Logger.log("no email address found for staff member " + staffName);
}
});
}
このスクリプトがタイムアウトしないように最適化する方法について、いくつかの指針をいただければ幸いです。