Преобразовать массив JavaScript в объект JSON
Я изменяю проект слияния в Google Apps Script. Проблема, с которой я сталкиваюсь, заключается в том, чтобы заставить тело письма отображать встроенные изображения. В настоящее время все встроенные изображения, присутствующие в исходном шаблоне электронной почты, отображаются в виде вложений после вызова 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});
3 ответа
100% -ная верность от проекта или готового ответа полностью выполнима. Этот фрагмент кода взят из рабочего слияния, которое я расширил для поддержки встроенных изображений (как встроенных больших двоичных объектов, так и внешних ссылок), а также вложений:
...
//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});
У меня это работает с пользователями домена весь день, каждый день. Надеюсь это поможет.
Некоторые комментарии:
> 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
измененный "shim" или "monkey patch", тогда эти свойства тоже будут перечислены, поэтому:
> var title = imgVars[i].match(/title="([^\"]+\")/);
вполне может быть попытка вызвать сопоставление для свойства, значение которого является ссылкой на функцию, и поэтому выдает ошибку. По крайней мере, должен быть включен тест hasOwnProperty, но лучше просто использовать обычный цикл for.
> for (j in attachments) {
Кажется, вложения также являются массивом, так что используйте здесь цикл for по тем же причинам, что и выше. Это также не очень хорошая идея использовать for..in (которая может посещать свойства в неожиданном порядке) с splice, что подразумевает, что вы ожидаете определенного заказа. Обратите внимание, что в некоторых браузерах for..in будет посещать элементы массива в порядке их добавления в массив, а не в числовом порядке. Другие браузеры всегда будут посещать числовые свойства в определенном порядке, но не в других.
Многое из этого будет намного проще, если HTML преобразуется во фрагмент документа, тогда методы DOM можно использовать для извлечения элементов img и доступа к их свойствам для создания объекта. Затем нативные методы могут быть использованы для преобразования объекта в JSON при необходимости.
К сожалению, встроенные изображения не имеют заголовка. У них есть alt=Inline Image 1, но это не то же самое, что и имя вложения. Единственные элементы в теге img - это alt и src.
Учитывая это, кажется, нет никакого способа связать встроенное изображение с вложениями, кроме как надеяться, что первое встроенное изображение является первым вложением и т. Д.
Следует отметить, что я использую веб-интерфейс Gmail для создания черновика и вставки изображений с помощью лаборатории "Вставка изображений".