0

我有一个节点应用程序使用nodemailer成功发送电子邮件。我正在发送带有类似代码的电子邮件:

const emailRequest = {
  from: { name: "Sender name", address: "sender@example.com" },
  to: [/* recipients */],
  subject: "Email subject",
  text: "Some email text",
  html: '<p>Some email text</p><p><img src="data:image/png;base64,{base64_image_content}">',
} as SendMailOptions;

const ses = new SES();
const transporter = nodemailer.createTransport({
  SES: ses,
  sendingRate: MAX_SEND_RATE,
});

transporter.sendMail(emailRequest, sendMailResponseHandler);

问题是有时电子邮件正文包含格式如下的内联图像,包含图像{base64_image_content}的实际数据在哪里:

<img src="data:image/png;base64,{base64_image_content}">

而且Gmail 不支持内嵌图片数据。当我在 Gmail 中选择“显示原件”时,电子邮件发送并显示图像数据,但图像未出现在 Gmail 网络客户端中,并且在 Gmail 移动客户端中显示为损坏的图像。

我无法控制内联图像,所以我希望找到一种方法来提取内联图像数据并将其作为附件添加到电子邮件中,并使用 cid 来引用电子邮件正文中的那些附件我打电话transporter.sendMail

我想从这里更改 HTML:

<p>Some email text</p><p><img src="data:image/png;base64,{base64_image_content}">

对此:

<p>Some email text</p><p><img src="cid:myImageCid">

并将图像添加为附件:

const emailRequest = {
  // other things
  attachments: [{ cid: "myImageCid", content: base64_image_content }]
} as SendMailOptions;

我需要帮助的部分是从原始电子邮件 HTML 中提取图像数据并将其替换为 cid 参考。有没有办法我可以做到这一点?

4

3 回答 3

1
require("fs").writeFile("out.png", (some_email_html.split("img")[1]).replace('">',"").split(",")[1], 'base64', function(err) {

console.log(err); 

});

上面的代码将从 html 中提取图像,假设 some_email_html 作为邮件的正文,并将其保存为 out.png,您可以将名称更改为其他任何名称,并在发送电子邮件时删除。请注意,代码假设您需要一个图像,您可以修改以提取更多,或者如果您也需要帮助,请告诉我。

于 2021-04-21T00:58:32.737 回答
0

我最终通过自己提取图像数据来遵循 akisoft 的建议。我是这样做的:

extractImages = (html: string) => {
  // Match all image tags with data in their src
  const regex = /<img src="data:.+?">/gs;
  const images = html.match(regex) ?? [];
  const attachments = images.map((originalImageTag) => {
    // Parse out the image data and meta info
    const imageSrc = (originalImageTag.match(/<img src="data:(.+?)">/s) ?? [])[1];
    const [imageMeta, content] = imageSrc.split(",");
    const [imageType, encoding] = imageMeta.split(";");
    const fileType = imageType.split("/")[1];
    const filename = `image.${fileType}`;
    const cid = uuid();
    const newImageTag = `<img src="cid:${cid}">`;

    // Replace the image tags with ones that reference attached content
    html = html.replace(originalImageTag, newImageTag);

    // Collect attachment data to be passed to nodemailer
    return {
      filename,
      cid,
      encoding,
      content,
      contentDisposition: "inline",
    } as Attachment;
  });

  // Return the modified HTML and the attachments
  return { html, attachments };
};

我将原始电子邮件的 HTML 传递给该函数,它返回修改后的 HTML 和我可以直接传递给 nodemailer 的附件列表。

于 2021-04-21T18:02:46.547 回答
0

像这样通过邮件发送附件,您可以在请求中提供附件。

 const emailRequest = {
      from: { name: "Sender name", address: "sender@example.com" },
      to: [/* recipients */],
      subject: "Email subject",
      attachment: [{
         path: filePath, //"public/data/somefile.png"
         filename: filename,
         cid: filename + "@"
      }],
      text: "Email text",
      html: "Email HTML",
    } as SendMailOptions;
于 2021-04-20T20:28:52.853 回答