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

如何解决呢?


4 回复

在使用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 发送带有中文文件名的附件时,可能会遇到文件名乱码或显示不正确的问题。这通常是因为编码问题导致的。为了解决这个问题,我们需要对附件的文件名进行适当的编码处理。

以下是具体步骤和示例代码:

解决方案

  1. 使用 quoted-printable 编码:将文件名转换为 quoted-printable 编码格式。
  2. 设置 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);
});

解释

  1. 创建 Quoted-Printable 编码:我们使用 emailjs-mime-codec 库中的 createQuotedPrintable 方法来生成 quoted-printable 编码的文件名。
  2. 设置 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-templatesnodemailer-template-engine 等。

回到顶部