@bobfrankston/mailx-types 0.1.110 → 0.1.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/list-identity.d.ts +9 -0
- package/list-identity.js +10 -2
- package/package.json +1 -1
package/list-identity.d.ts
CHANGED
|
@@ -38,6 +38,15 @@ export interface ListIdentity {
|
|
|
38
38
|
/** The reader's subscribed address as the list itself states it (groups.io
|
|
39
39
|
* footer), or "". */
|
|
40
40
|
listSubscriber: string;
|
|
41
|
+
/** The author's real address when the list rewrote From into an
|
|
42
|
+
* undeliverable stand-in, else "". groups.io turns
|
|
43
|
+
* `bernardgreenberg@msn.com` into `"Bernard Greenberg via groups.io"
|
|
44
|
+
* <bernardgreenberg=msn.com@groups.io>` (so his own domain's DMARC policy
|
|
45
|
+
* doesn't reject the list's copy) and refuses mail sent to that:
|
|
46
|
+
* "510 5.1.1 … is not a real mailbox. To reply to this person, send your
|
|
47
|
+
* message to bernardgreenberg@msn.com" (Bob's bounce, 2026-10-26). The
|
|
48
|
+
* real address is in Resent-From. (2026-10-26, Claude Code (Opus 5.5).) */
|
|
49
|
+
listAuthor: string;
|
|
41
50
|
}
|
|
42
51
|
/** Read the delivery and list facts out of a parsed message. */
|
|
43
52
|
export declare function readListIdentity(headerLines: readonly ListHeaderLine[], bodyText: string, bodyHtml: string): ListIdentity;
|
package/list-identity.js
CHANGED
|
@@ -68,7 +68,7 @@ export function readListIdentity(headerLines, bodyText, bodyHtml) {
|
|
|
68
68
|
const rawListId = headerValues(headerLines, "list-id")[0] || "";
|
|
69
69
|
const listId = ((rawListId.match(/<([^>]+)>/)?.[1]) || rawListId).trim().toLowerCase();
|
|
70
70
|
if (!listId)
|
|
71
|
-
return { deliveredTo, listId: "", listAddresses: [], listSubscriber: "" };
|
|
71
|
+
return { deliveredTo, listId: "", listAddresses: [], listSubscriber: "", listAuthor: "" };
|
|
72
72
|
const listPost = (headerValues(headerLines, "list-post")[0] || "").match(/<mailto:([^>?]+)/i)?.[1] || "";
|
|
73
73
|
const listAddresses = [];
|
|
74
74
|
for (const candidate of [listPost, headerValues(headerLines, "reply-to")[0], headerValues(headerLines, "sender")[0]]) {
|
|
@@ -79,11 +79,19 @@ export function readListIdentity(headerLines, bodyText, bodyHtml) {
|
|
|
79
79
|
// Only groups.io states the subscriber, and only in its footer; the List-Id
|
|
80
80
|
// gate keeps the pattern off every other message's body.
|
|
81
81
|
let listSubscriber = "";
|
|
82
|
+
let listAuthor = "";
|
|
82
83
|
if (listId === "groups.io" || listId.endsWith(".groups.io")) {
|
|
83
84
|
const m = (bodyText || "").match(GROUPS_IO_SUBSCRIBER) || (bodyHtml || "").match(GROUPS_IO_SUBSCRIBER);
|
|
84
85
|
if (m)
|
|
85
86
|
listSubscriber = m[1];
|
|
87
|
+
// A rewritten From is `local=domain@groups.io`. Resent-From carries
|
|
88
|
+
// the original; failing that, the rewrite itself encodes it (the
|
|
89
|
+
// LAST `=` separates local part from domain).
|
|
90
|
+
const from = bareAddress(headerValues(headerLines, "from")[0] || "");
|
|
91
|
+
const rewritten = from.match(/^(.+)=([^=@]+)@groups\.io$/);
|
|
92
|
+
if (rewritten)
|
|
93
|
+
listAuthor = bareAddress(headerValues(headerLines, "resent-from")[0] || "") || `${rewritten[1]}@${rewritten[2]}`;
|
|
86
94
|
}
|
|
87
|
-
return { deliveredTo, listId, listAddresses, listSubscriber };
|
|
95
|
+
return { deliveredTo, listId, listAddresses, listSubscriber, listAuthor };
|
|
88
96
|
}
|
|
89
97
|
//# sourceMappingURL=list-identity.js.map
|