大家平时会有发邮件的时候没有一个模板而发愁吗?在发邮件的时候,很多时候我们还是需要一些邮件定制一些邮件模板,这样对于用户体验来说更棒。下面我来介绍一下技术细节,有说的不好的地方,请拍砖!
首先在我们来设计一下模板文件的结构目录:
emalilplates为邮件模板根目录的文件夹 Template1、Template2为邮件模板的文件夹
-
html.
邮件模板html语法支持格式( jade, handlebars, eco, ejs) template engine
-
style.stylus
用stylus是因为考虑到他能支持css, sass, less的基本语法,总之就是因为它很强大.
-
emailplate.json
我们在邮件模板主题中也许会需要动态的在邮件主题中改变一些内容,这个时候就需要传递该json的参数
下面是具体技术实现过程,我就用我最擅长的nodejs中的coffeescript语法实现给大家看吧.
_ = require 'underscore'
glob = require 'glob'
async = require 'async'
fs = require 'fs'
cons = require 'consolidate'
stylus = require 'stylus'
juice = require 'juice'
module.exports = class Emailplate
settings:
views: './emailplates'
constructor: (settings = {}) ->
_.extend [@settings](/user/settings), settings
get: (name) ->
[@settings](/user/settings)[name]
set: (setting, val) ->
if arguments.length is 1
_.extend [@settings](/user/settings), setting
else
[@settings](/user/settings)[setting] = val
this
settings中的参数views是用来设置emailplates的存放路径,当然,我们在调用的时候可以随时改掉这个路径
themes: (fn) ->
glob "#{[@settings](/user/settings).views}/**/emailplate.json", (err, files) ->
parallel = []
_.each files, (file) ->
parallel.push (cb) ->
fs.readFile file, 'utf-8', (err, content) ->
info = JSON.parse content
cb null, info
async.parallel parallel, fn
theme: (name, fn) ->
fs.readFile "#{[@settings](/user/settings).views}/#{name}/emailplate.json", 'utf-8', (err, content) ->
return fn err if err
info = JSON.parse content
fn null, info
多个获取主题信息的方法我简单介绍下: 我用了glob这个模块遍历所有主题下的emailplate.json而得到我们所需的信息, emailplate.json中是一些信息介绍和要传人emailplates view中的变量如:
另外要主要的是,为了避免在循环的时候拿不到值需要用each 或者 do...while等等方式去解决,而我们在读文件的时候需要转下编码,我默然转为utf-8格式,然后用async这个插件进行同步并行的方式读取。
最后,我们还需要一个render的方法把html和css编译后显示出来。
render: (theme, options, fn) ->
if _.isFunction options
fn = options
options = {}
themeDir = "#{[@settings](/user/settings).views}/#{theme}"
fs.readFile "#{themeDir}/emailplate.json", 'utf-8', (err, content) ->
info = JSON.parse content
options = _.defaults options, info.locals
async.parallel
html: (cb) ->
cons[info.template.engine] "#{themeDir}/html.#{info.template.extension}", options, cb
css: (cb) ->
fs.readFile "#{themeDir}/style.styl", 'utf-8', (err, content) ->
stylus.render content, cb
,
(err, results) ->
html = juice results.html, results.css
fn null, html
在这里,大家可以看到,我用了async同步并行的方式去读html和css,然后等待都读完后在进行编译操作,把得到的结果进行回调处理。另外需提醒的是,theme为主题名称, 而options为要传入的变量.
var Emailplate = require('emailplate')
, emailplate = new Emailplate();
#get和set 邮件模板路径代码
emailplate.set('views', __dirname + '/emailplates');
emailplate.get('views');
#获取所有邮件模板信息
emailplate.themes(function(err, infos) {
});
#获取单个邮件模板信息
emailplate.theme('themeName', function(err, info) {
});
# render 邮件模板显示出来
emailplate.render('themeName', {title: "emailplate test"}, function(err, html) {
#这里返回的结果是编译后的html代码
});
回复 (5)
ym1623 兄,我想问下微信模拟登陆的 发送信息部分目前是否还成功。 我用ASP写的模拟登陆。 发送信息时候已经提交TOKEN了 但是返回 {"ret":"-1", "msg":"need post"}
我是POST提交的
那个微信我有些时段没有去管了,,这几天我有空的话去更新下.