email-templates + mjml 发送邮件

2020-12-07 15:17:45

参考地址 email-templates + mjml 发送邮件

mjml 是一个很不错的响应式邮件html 内容标签库,email-templates 是一个灵活强大的邮件发送框架,两者集成起来我们
可以设计灵活强大的邮件发送系统,以下是一个简单的集成使用,实际使用还有好多地方需要完善

环境准备

  • 项目结构

 

├── README.md
├── app.js
├── package.json
├── polyfill.js
├── templates
│ └── mail.mjml
  • 代码说明
    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",
    "pug": "^2.0.4"
  },
  "scripts": {
    "app":"node app.js"
  }
}

polyfill.js js 字符串插值polyfill,主要解决mjml 对于变量的支持

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 集成email-templates 与mjml 的代码
使用了email-templates 的自定义渲染处理,

 

const Email = require('email-templates');
const mjml2html = require("mjml")
const fs = require("fs")
require("./polyfill")
const email = new Email({
  message: {
    from: 'niftylettuce@gmail.com',
    headers: {
      'X-Some-Custom-Thing': 'Some-Value'
    },
    list: {
      unsubscribe: 'https://niftylettuce.com/unsubscribe'
    }
  },
  transport: {
    jsonTransport: true
  },
  render: (view, locals) => {
    return new Promise((resolve, reject) => {
      // this example assumes that `template` returned
      // is an ejs-based template string
      // view = `${template}/html` or `${template}/subject` or `${template}/text`
     // 集成mjml 的核心部分,读取模版内容,同时应用插值添加变量支持
      if (view.substring("html")) {
        let vars = {
          appname:"dalongdemo-rongfengliang"
        }
        let htmlOutput = mjml2html(fs.readFileSync("templates/mail.mjml").toString().interpolate({vars}))
        resolve(htmlOutput.html)
      }
      if (view.substring("text")) {
        resolve("not support")
      }
    });
  }
}
);

email
  .send({
    template: 'mars',
    message: {
      to: 'elon@spacex.com',
      subject: "demoapp"
    },
    locals: {
      name: 'Elon'
    }
  })
  .then(console.log)
  .catch(console.error);

mail.mjml mjml 模版内容,使用mjml npm 包进行渲染

    <mjml>
  <mj-head>
    <mj-preview>Hello MJML</mj-preview>
    <mj-title>Hello MJML</mj-title>
    <mj-attributes>
      <mj-accordion border="none" padding="1px" />
      <mj-accordion-element icon-wrapped-url="http://i.imgur.com/Xvw0vjq.png" icon-unwrapped-url="http://i.imgur.com/KKHenWa.png" icon-height="24px" icon-width="24px" />
      <mj-accordion-title font-family="Roboto, Open Sans, Helvetica, Arial, sans-serif" background-color="#fff" color="#031017" padding="15px" font-size="18px" />
      <mj-accordion-text font-family="Open Sans, Helvetica, Arial, sans-serif" background-color="#fafafa" padding="15px" color="#505050" font-size="14px" />
    </mj-attributes>
  </mj-head>
  <mj-body>
    <!-- Company Header -->
    <mj-section padding="20px" background-color="#ffffff">
      <mj-column background-color="#dededd">
        <mj-accordion>
          <mj-accordion-element>
            <mj-accordion-title>Why use an accordion?</mj-accordion-title>
            <mj-accordion-text>
              <span style="line-height:20px">
                Because emails with a lot of content are most of the time a very bad experience on mobile, mj-accordion comes handy when you want to deliver a lot of information in a concise way.
              </span>
            </mj-accordion-text>
          </mj-accordion-element>
          <mj-accordion-element>
            <mj-accordion-title>${vars.appname}</mj-accordion-title>
            <mj-accordion-text>
              <span style="line-height:20px">
               ${new Date()} Content is stacked into tabs and users can expand them at will. If responsive styles are not supported (mostly on desktop clients), tabs are then expanded and your content is readable at once.
              </span>
            </mj-accordion-text>
          </mj-accordion-element>
        </mj-accordion>
      </mj-column>
    </mj-section>
    <mj-section background-color="#f0f0f0">
      <mj-column>
        <mj-text font-style="italic" font-size="20px" color="#626262">
         demoappppp
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Image Header -->
    <mj-section background-url="http://1.bp.blogspot.com/-TPrfhxbYpDY/Uh3Refzk02I/AAAAAAAALw8/5sUJ0UUGYuw/s1600/New+York+in+The+1960's+-+70's+(2).jpg" background-size="cover" background-repeat="no-repeat">

      <mj-column width="600px">

        <mj-text align="center" color="#fff" font-size="40px" font-family="Helvetica Neue">Slogan here</mj-text>

        <mj-button background-color="#F63A4D" href="#">
          Promotion
        </mj-button>

      </mj-column>

    </mj-section>

    <!-- Introduction Text -->
    <mj-section background-color="#fafafa">
      <mj-column width="400px">

        <mj-text font-style="italic" font-size="20px" font-family="Helvetica Neue" color="#626262">My Awesome Text</mj-text>

        <mj-text color="#525252">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum enim eget magna efficitur, eu semper augue semper. Aliquam erat volutpat. Cras id dui lectus. Vestibulum sed finibus lectus, sit amet suscipit nibh. Proin nec commodo purus. Sed eget nulla elit. Nulla aliquet mollis faucibus.
        </mj-text>

        <mj-button background-color="#F45E43" href="#">Learn more</mj-button>

      </mj-column>
    </mj-section>
    <mj-section>
      <mj-column>
        <mj-carousel>
          <mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/11/ecommerce-guide.jpg" />
          <mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/09/3@1x.png" />
          <mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/09/1@1x.png" />
        </mj-carousel>
      </mj-column>
    </mj-section>
    <!-- 2 columns section -->
    <!-- Side image -->
    <mj-section background-color="white">

      <!-- Left image -->
      <mj-column>
        <mj-image width="200px" src="https://designspell.files.wordpress.com/2012/01/sciolino-paris-bw.jpg" />
      </mj-column>

      <!-- right paragraph -->
      <mj-column>
        <mj-text font-style="italic" font-size="20px" font-family="Helvetica Neue" color="#626262">
          Find amazing places
        </mj-text>

        <mj-text color="#525252">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum enim eget magna efficitur, eu semper augue semper. Aliquam erat volutpat. Cras id dui lectus. Vestibulum sed finibus lectus.</mj-text>

      </mj-column>
    </mj-section>
    <!-- Icons -->
    <mj-section background-color="#fbfbfb">
      <mj-column>
        <mj-image width="100px" src="http://191n.mj.am/img/191n/3s/x0l.png" />
      </mj-column>
      <mj-column>
        <mj-image width="100px" src="http://191n.mj.am/img/191n/3s/x01.png" />
      </mj-column>
      <mj-column>
        <mj-image width="100px" src="http://191n.mj.am/img/191n/3s/x0s.png" />
      </mj-column>
    </mj-section>
    <!-- Social icons -->
    <mj-section background-color="#e7e7e7">
      <mj-column>
        <mj-social>
          <mj-social-element name="facebook" />
        </mj-social>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

 

 

