今天有写过一个简单的email-templates 集成mjml 的方法,是通过自定义render(扩展性比较灵活)实际上
email-templates 也提供了配置选项,我们可以选择自己的方法进行模版引擎的扩展,以下是一个简单的尝试
环境准备
- 项目结构
├── README.md
├── app.js
├── emails
│ └── templates
│ ├── html.mjml
│ ├── subject.mjml
│ └── text.mjml
├── package.json
├── polyfill.js
└── yarn.lock
- 代码说明
package.json 依赖的包以及npm script 定义
{
"name": "email-template-learning",
"version": "1.0.0",
"main": "app.js",
"license": "MIT",
"dependencies": {
"email-templates": "^6.1.1",
"mjml": "^4.5.1",
"nodemailer": "^6.4.2",
"pug": "^2.0.4"
},
"scripts": {
"app": "node app.js"
}
}
polyfill.js string 支持插值的,方便变量引入,比较简单
String.prototype.interpolate = function(params) {
const names = Object.keys(params);
const vals = Object.values(params);
return new Function(...names, `return \`${this}\`;`)(...vals);
}
module.exports = String.prototype.interpolate
app.js 核心代码,后边会有介绍
const Email = require('email-templates');
const mjml2html = require("mjml")
const fs = require("fs")
/**
* customer render functions for mjml
* @param {mjml content string} mjmlcontent
*/
function mjml(mjmlpath,locals,cb) {
let mjmlContent = mjml2html(fs.readFileSync(mjmlpath).toString());
cb(null,mjmlContent.html)
}
const nodemailer = require("nodemailer")
require("./polyfill")
const realtransporter = nodemailer.createTransport({
port: 587,
host: "<smtp host>",
auth: {
type: "LOGIN",
user: "<email accounts>",
pass: "<email password>"
}
})
const email = new Email({
message: {
from: '<email accounts>'
},
views: {
options: {
extension: 'mjml', // for mjml
map: {
mjml: 'mjml',
},
engineSource: {
mjml:mjml
}
}
},
send: true,
transport: realtransporter
}
);
.send({
template: 'templates',
message: {
to: '1141591465@qq.com',
subject: "demoapp"
},
locals: {
name: 'Elon'
}
})
.then(console.log)
.catch(console.error);
模版内容,内容在emails, 目录结构如下,内容就是实际的mjml 标签
emails
└── templates
├── html.mjml
├── subject.mjml
└── text.mjml
- 自定义模版引擎的核心说明
对于自定义模版引擎是通过views.opions 配置的,需要制定模版引擎的后缀以及引擎的处理函数,还有map 映射
比如mjml 的配置,如果配置了map,则需要添加engineSource ,engineSource 对应一个支持回掉的函数
views: {
options: {
extension: 'mjml', // for mjml
map: {
mjml: 'mjml',
},
engineSource: {
mjml:mjml
}
}
具体处理的源码(回掉处理依赖pify)
说明
使用通过配置的方法比较适合比较固定的模版(不需要参数传递),对于需要参数传递的,通过自定义的方式会更方便点,实际上对于需要扩展的
我们可以通过缓存以及数据库存储的模式(s3 也不错)增强系统的可扩展行性
参考资料
https://email-templates.js.org/#/?id=custom-template-engine-e-g-ejs
https://github.com/rongfengliang/email-templates-mjml-learning/tree/mjml
https://www.npmjs.com/package/pify