fix(watcher): handle wrapped Subject lines in forwarded emails
Update the parseForwardedHeader function to correctly join wrapped Subject lines before the To: line, ensuring accurate parsing of Gmail forwarded messages. Enhance tests to validate this behavior with Tokopedia email examples.
This commit is contained in:
@@ -13,6 +13,9 @@ export function extractEmail(from) {
|
|||||||
/**
|
/**
|
||||||
* Parse a Gmail "Forwarded message" header block from the body.
|
* Parse a Gmail "Forwarded message" header block from the body.
|
||||||
* Returns null if no forwarded header is present.
|
* Returns null if no forwarded header is present.
|
||||||
|
*
|
||||||
|
* Subject may wrap onto following lines without leading whitespace
|
||||||
|
* (Gmail plain-text fold), so we read until the To: line.
|
||||||
*/
|
*/
|
||||||
export function parseForwardedHeader(body) {
|
export function parseForwardedHeader(body) {
|
||||||
if (!body) return null;
|
if (!body) return null;
|
||||||
@@ -22,14 +25,14 @@ export function parseForwardedHeader(body) {
|
|||||||
|
|
||||||
const after = body.slice(idx);
|
const after = body.slice(idx);
|
||||||
const headerMatch = after.match(
|
const headerMatch = after.match(
|
||||||
/From:\s*(.+)\r?\nDate:\s*(.+)\r?\nSubject:\s*(.+)\r?\nTo:\s*(.+)/i,
|
/From:\s*(.+)\r?\nDate:\s*(.+)\r?\nSubject:\s*([\s\S]+?)\r?\nTo:\s*(.+)/i,
|
||||||
);
|
);
|
||||||
if (!headerMatch) return null;
|
if (!headerMatch) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
from: headerMatch[1].trim(),
|
from: headerMatch[1].trim(),
|
||||||
date: headerMatch[2].trim(),
|
date: headerMatch[2].trim(),
|
||||||
subject: headerMatch[3].trim(),
|
subject: headerMatch[3].replace(/\s+/g, " ").trim(),
|
||||||
to: headerMatch[4].trim(),
|
to: headerMatch[4].trim(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,7 +359,8 @@ Roby
|
|||||||
export const tokopediaMultiForwardedBody = `---------- Forwarded message ---------
|
export const tokopediaMultiForwardedBody = `---------- Forwarded message ---------
|
||||||
From: Tokopedia <noreply@tokopedia.com>
|
From: Tokopedia <noreply@tokopedia.com>
|
||||||
Date: Fri, Aug 21, 2026 at 12:39 AM
|
Date: Fri, Aug 21, 2026 at 12:39 AM
|
||||||
Subject: Pesanan Selesai: “sandal jepit ANDA pria casual...” dan 1 Item Lainnya
|
Subject: Pesanan Selesai: “sandal jepit ANDA pria casual...” dan 1 Item
|
||||||
|
Lainnya
|
||||||
To: <nasyarobby@gmail.com>
|
To: <nasyarobby@gmail.com>
|
||||||
|
|
||||||
Hai *Roby,*
|
Hai *Roby,*
|
||||||
|
|||||||
@@ -43,6 +43,16 @@ describe("parseForwardedHeader", () => {
|
|||||||
assert.equal(h.subject, "Pembayaran Berhasil!");
|
assert.equal(h.subject, "Pembayaran Berhasil!");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("joins wrapped Subject lines before To", () => {
|
||||||
|
const h = parseForwardedHeader(tokopediaMultiForwardedBody);
|
||||||
|
assert.ok(h);
|
||||||
|
assert.match(h.from, /noreply@tokopedia\.com/);
|
||||||
|
assert.equal(
|
||||||
|
h.subject,
|
||||||
|
"Pesanan Selesai: “sandal jepit ANDA pria casual...” dan 1 Item Lainnya",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("returns null when there is no Fwd block", () => {
|
it("returns null when there is no Fwd block", () => {
|
||||||
assert.equal(parseForwardedHeader(livinDirectBody), null);
|
assert.equal(parseForwardedHeader(livinDirectBody), null);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user