Преобразовать массив 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 для создания черновика и вставки изображений с помощью лаборатории "Вставка изображений".

Другие вопросы по тегам