-
Notifications
You must be signed in to change notification settings - Fork 2
/
MailMerge.js
147 lines (142 loc) · 6.88 KB
/
MailMerge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
function processRow(rowData, mergeData, emailcol) {
var emailText = fillInTemplateFromObject(mergeData.template, rowData);
var emailSubject = fillInTemplateFromObject(mergeData.subject, rowData);
var plainTextBody = fillInTemplateFromObject(mergeData.plainText, rowData);
mergeData['htmlBody'] = emailText;
if (rowData.cc != undefined) mergeData.cc = rowData.cc;
if (rowData.bcc != undefined) mergeData.bcc = rowData.bcc;
console.log(rowData)
GmailApp.sendEmail(rowData[emailcol], emailSubject, plainTextBody, mergeData);
}
function getDraftId() {
var drafts = GmailApp.getDrafts();
for (var i = 0; i < drafts.length; i++) {
console.log(drafts[i].getId());
console.log(drafts[i].getMessage().getSubject());
}
}
function run_mail_merge(ss, draftID, tocolumn) {
var name = "Minds Matter"
var domainname = PropertiesService.getScriptProperties().getProperty('domainname');
var from = 'admin@' + domainname;
var selectedDraft = GmailApp.getDraft(draftID)
var selectedTemplate = selectedDraft.getMessage()
var dataSheet = ss.getActiveSheet();
var headers = createHeaderIfNotFound_('Merge status', ss);
var dataRange = dataSheet.getDataRange();
//////////////////////////////////////////////////////////////////////////////
// Get inline images and make sure they stay as inline images
//////////////////////////////////////////////////////////////////////////////
var emailTemplate = selectedTemplate.getBody();
var rawContent = selectedTemplate.getRawContent();
var attachments = selectedTemplate.getAttachments();
var cc = selectedTemplate.getCc();
var bcc = selectedTemplate.getBcc();
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) {
id = id[1];
var temp = rawContent.split(id)[1];
temp = temp.substr(temp.lastIndexOf('Content-Type'));
var imgTitle = temp.match(/name="([^"]+)"/);
var contentType = temp.match(/Content-Type: ([^;]+);/);
contentType = (contentType != null) ? contentType[1] : "image/jpeg";
var b64c1 = rawContent.lastIndexOf(id) + id.length + 3; // first character in image base64
var b64cn = rawContent.substr(b64c1).indexOf("--") - 3; // last character in image base64
var imgb64 = rawContent.substring(b64c1, b64c1 + b64cn + 1); // is this fragile or safe enough?
var imgblob = Utilities.newBlob(Utilities.base64Decode(imgb64), contentType, id); // decode and blob
if (imgTitle != null) imgToReplace.push([imgTitle[1], imgVars[i], id, imgblob]);
}
}
}
}
for (var i = 0; i < imgToReplace.length; i++) {
inlineImages[imgToReplace[i][2]] = imgToReplace[i][3];
var newImg = imgToReplace[i][1].replace(/src="[^\"]+\"/, "src=\"cid:" + imgToReplace[i][2] + "\"");
emailTemplate = emailTemplate.replace(imgToReplace[i][1], newImg);
}
}
//////////////////////////////////////////////////////////////////////////////
var mergeData = {
template: emailTemplate,
subject: selectedTemplate.getSubject(),
plainText: selectedTemplate.getPlainBody(),
attachments: attachments,
name: name,
from: from,
cc: cc,
bcc: bcc,
inlineImages: inlineImages
}
var objects = getRowsData(dataSheet, dataRange);
console.log(objects);
for (var i = 0; i < objects.length; ++i) {
var rowData = objects[i];
if (rowData.mergeStatus == "") {
try {
processRow(rowData, mergeData, tocolumn);
dataSheet.getRange(i + 2, headers.indexOf('Merge status') + 1).setValue("Done").clearFormat().setComment(new Date());
}
catch (e) {
dataSheet.getRange(i + 2, headers.indexOf('Merge status') + 1).setValue("Error").setBackground('red').setComment(e.message);
}
}
}
}
function run_merge() {
var draftID = PropertiesService.getScriptProperties().getProperty('newAccountDraftID');
var userID = PropertiesService.getScriptProperties().getProperty('newUserSheetID');
var ss = SpreadsheetApp.openById(userID);
run_mail_merge(ss, draftID, 'privateemail');
}
// Replaces markers in a template string with values define in a JavaScript data object.
// Arguments:
// - template: string containing markers, for instance <<Column name>>
// - data: JavaScript object with values to that will replace markers. For instance
// data.columnName will replace marker <<Column name>>
// Returns a string without markers. If no data is found to replace a marker, it is
// simply removed.
function fillInTemplateFromObject(template, data) {
template = template.replace(/<</g, '<<');
template = template.replace(/>>/g, '>>');
template = template.replace(/\{\{/g, '<<');
template = template.replace(/\}\}/g, '>>');
var email = template;
console.log(template)
template = template.replace(/">/g, "~");
// Search for all the variables to be replaced, for instance <<Column name>>
var templateVars = template.match(/<<[^\>]+>>/g);
if (templateVars != null) {
if (template.match(/\$\%[^\%]+\%/g) != null) {
templateVars = templateVars.concat(template.match(/\$\%[^\%]+\%/g));
}
}
else {
var templateVars = template.match(/\$\%[^\%]+\%/g);
}
console.log(templateVars)
if (templateVars != null) {
// Replace variables from the template with the actual values from the data object.
// If no value is available, replace with the empty string.
for (var i = 0; i < templateVars.length; ++i) {
// normalizeHeader ignores <<>> so we can call it directly here.
var variableData = data[normalizeHeader(templateVars[i].replace(/<[^\~]+~/, ''))];
variableData = variableData.replace(/\r?\n/g, "<br />")
templateVars[i] = templateVars[i].replace(/~/g, '">');
// Check that we have a header for this merge field
if (variableData == undefined) {
throw new UserException("Undefined merge field " + templateVars[i]);
}
email = email.replace(templateVars[i], variableData || "");
}
}
return email;
}