在如今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')
})
如果你需要系统自动判断邮件是否投递成功,有两个选择:
- 使用支持错误报告的MSA,亚马逊的简单邮件服务SES就是这样的服务
- 选择直接投递,跳过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方法可用来做网站监测工具,当网站出现问题时,发送邮件给开发者。