Nodejs nodemailer不支持中文文件名吗?如何解决?
Nodejs nodemailer不支持中文文件名吗?如何解决?
在使用nodemailer发送邮件时,如果带有中文文件名的附件,虽然发送成功了,但是在收件箱里面看到的文件名是错的。 例如,我通过如下配置发送了2个附件:
var mailOptions = {
...
attachments: [
{ filename: '韩安.jpg',
path: '/Users/hanan/project/ksend/韩安.jpg'
},
{ filename: 'README哈哈.md',
path: '/Users/hanan/project/ksend/README哈哈.md'
}
]
...
}
发送成功了,但是到收件箱一看,附件文件名变成了下面这样子:
tcmime.1388.1527.1742.bin
tcmime.2438.2598.2671.bin
如何解决呢?
在使用nodemailer发送邮件时,如果带有中文文件名的附件,虽然发送成功了,但是在收件箱里面看到的文件名是错的。 例如,我通过如下配置发送了2个附件:
var mailOptions = {
...
attachments: [
{ filename: '韩安.jpg',
path: '/Users/hanan/project/ksend/韩安.jpg'
},
{ filename: 'README哈哈.md',
path: '/Users/hanan/project/ksend/README哈哈.md'
}
]
...
}
发送成功了,但是到收件箱一看,附件文件名变成了下面这样子:
tcmime.1388.1527.1742.bin
tcmime.2438.2598.2671.bin
如何解决呢?
在使用 nodemailer
发送带有中文文件名的附件时,可能会遇到文件名乱码或显示不正确的问题。这通常是因为编码问题导致的。为了解决这个问题,我们需要对附件的文件名进行适当的编码处理。
以下是具体步骤和示例代码:
解决方案
- 使用
quoted-printable
编码:将文件名转换为quoted-printable
编码格式。 - 设置
Content-Disposition
头:确保邮件客户端能够正确识别并显示中文文件名。
示例代码
const nodemailer = require('nodemailer');
const fs = require('fs');
const { createQuotedPrintable } = require('emailjs-mime-codec');
// 创建一个 nodemailer 运输工具
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'your-email@gmail.com',
pass: 'your-password'
}
});
// 准备邮件数据
let mailOptions = {
from: 'your-email@gmail.com', // 发件人
to: 'recipient@example.com', // 收件人
subject: '邮件主题', // 邮件主题
text: '邮件正文', // 邮件正文
attachments: [
{
filename: '韩安.jpg',
path: '/Users/hanan/project/ksend/韩安.jpg',
contentDisposition: `attachment; filename*=UTF-8''${createQuotedPrintable('韩安.jpg')}`
},
{
filename: 'README哈哈.md',
path: '/Users/hanan/project/ksend/README哈哈.md',
contentDisposition: `attachment; filename*=UTF-8''${createQuotedPrintable('README哈哈.md')}`
}
]
};
// 发送邮件
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Email sent: ' + info.response);
});
解释
- 创建 Quoted-Printable 编码:我们使用
emailjs-mime-codec
库中的createQuotedPrintable
方法来生成quoted-printable
编码的文件名。 - 设置
contentDisposition
:在附件对象中添加contentDisposition
属性,并将其值设置为filename*
,以确保邮件客户端能够正确解析和显示中文文件名。
通过上述方法,可以确保在发送包含中文文件名的附件时,文件名能够在收件箱中正确显示。
今天在github给作者提issue,作者意思可能是接收方的问题: https://github.com/andris9/Nodemailer/issues/374#issuecomment-68522370 由于之前使用QQ邮箱接收的,换了下163邮箱,果然是好的。
当使用 nodemailer
发送包含中文文件名的附件时,默认情况下可能会遇到文件名乱码或显示为二进制文件名的情况。这是因为 MIME 编码规则对于非英文字符的支持不够友好。
为了正确处理中文文件名,可以使用 RFC2231
编码,这是一种标准的 MIME 编码方式,用于处理多字节字符。下面是解决这个问题的示例代码:
const nodemailer = require('nodemailer');
// 创建一个SMTP传输对象
let transporter = nodemailer.createTransport({
host: "smtp.example.com",
port: 587,
secure: false, // 使用SSL/TLS
auth: {
user: 'your-email@example.com', // 用户名
pass: 'your-password' // 密码
}
});
let mailOptions = {
from: '"Your Name" <your-email@example.com>', // 发件人
to: 'recipient@example.com', // 收件人
subject: '邮件主题',
text: '邮件正文',
attachments: [
{
filename: Buffer.from('韩安.jpg').toString('base64'),
path: '/Users/hanan/project/ksend/韩安.jpg',
contentDisposition: 'attachment; filename*=UTF-8\'\'' + encodeURIComponent('韩安.jpg')
},
{
filename: Buffer.from('README哈哈.md').toString('base64'),
path: '/Users/hanan/project/ksend/README哈哈.md',
contentDisposition: 'attachment; filename*=UTF-8\'\'' + encodeURIComponent('README哈哈.md')
}
]
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
});
在这个例子中,我们使用了 filename*
属性,并且通过 encodeURIComponent
对中文文件名进行了编码,这样就可以保证文件名在邮件客户端中正确显示了。
此外,也可以考虑使用一些库来帮助处理文件名的编码问题,比如 email-templates
和 nodemailer-template-engine
等。