I have a node application successfully sending emails using nodemailer. I am sending emails with code similar to this:
const emailRequest = {
from: { name: "Sender name", address: "[email protected]" },
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);
The problem is that sometimes the email body contains inline images formatted like this, where {base64_image_content}
is the actual data containing the image:
<img src="data:image/png;base64,{base64_image_content}">
and Gmail does not support inline image data. The email sends and the image data shows up when I choose "Show original" in Gmail, but the image does not appear in the Gmail web client and it appears as a broken image in the Gmail mobile client.
I don't have control over the inline images, so I'm hoping to find a way to extract the inline image data and add it as an attachment to the email, and use a cid to refer to those attachments in the email body before I call transporter.sendMail
.
I want to change the HTML from this:
<p>Some email text</p><p><img src="data:image/png;base64,{base64_image_content}">
to this:
<p>Some email text</p><p><img src="cid:myImageCid">
and add the image as an attachment:
const emailRequest = {
// other things
attachments: [{ cid: "myImageCid", content: base64_image_content }]
} as SendMailOptions;
The part I need help with is extracting the image data from the original email HTML and replacing it with a cid reference. Is there a way I can do that?
I ended up following the advise of akisoft by extracting the image data myself. Here's how I did it:
I pass the HTML of the original email into that function and it returns modified HTML and a list of attachments I can pass directly to nodemailer.