Better

Ethan的博客,欢迎访问交流

Node与Express开发之邮件发送

在如今Web中,邮件发送是十分常见的功能,邮件是网站和世界沟通的主要方式之一。对于Node而言,实现邮件发送就十分简单了,希望自己能对邮件有着深入一点的理解。

SMTP、MSA和MTA

发送邮件的通用语言是简单邮件传输协议(SMTP),尽管用SMTP直接发送一封邮件给接受者的邮件服务器是有可能的,但这通常是一个非常糟糕的注意,除非你是值得信任的发送者,否则邮件很有可能直接被扔进垃圾箱。

通过邮件提交代理(MSA)比较好,他会通过可信的渠道投递邮件,降低邮件被标记为垃圾邮件的可能性。

邮件传输代理(MTA),它提供将邮件真正送到其最终目的的服务器。

所以你需要一个MSA,最容易的入手方式是用免费的邮件服务,比如Gmail等,但这是一个临时的解决方案,除了有限制之外,他还会暴露你的个人邮件地址。

邮件组成

邮件头

邮件消息由两个部分组成:头部和主体。头部包含与邮件给有关的信息:谁发的,发给谁,接受日期和主题等。

有些头信息令人吃惊,比如from地址,他可以由发送方任意设定。当你指定的from地址不是你发送的邮件账号时,经常被当成欺诈。没有什么会阻止你将邮件的from地址进行修改。你完全可以按照自己的想法设定特定的头信息。有时出于正当理由可以这样做,但是绝不可以滥用他。

邮件格式

如果邮件功能越来越丰富,可以传输图片,格式化文本和附件。邮件即可以是普通文本,也可以是HTML。

HTML邮件:他不像网站写HTML那么简单,大多数邮件客户端只支持一小部分HTML。邮件的HTML兼容性问题让人头痛,但是有东西可以帮助我们。

HTML Email Boilerplate,它能帮助我们节省很多时间,本质上是一个编写的非常良好并经过严格测试的HTNL邮件模板。

Nodemail使用

创建实例

安装就不废话啦,使用的第一步就是创建Nodemailer实例,具体如下:

var nodemailer = require('nodemailer');

var mailTransport = nodemailer.createTransport('SMTP',{
    service:'Gmail',
    auth:{
        user:credentials.gmail.user,
        pass:credentials.gmail.password
    }
})

Nodemailer为大多数流行的邮件服务提供了快捷方式,如果你的MSA没有出现在这个列表上,或者你需要直接连接一个SMTP服务器,它也支持:

var mailTransport = nodemailer.createTransport('SMTP',{
    host:'smtp.pig1024.me',
    secureConnection:true,//使用SSL端口:465
    auth:{
        user:credentials.gmail.user,
        pass:credentials.gmail.password
    }
})

发送邮件

发送邮件需要注意的是,没有错误不一定表示邮件成功发送给接受者,只有在跟MSA通信出现问题的时候才会设置回调函数的err参数,比如网络或授权错误。如果MSA不能投递邮件,比如因为无效的邮件地址或未知的用户,你会收到一封投递给MSA账号的失败邮件。

mailTransport.sendMail({
    from:'"sky" <info@pig1024.me>',
    toL'aaa@gmail.com',
    subject:'subject',
    text:'thanks'
},function(err){
    if(err) console.log('unable to send email')
})

如果你需要系统自动判断邮件是否投递成功,有两个选择:

  1. 使用支持错误报告的MSA,亚马逊的简单邮件服务SES就是这样的服务
  2. 选择直接投递,跳过MSA,这是一个复杂的方案,并且很可能被标记为垃圾邮件

发送多个接收者

Nodemail支持发送邮件给多个接收者,只要把他们逗号分隔开。

mailTransport.sendMail({
    from:'"sky" <info@pig1024.me>',
    to:'aaa@gmail.com,"Jane" <june@yahoo.com>'
    subject:'subject',
    text:'thanks'
},function(err){
    if(err) console.log('unable to send email')
})

