Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add cid image attachment support in template #10 #14

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ or if you want to contribute see this READMEs:
- HTML form are autogenerated by [JSON Schema](https://json-schema.org/)
- User can preview the email or send email
- Optionnaly record all email sent
- [cid](https://nodemailer.com/message/embedded-images/) image attachment support


## This project is based on this stack
Expand Down
51 changes: 48 additions & 3 deletions backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ function getHtml(templatePath, values) {
);
}

function replaceAllCIDByPreviewUrl(data, ctx) {
return data.replace(/(['|"])cid:(.*)(['|"])/gi, `$1${ctx.siteUrl}/v1/templates/${ctx.params.name}/attachments/$2$3`);
}

function getTxt(templatePath, values) {
return nunjucks.renderString(
fs.readFileSync(
Expand Down Expand Up @@ -119,7 +123,10 @@ router.post('/v1/templates/:name/preview', (ctx) => {
ctx.type = 'application/json';
ctx.body = {
'subject': getSubject(subjectTemplatePath, ctx.request.body),
'html': getHtml(mjmlTemplatePath, ctx.request.body),
'html': replaceAllCIDByPreviewUrl(
getHtml(mjmlTemplatePath, ctx.request.body),
ctx
),
'txt': getTxt(txtTemplatePath, ctx.request.body)
};
});
Expand All @@ -146,15 +153,53 @@ router.post('/v1/templates/:name/send', async (ctx) => {
to: ctx.request.body.to,
subject: getSubject(subjectTemplatePath, ctx.request.body),
html: getHtml(mjmlTemplatePath, ctx.request.body),
text: getTxt(txtTemplatePath, ctx.request.body)
text: getTxt(txtTemplatePath, ctx.request.body),
attachments: fs.readdirSync(
path.join(
ctx.templatePath,
ctx.params.name,
'attachments'
)
).map((filename) => {
return {
filename: filename,
path: path.join(
ctx.templatePath,
ctx.params.name,
'attachments',
filename
),
cid: filename,
encoding: 'base64'
};
})
});
ctx.body = { result: result };
});

module.exports = function createApp(port, templatePath, staticPath, smtpUrl) {
router.get('/v1/templates/:name/attachments/:filename', async (ctx) => {
console.log('attachments');
const attachmentFilePath = path.join(
ctx.templatePath,
ctx.params.name,
'attachments',
ctx.params.filename
);
if (!fs.existsSync(attachmentFilePath)) {
ctx.status = 404;
ctx.body = `${ctx.params.name}/attachments/${ctx.params.filename} file not exists`;
return;
}

ctx.attachment(ctx.params.filename);
ctx.body = fs.createReadStream(attachmentFilePath);
});

module.exports = function createApp(port, templatePath, staticPath, smtpUrl, siteUrl) {
const app = new Koa();
app.context.port = port;
app.context.templatePath = templatePath;
app.context.siteUrl = siteUrl;

if (smtpUrl === undefined) {
app.context.transporter = nodemailer.createTransport({
Expand Down
3 changes: 2 additions & 1 deletion backend/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const app = createApp(
PORT,
process.env.TEMPLATES_PATH || '../mail-templates/',
process.env.STATIC_PATH || undefined,
process.env.SMTP_URL || undefined
process.env.SMTP_URL || undefined,
process.env.SITE_URL || `http://127.0.0.1:${PORT}`
);

const server = app.listen(PORT, () => {
Expand Down
22 changes: 22 additions & 0 deletions backend/src/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,25 @@ paths:
application/json:
schema:
type: object

/v1/templates/{name}/attachments/{filename}:
get:
summary: "Get template attachment files"
parameters:
- in: path
name: name
schema:
type: string
required: true
description: Template name
- in: path
name: filename
schema:
type: string
required: true
description: Attachment filename
responses:
'200':
description: File content
content:
application/x-binary
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions mail-templates/confirm_email/default.mjml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
<mj-body>
<mj-section background-color="white">
<mj-column>
<mj-text>
<mj-text>
<p>Hi {{ username }}!</p>

<p>Thanks for signing up for {{ application_name }}!</p>
</mj-text>

<mj-image width="100px" src="cid:gibbon.png" />

<mj-text>
<p>Please confirm your email ({{ confirm_email|safe }}) by clicking the link below:</p>
</mj-text>

Expand All @@ -17,7 +21,7 @@
color="white"
>Confirm</mj-button>

<mj-text>
<mj-text>
<p>This link will expire in 48 hours.</p>

{% if is_new_user %}
Expand Down