[SOLVED] Embed server side rendered image into html email

Hi All,
I’m adding a feature to my app to send reports to the users.
This report would include a chart showing some indicators.
I can create a server side rendered chart (svg) using D3-node.
I can create an html email and send it to user.
But i don’t know yet how to embed the chart into the email.

I understand that svg’s are not well supported by email clients. So i would have to work with an embedded image.
It is likely, the best way to embed an image to an email is to work with CID Embedded Images, and mailcomposer can do CID embedded images
But i got lost between the chart creation and the image embedding

Is it possible to do all the steps in a single pipe without creating a png file ?
Should I create a image.png file, encode it to base64 and attach it to the email ? If so how is it possible in production ?

Thanks in advance for your insights

I think server side rendered template containing an image with base64 source will do it. If svg is creating problems you can convert to png or jpeg etc.I don’t know if there is any better way though.

Thank you for your reply
Svg’s are definitely not supported by most email clients if not all of them. So the only way to include embedded charts in an email is to use png files.
I finally managed to do it this way :

/server/methods

import { Meteor } from 'meteor/meteor';
import { Email } from 'meteor/email';
import { createCanvasChart } from './createCanvasChart.js';

Meteor.methods({
  'sendEmailWithPng' (data) {
    const pngChart = createCanvasChart(data);
    this.unblock;
    let message = `
        <!DOCTYPE html>
        <html lang="en">
            <head>
                <meta name="viewport" content="width=device-width" />
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
                <title></title>
                <style type="text/css">
                  /* your email template css goes here ... */
                </style>
            </head>
            <body>
                <table class="body">
                    <tr>
                        <td></td>
                        <td class="container">
                            <div class="content">
                                Your message to your user
                                <img src="cid:pngChart" /> /* your chart will show here */
                            </div>
                        </td>
                        <td></td>
                    </tr>
                </table>
            </body>
        </html>
        `
        const to = "yourUser@herDomain.com";
        const from = "you@yourDomain.com";
        const subject = "Message with chart";
        const attachments = [
            {
                filename: "chart.png",
                content: pngChart,
                encoding: 'base64',
                cid: 'pngChart'
            }
        ];
        Email.send({ to, from, subject, html: message, attachments });
  }
});
createCanvasChart.js

import D3Node from 'd3-node';
import canvasModule from 'canvas'

export function createCanvasChart(data) {
    const d3n = new D3Node({ canvasModule }); // pass it node-canvas
    const canvas = d3n.createCanvas(900, 600);
    const d3 = d3n.d3;
    
    const context = canvas.getContext('2d');
   
    // draw a box around our canvas border
    context.fillStyle = 'black';
    context.strokeRect(0, 0, canvas.width, canvas.height);

    /* Draw you chart in canvas here */
 
    const png = canvas.pngStream();
    return png;   
}

I hope this might help others

2 Likes