注意:普通邮件地址(aaa@qq.com)和指定了接收者姓名的地址"aaa aaa@qq.com"混合在一起,这种语法是可以的。

在向多个接收者发送邮件时,必须注意观察MSA的限制。比如限制每封邮件接受者的上限,这时候就需要按照上限多次发送。

发送HTML邮件

现在大多数人都想看到更漂亮的邮件,Nodemailer允许你在同一封邮件里发送HTML和普通文本两种版本,让邮件客户端选择显示哪个版本(一般是HTML)。

mailTransport.sendMail({
    from:'"sky" <info@pig1024.me>',
    to:'aaa@gmail.com,"Jane" <june@yahoo.com>'
    subject:'subject',
    html:'<b>thanks</b>'
    text:'thanks'
},function(err){
    if(err) console.log('unable to send email')
})

如上做法工作量加大。额Nodemailer会自动将HTML翻译成普通文本,如果需要这么做的:

mailTransport.sendMail({
    from:'"sky" <info@pig1024.me>',
    to:'aaa@gmail.com,"Jane" <june@yahoo.com>',
    subject:'subject',
    html:'<b>thanks</b>',
    generateTextFromHtml:true
},function(err){
    if(err) console.log('unable to send email')
})

邮件其他处理

邮件图片

尽管可以在HTML邮件中嵌入图片,但不建议这么做,这会值得邮件变得臃肿,推荐的做法是把邮件中的图片放在Web服务器上,并在邮件中放入正确的链接。

用视图发送HTML

把HTML字符串放入JavaScript应该避免的一种做法, 如果使用HTML Email Boilerplate,你还会想将套路化代码放到字符串里吗?

如果使用模板的话,代码如何处理呢?就需要说到res.render妙用的。

res.render('thanks',{layout":null,data:data},function(err,html){
    if(err){
        console.log('error in email template');
    }
    mailTransport.sendMail({
        from:'"sky" <info@pig1024.me>',
        to:'aaa@gmail.com,"Jane" <june@yahoo.com>'
        subject:'subject',
        html:html
        generateTextFromHtml:true
    },function(err){
        if(err) console.log('unable to send email')
    })
});
res.render('thanks',{data:data})

正常情况下调用两次res.render,一般只调用一次,调用两次只会显示第一次调用的结果。在这里我们第一次调用避开了正常的渲染过程,提供了一个回调函数,这样可以阻止视图的结果渲染到浏览器中。相反回调函数在参数html中接受到渲染好的视图,我们只需要接受渲染好的HTML并发送邮件,指定layout为null,防止使用我们的布局文件。最后再调用一次res.render,这次结果会像往常一样将HTML相应给浏览器。

封装邮件功能

直接上DEMO代码:

var nodemailer = require('nodemailer');

module.exports = function (credentials) {
    var mailTransport = nodemailer.createTransport('SMTP',{
        service:'Gmail',
        auth:{
            user:credentials.gmail.user,
            pass:credentials.gmail.password
        }
    });

    var from = '"aaa" <aaa@qq.com>';
    var errprRecipient = 'bbb@qq.com';

    return {
        send:function (to,subj,body) {
            mailTransport.sendMail({
                from:from,
                to:to,
                subject:subj,
                html:body,
                generateTextFromHtml:true
            },function(err){
                if(err) console.log('unable to send email')
            })
        },

        emailError:function (message,filename,exception) {
            var body = message + exception + filename;
            mailTransport.sendMail({
                from:from,
                to:errprRecipient,
                subject:'Website Error',
                html:body,
                generateTextFromHtml:true
            },function(err){
                if(err) console.log('unable to send email')
            })
        }
    }
}

// 使用
var emailService = require('./lib/email.js')(credentials);
emailService.send();

emailError方法可用来做网站监测工具,当网站出现问题时,发送邮件给开发者。



留言