用nodemailer实现邮件发送

背景

由于随手记账本是基于小程序的,没办法直接通过浏览器下载的方式导出给用户。于是考虑在导出请求时,要求用户提供一个电子邮箱,后台生成导出的excel文件之后直接以附件的形式发送到用户邮箱中。目前是通过SendGrid提供的免费邮箱服务来实现邮箱发送。SendGrid也提供各个版本的webapi支持,不过考虑到后续兼容性,本次就摒弃了SendGrid提供的接口组件,使用nodemail

思路

发送邮件的方式基本大同小异,使用smtp协议的话需要知道:

  • 邮箱服务器地址
  • 端口号
  • 用户名
  • 密码

然后邮件内容上需要明确:

  • 收件人
  • 主题
  • 邮件内容
  • 是否为html格式
  • 附件
  • 发件人(如果通过个人邮箱开通smtp发件,那么可能不支持另外设置发件人。因为发件人就是自己,SendGrid是支持只是发件人的,比如`no-reply@torandom.com`。)

最后按照使用的邮件模块的说明发送即可。

实现

nodemailer的文档不是太直观,说明的很详细,但是没有一个完整的简单例子。普通的单次邮件发送主要有这么几个步骤:

  • 设置smtpConfig信息
  • 设置message信息
  • 创建transporter对象
  • 调用transporter对象的sendMail()发送邮件并接受回调

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const nodemailer = require('nodemailer')
// 配置邮件服务器信息
let smtpConfig = {
host: 'smtp.sendgrid.net',
port: 587,
secure: false, // upgrade later with STARTTLS
auth: {
user: 'username',
pass: 'password'
}
}
// 配置邮件内容信息
let message = {
from: 'no-reply@torandom.com',
to: 'test@torandom.com',
subject: '随手记账本 - 导出',
text: '随手记账本导出测试',
html: '<p>HTML version of the message</p>',
attachments: [
{
filename: 'package.json',
path: './package.json'
}
]
}
// 创建transporter对象
let transporter = nodemailer.createTransport(smtpConfig)
// 发送邮件
transporter.sendMail(message)
.then(info => {
if (info.accepted) {
console.log('已发送至' + info.accepted.toString())
} else {
console.log('邮件发送失败')
console.log(info)
}
})

注意

  • 在发送邮件部分。回调的info内容是由你的邮件服务器提供的,不同的邮件服务器提供的内容是不同的需要确认。

  • 如果测试代码的时候,发送到自己的QQ邮箱。发送的数量太多了的话,会有如下的报错:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    550 Connection frequency limited

    出错原因:该服务器IP的发信频率超过腾讯邮箱限制。

    腾讯邮箱对来自相同IP的外部发信服务器有一定的频率限制:
    1、超过每分钟发信量限制,此IP地址被禁止发信若干分钟。
    2、超过每小时发信量限制,此IP地址被禁止发信若干小时。
    3、超过每日发信量限制,此IP地址本日内禁止再发信。
    4、以上频率限制数值属于腾讯邮箱保密数据,恕不公开。

    改善建议:如果您是该服务器IP的管理员,请暂停该服务器IP的发信,稍后降低频率重新尝试发信。
    如果您是个人邮箱用户,请向您的电子邮件提供商报告此情况。

    https://service.mail.qq.com/cgi-bin/help?subtype=1&id=20022&no=1000722

    这时候需要把你的发件人加入到接受邮件的白名单中即可。

  • 关于nodemailer的更多高级用法,比如邮件池之列的请参考如下官方文档。

https://nodemailer.com/about/