-
Notifications
You must be signed in to change notification settings - Fork 18
Description
(Bug报告:包含非ASCII字符的长邮件主题被错误截断,而非按RFC规范折行)
Library: https://deno.land/x/denomailer/mod.ts (Latest version as of June 2025)
Deno Version: v2.3.5 (or newer)
Bug Description:
When an email subject contains non-ASCII characters (e.g., CJK characters) and its Quoted-Printable encoded length exceeds an internal hardcoded threshold (approx. 72 characters for the payload, 84 for the full header), the library does not perform RFC 2047 header folding. Instead, it crudely truncates the encoded string. This results in a malformed Subject header, causing the recipient's mail client to display garbled text.
Purely ASCII subjects, even if they are very long, bypass this faulty encoding logic and are sent as-is, thus not triggering the bug. This makes the bug specific to internationalization (i18n) use cases.
(Bug描述:当邮件主题包含中日韩等非ASCII字符,并且其Quoted-Printable编码后的内容长度超过一个内部硬编码的阈值(约72个字符,完整邮件头约84个字符)时,denomailer库不会按照RFC 2047规范对邮件头进行折行(Folding),而是直接对编码后的字符串进行粗暴截断(Truncation)。这导致生成的邮件头损坏,收件方看到的邮件主题为乱码。纯ASCII字符长标题会绕过这个有缺陷的编码逻辑,因此不会触发此bug,使其成为一个国际化场景下的严重问题。)
Steps to Reproduce (复现步骤):
Save the following code as test.ts and run it with deno run --allow-net test.ts.
// test.ts
import { SMTPClient } from "https://deno.land/x/denomailer/mod.ts";
const client = new SMTPClient({
connection: {
hostname: "your_smtp_server.com",
port: 465,
tls: true,
auth: {
username: "your_username",
password: "your_password",
},
},
});
async function sendTestMail(subject: string) {
console.log(`\nTesting subject: "${subject}"`);
try {
await client.send({
from: "[email protected]",
to: ["[email protected]"],
subject: subject,
content: "This is a test.",
});
console.log("--> SUCCESS: Mail sent without error from library.");
} catch (e) {
console.error("--> FAILED: Library threw an error.", e);
}
}
// 8 Chinese characters - Encoded payload length is 72 chars. Should SUCCEED.
await sendTestMail("一二三四五六七八");
// 9 Chinese characters - Encoded payload length is 81 chars. Will FAIL (be truncated).
await sendTestMail("一二三四五六七八九");
await client.close();Expected Behavior (期望行为):
Both emails should be sent successfully, and the subjects should be displayed correctly in the recipient's mail client. The second, longer subject header should be folded into multiple lines in the raw email source according to RFC 2047.
Actual Behavior (实际行为):
The first email with 8 Chinese characters succeeds. The second email with 9 Chinese characters, while sent without an error from the library, arrives with a garbled subject. Analysis of the raw email header shows a truncated Quoted-Printable string, for example: Subject: =?utf-8?Q?=e4=b8=80=e4=b8=89=e4=b8=89=e5=9b=9b=e4=ba=94=e5=85=ad=e4=b8=83=e5=85=ab=e4=b9=9d?= (The string is cut off before the final characters and closing ?=).
Root Cause Analysis (根本原因分析):
The issue stems from a flawed implementation of RFC 2047 for long headers.
- The library correctly identifies strings with non-ASCII characters for encoding.
- It encodes them using Quoted-Printable.
- However, instead of implementing a proper line-folding mechanism for encoded strings exceeding a certain length (observed to be ~72 chars for the payload), it simply truncates the string.
- This truncation corrupts the multi-byte character sequence and creates an invalid header, leading to the garbled output.
Workaround / Recommendation for Other Users
(变通方案 / 给其他用户的建议)
Given that this bug is critical for any application supporting internationalization (i18n) and the denomailer library has not been updated in a significant amount of time, a reliable workaround is necessary for production environments.
The recommended solution is to leverage Deno's native support for npm packages and use a mature, actively maintained library from the Node.js ecosystem. Nodemailer is the industry standard for this. It correctly handles all RFC 2047 encoding and header folding.
This approach resolves the issue completely and provides a more robust and feature-rich email-sending capability.
(鉴于此bug对于任何需要国际化支持的应用都是致命的,并且 denomailer 库已长时间未更新,在生产环境中必须采用一个可靠的变通方案。)
(推荐的解决方案是利用Deno对npm包的原生支持,来使用一个来自Node.js生态的、成熟且仍在积极维护的库。Nodemailer 是这方面的行业标准,它能正确处理所有RFC 2047编码和邮件头折行问题。)
(这个方法可以彻底解决该问题,并提供一个更健壮、功能更丰富的邮件发送能力。)
Example using npm:nodemailer in Deno:
(在 Deno 中使用 npm:nodemailer 的示例:)
// Import Nodemailer directly using an npm specifier
import nodemailer from "npm:nodemailer";
// Create a transporter using the same SMTP credentials
const transporter = nodemailer.createTransport({
host: "your_smtp_server.com",
port: 465,
secure: true, // true for 465 (SSL/TLS)
auth: {
user: "your_username",
pass: "your_password",
},
});
// The same long subject that fails with denomailer
const longChineseSubject = "一二三四五六七八九";
console.log("Attempting to send with Nodemailer...");
// Send the email
const info = await transporter.sendMail({
from: '"Sender Name" <[email protected]>',
to: "[email protected]",
subject: longChineseSubject,
text: "This email was sent from Deno using Nodemailer and should have a correctly displayed subject.",
});
console.log(`Email sent successfully with Nodemailer! Message ID: ${info.messageId}`);