{"version":3,"file":"addressing.mjs","sources":["../src/addressing.ts"],"sourcesContent":["/**\n * Address parsing and grouping — aligned with the legacy `sendmail` npm package\n * (guileen/node-sendmail) behavior for recipient grouping and domain extraction.\n */\n\n/** Extract bare email from `Name ` or return trimmed input (linear time, no regex). */\nexport function extractEmail(address: string): string {\n const trimmed = address.trim();\n const open = trimmed.indexOf('<');\n if (open === -1) {\n return trimmed;\n }\n const close = trimmed.indexOf('>', open + 1);\n if (close === -1) {\n return trimmed;\n }\n return trimmed.slice(open + 1, close).trim();\n}\n\n/** Split address lists (legacy package accepted both string and array). */\nexport function parseAddressList(addresses: string | string[] | undefined): string[] {\n if (!addresses) {\n return [];\n }\n if (Array.isArray(addresses)) {\n return addresses.map((a) => extractEmail(String(a))).filter((a) => a.length > 0);\n }\n return addresses\n .split(',')\n .map((a) => extractEmail(a))\n .filter((a) => a.length > 0);\n}\n\n/** Legacy sendmail host extraction regex from guileen/node-sendmail@1.6.1. */\nconst LEGACY_HOST_REGEX = /[^@]+@([\\w\\d\\-.]+)/;\n\n/**\n * Do not run the legacy regex on unbounded input (defense in depth; the pattern is not ReDoS-prone,\n * but capping work is cheap and matches RFC 5321 practical address size expectations).\n */\nconst MAX_INPUT_LEN_FOR_LEGACY_HOST_REGEX = 320;\n\n/** Domain part of an email address (after the last `@`). */\nexport function getHostFromAddress(email: string): string | undefined {\n const normalized = extractEmail(email);\n if (normalized.length > MAX_INPUT_LEN_FOR_LEGACY_HOST_REGEX) {\n return undefined;\n }\n const match = LEGACY_HOST_REGEX.exec(normalized);\n return match?.[1];\n}\n\n/** Group recipient addresses by recipient domain (MX routing key). */\nexport function groupRecipientsByDomain(recipients: string[]): Record {\n const groups: Record = {};\n for (const raw of recipients) {\n const host = String(getHostFromAddress(raw));\n if (!groups[host]) {\n groups[host] = [];\n }\n groups[host].push(raw);\n }\n return groups;\n}\n\n/** Collect all recipients from to / cc / bcc (same sources as legacy sendmail). */\nexport function collectRecipients(mail: {\n to?: string | string[];\n cc?: string | string[];\n bcc?: string | string[];\n}): string[] {\n return [\n ...parseAddressList(mail.to),\n ...parseAddressList(mail.cc),\n ...parseAddressList(mail.bcc),\n ];\n}\n"],"names":["extractEmail","address","trimmed","trim","open","indexOf","close","slice","parseAddressList","addresses","Array","isArray","map","a","String","filter","length","split","LEGACY_HOST_REGEX","MAX_INPUT_LEN_FOR_LEGACY_HOST_REGEX","getHostFromAddress","email","normalized","undefined","match","exec","groupRecipientsByDomain","recipients","groups","raw","host","push","collectRecipients","mail","to","cc","bcc"],"mappings":"AAAA;;;AAGC,0GAGM,SAASA,aAAaC,OAAe,EAAA;IAC1C,MAAMC,OAAAA,GAAUD,QAAQE,IAAI,EAAA;IAC5B,MAAMC,IAAAA,GAAOF,OAAAA,CAAQG,OAAO,CAAC,GAAA,CAAA;IAC7B,IAAID,IAAAA,KAAS,EAAC,EAAG;QACf,OAAOF,OAAAA;AACT,IAAA;AACA,IAAA,MAAMI,KAAAA,GAAQJ,OAAAA,CAAQG,OAAO,CAAC,KAAKD,IAAAA,GAAO,CAAA,CAAA;IAC1C,IAAIE,KAAAA,KAAU,EAAC,EAAG;QAChB,OAAOJ,OAAAA;AACT,IAAA;AACA,IAAA,OAAOA,QAAQK,KAAK,CAACH,IAAAA,GAAO,CAAA,EAAGE,OAAOH,IAAI,EAAA;AAC5C;AAEA,4EACO,SAASK,gBAAAA,CAAiBC,SAAwC,EAAA;AACvE,IAAA,IAAI,CAACA,SAAAA,EAAW;AACd,QAAA,OAAO,EAAE;AACX,IAAA;IACA,IAAIC,KAAAA,CAAMC,OAAO,CAACF,SAAAA,CAAAA,EAAY;AAC5B,QAAA,OAAOA,SAAAA,CAAUG,GAAG,CAAC,CAACC,IAAMb,YAAAA,CAAac,MAAAA,CAAOD,CAAAA,CAAAA,CAAAA,CAAAA,CAAKE,MAAM,CAAC,CAACF,CAAAA,GAAMA,CAAAA,CAAEG,MAAM,GAAG,CAAA,CAAA;AAChF,IAAA;AACA,IAAA,OAAOP,UACJQ,KAAK,CAAC,GAAA,CAAA,CACNL,GAAG,CAAC,CAACC,CAAAA,GAAMb,YAAAA,CAAaa,CAAAA,CAAAA,CAAAA,CACxBE,MAAM,CAAC,CAACF,CAAAA,GAAMA,CAAAA,CAAEG,MAAM,GAAG,CAAA,CAAA;AAC9B;AAEA,+EACA,MAAME,iBAAAA,GAAoB,oBAAA;AAE1B;;;AAGC,IACD,MAAMC,mCAAAA,GAAsC,GAAA;AAE5C,6DACO,SAASC,kBAAAA,CAAmBC,KAAa,EAAA;AAC9C,IAAA,MAAMC,aAAatB,YAAAA,CAAaqB,KAAAA,CAAAA;IAChC,IAAIC,UAAAA,CAAWN,MAAM,GAAGG,mCAAAA,EAAqC;QAC3D,OAAOI,SAAAA;AACT,IAAA;IACA,MAAMC,KAAAA,GAAQN,iBAAAA,CAAkBO,IAAI,CAACH,UAAAA,CAAAA;IACrC,OAAOE,KAAAA,GAAQ,CAAA,CAAE;AACnB;AAEA,uEACO,SAASE,uBAAAA,CAAwBC,UAAoB,EAAA;AAC1D,IAAA,MAAMC,SAAmC,EAAC;IAC1C,KAAK,MAAMC,OAAOF,UAAAA,CAAY;QAC5B,MAAMG,IAAAA,GAAOhB,OAAOM,kBAAAA,CAAmBS,GAAAA,CAAAA,CAAAA;AACvC,QAAA,IAAI,CAACD,MAAM,CAACE,IAAAA,CAAK,EAAE;YACjBF,MAAM,CAACE,IAAAA,CAAK,GAAG,EAAE;AACnB,QAAA;AACAF,QAAAA,MAAM,CAACE,IAAAA,CAAK,CAACC,IAAI,CAACF,GAAAA,CAAAA;AACpB,IAAA;IACA,OAAOD,MAAAA;AACT;AAEA,oFACO,SAASI,iBAAAA,CAAkBC,IAIjC,EAAA;IACC,OAAO;AACFzB,QAAAA,GAAAA,gBAAAA,CAAiByB,KAAKC,EAAE,CAAA;AACxB1B,QAAAA,GAAAA,gBAAAA,CAAiByB,KAAKE,EAAE,CAAA;AACxB3B,QAAAA,GAAAA,gBAAAA,CAAiByB,KAAKG,GAAG;AAC7B,KAAA;AACH;;;;"}