Decode QOutlook legacy MIME words

This commit is contained in:
Курнат Андрей
2026-06-01 08:22:01 +03:00
parent cf3d6b0b01
commit 472288badf
3 changed files with 12 additions and 14 deletions
+3
View File
@@ -37,6 +37,9 @@ describe("outlookMail helpers", () => {
it("декодирует UTF-8 MIME words и transfer encodings", () => {
expect(decodeMimeWords("=?UTF-8?B?0J/RgNC40LLQtdGC?=")).toBe("Привет");
expect(decodeMimeWords("=?windows-1251?B?z/Do4uXy?=")).toBe("Привет");
expect(decodeMimeWords("=?windows-1251?Q?=CF=F0=E8=E2=E5=F2?=")).toBe("Привет");
expect(decodeMimeWords("=?UTF-8?B?0J/RgNC4?= =?UTF-8?B?0LLQtdGC?=")).toBe("Привет");
expect(decodeTransferBody("0J/RgNC40LLQtdGC", "base64")).toBe("Привет");
expect(decodeTransferBody("=D0=9F=D1=80=D0=B8=D0=B2=D0=B5=D1=82", "quoted-printable")).toBe("Привет");
});
+7 -12
View File
@@ -457,18 +457,13 @@ function optionalAddressHeaders(message: MailMessage): string[] {
}
export function decodeMimeWords(value: string): string {
return value.replace(/=\?([^?]+)\?([bqBQ])\?([^?]+)\?=/g, (_match, charset: string, encoding: string, encoded: string) => {
const normalizedCharset = charset.toLowerCase();
if (normalizedCharset !== "utf-8" && normalizedCharset !== "utf8") {
return _match;
}
if (encoding.toLowerCase() === "b") {
return decodeUtf8Bytes(base64ToBytes(encoded));
}
return decodeUtf8Bytes(quotedPrintableToBytes(encoded.replace(/_/g, " ")));
});
return value
.replace(/(=\?[^?]+\?[bqBQ]\?[^?]+\?=)\s+(?==\?[^?]+\?[bqBQ]\?[^?]+\?=)/g, "$1")
.replace(/=\?([^?]+)\?([bqBQ])\?([^?]+)\?=/g, (match, charset: string, encoding: string, encoded: string) => {
const bytes = encoding.toLowerCase() === "b" ? base64ToBytes(encoded) : quotedPrintableToBytes(encoded.replace(/_/g, " "));
const decoded = decodeBytes(bytes, charset);
return decoded || match;
});
}
export function decodeTransferBody(body: string, encoding = "", charset = "utf-8"): string {