运行&&效果

默认运行的模式是预览,我们可以方便的查看发送内容

  • 运行

yarn app
  • 效果

 

 

说明

以上是一个简单的集成,email-templates 以及mjml 还是很强大的

参考资料

https://github.com/forwardemail/email-templates
https://github.com/mjmlio/mjml
https://github.com/rongfengliang/email-templates-mjml-learning


  • 2020-03-14 23:39:59

    vuetify和@nuxt/vuetify icon 之我见

    vuetify中v-icon,貌似默认支持 Material Design Icons, Material Icons, Font Awesome 4 and Font Awesome 5, 我自己单独引入了vuetify 用哪一个图标都没有问题。但是用了@nuxt/vuetify只能用mdi-home这样的。不知道因为啥。肯定是封装后,封装成一个了。 但是我修改vuetify的设置,哪一个图标也都能用。哎,不过多研究了。

  • 2020-03-16 15:57:53

    nuxtjs中单独引入Message组件的问题

    // 引入elementUIimport { Message } from 'element-ui';//由于Message组件并没有install 方法供Vue来操作的,是直接返回的,因此按照官方文档单独引入的方法是//会报错的,需要给 Message 添加 install 方法Message.install = function (Vue, options) {Vue.prototype.$message = Message}Vue.use(Message )//消息提示

  • 2020-03-16 16:03:20

    css的var()函数

     随着sass,less预编译的流行,css也随即推出了变量定义var函数。var()函数,就如同sass和less等预编译软件一样,可以定义变量并且进行对应的使用。

  • 2020-03-16 16:52:05

    对icomoon的误解,以及最快速的使用

    此时需要注意顶部第一个选项,Quick Usage,一定要打开,Enable Quick Usage,谁让咱英语不好呢,这个时候会出现一个css连接,直接引用就好了,就可以随意使用图标了,引入这一个css就能实现我们的功能,省区引入太多文件的烦恼,你可以在浏览器打开这个css,可以看到里面把我们所用的文件整成base64了。所以挺好用的。

  • 2020-03-17 09:47:05

    video标签视频不自动播放的问题

    添加 muted 属性,就可以通过地址栏进入网页的时候自动播放了,手机端还是有的有限制的,比如iphone浏览器,就不行,苹果手机为了保护用户的流量和用户的意愿,是禁止自动播放的,必须有手动触发。

  • 2020-03-17 14:21:31

    nuxt+pm2 自动化部署及打包后文件自动上传阿里云 oss(精华)

    部署nuxtjs,这一篇文章就够了,pm2 代码自动发布依赖于 git 工具,先将 ssh 密钥配置再你的代码仓库(github 或者 gitLab),具体操作自行 google 或者点击github 配置 ssh。 使用 ssh 密钥链接服务器 s $ ssh-copy-id root@1.2.3.4 # 把本机的 SSH 秘钥添加至服务器,配置成功后,以后就不需要再执行这条 SSH 命令了

  • 2020-03-18 21:15:34

    使用canvas画布解决百度地图自定义图层全球连续显示问题

        基于百度地图的Web API进行自定义图层叠加时,默认的图层只能叠加到全球范围以内,即经度范围为[-180, 180],而无法将图层叠加到默认的全球范围以外,即经度范围超出了[-180, 180]之后,经纬度坐标会自动回归到(0, 0),而导致在地图拖拽时全球以外无法连续显示想要的图层,此时可以基于百度地图的自定义图层将经纬度坐标转为像素点使用画布canvas来解决该问题。解决后效果如下图所示: ———————————————— 版权声明:本文为CSDN博主「宏伟杰作」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u011284073/article/details/80549950