@maestro-js/mail 1.0.0-alpha.26 → 1.0.0-alpha.27

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/dist/index.d.ts CHANGED
@@ -19,11 +19,22 @@ interface MailAttachment {
19
19
  disposition?: string;
20
20
  contentId?: string;
21
21
  }
22
- interface MailHeaders {
22
+ type MailHeaders = {
23
23
  listUnsubscribePost?: string;
24
24
  listUnsubscribe?: string;
25
25
  replyTo?: MailAddress;
26
- }
26
+ /**
27
+ * Stable `Message-ID` (e.g. `<abc@your.domain>`) set explicitly so it can be stored and later
28
+ * reused in a thread's `References`. If omitted, the driver/transport generates one.
29
+ */
30
+ messageId?: string;
31
+ /** Parent message's `Message-ID` — becomes the `In-Reply-To` header. */
32
+ inReplyTo?: string;
33
+ /** Ordered chain of `Message-ID`s for the thread — becomes the `References` header. */
34
+ references?: string | string[];
35
+ } & {
36
+ [key: string]: string | string[] | MailAddress | undefined;
37
+ };
27
38
  interface MailEnvelope {
28
39
  to: MailAddress | MailAddress[];
29
40
  from?: MailAddress;
@@ -97,6 +108,7 @@ interface SendGrid {
97
108
  cc?: EmailData | EmailData[];
98
109
  bcc?: EmailData | EmailData[];
99
110
  from: EmailData;
111
+ replyTo?: EmailData;
100
112
  subject?: string;
101
113
  attachments?: {
102
114
  content: string;
@@ -106,6 +118,9 @@ interface SendGrid {
106
118
  contentId?: string;
107
119
  }[];
108
120
  category?: string;
121
+ headers?: {
122
+ [key: string]: string;
123
+ };
109
124
  customArgs?: {
110
125
  [key: string]: any;
111
126
  };
@@ -143,6 +158,7 @@ interface MailTrap {
143
158
  cc?: Address[];
144
159
  bcc?: Address[];
145
160
  from: Address;
161
+ reply_to?: Address;
146
162
  subject: string;
147
163
  text?: string;
148
164
  html?: string;
@@ -154,6 +170,7 @@ interface MailTrap {
154
170
  contentId?: string;
155
171
  }[];
156
172
  category?: string;
173
+ headers?: Record<string, string>;
157
174
  custom_variables?: Record<string, string | number | boolean>;
158
175
  } & ({
159
176
  text?: string;
@@ -352,7 +369,10 @@ declare namespace Mail {
352
369
  type Content = MailContent;
353
370
  /** File attachment with base64-encoded content, filename, optional MIME type and disposition */
354
371
  type Attachment = MailAttachment;
355
- /** Email headers: `listUnsubscribe`, `listUnsubscribePost`, and `replyTo` */
372
+ /**
373
+ * Email headers: well-known `replyTo`, `listUnsubscribe`, `listUnsubscribePost`, the threading
374
+ * headers `messageId`/`inReplyTo`/`references`, plus arbitrary string header keys.
375
+ */
356
376
  type Headers = MailHeaders;
357
377
  /** Complete email message: recipients, subject, content, optional attachments, headers, category, and extras */
358
378
  type Envelope = MailEnvelope;
package/dist/index.js CHANGED
@@ -2,6 +2,30 @@
2
2
  import "iso-fns2";
3
3
 
4
4
  // src/mail-types.ts
5
+ var KNOWN_MAIL_HEADER_KEYS = /* @__PURE__ */ new Set([
6
+ "listUnsubscribe",
7
+ "listUnsubscribePost",
8
+ "replyTo",
9
+ "messageId",
10
+ "inReplyTo",
11
+ "references"
12
+ ]);
13
+ function getCustomHeaders(headers) {
14
+ if (!headers) return {};
15
+ return Object.fromEntries(
16
+ Object.entries(headers).filter(([key, value]) => !KNOWN_MAIL_HEADER_KEYS.has(key) && typeof value === "string")
17
+ );
18
+ }
19
+ function getThreadingHeaders(headers) {
20
+ if (!headers) return {};
21
+ const out = {};
22
+ if (headers.messageId) out["Message-ID"] = headers.messageId;
23
+ if (headers.inReplyTo) out["In-Reply-To"] = headers.inReplyTo;
24
+ if (headers.references) {
25
+ out["References"] = Array.isArray(headers.references) ? headers.references.join(" ") : headers.references;
26
+ }
27
+ return out;
28
+ }
5
29
  function getEmails(address) {
6
30
  const list = Array.isArray(address) ? address : [address];
7
31
  return list.map((a) => typeof a === "string" ? a.trim() : a.email.trim());
@@ -25,10 +49,12 @@ function sendGridMailDriver(sendGrid) {
25
49
  cc: envelope.cc,
26
50
  bcc: envelope.bcc,
27
51
  from,
52
+ replyTo: envelope.headers?.replyTo,
28
53
  subject: envelope.subject ?? void 0,
29
54
  ...envelope.content,
30
55
  attachments: envelope.attachments,
31
56
  category: envelope.category ?? void 0,
57
+ headers: { ...getCustomHeaders(envelope.headers), ...getThreadingHeaders(envelope.headers) },
32
58
  customArgs: { ...envelope.extras ?? {}, __extraKeys__: JSON.stringify(Object.keys(envelope.extras ?? {})) }
33
59
  },
34
60
  false,
@@ -85,10 +111,12 @@ function mailTrapMailDriver(mailTrap) {
85
111
  cc: envelope.cc ? convertAddress(envelope.cc) : [],
86
112
  bcc: envelope.bcc ? convertAddress(envelope.bcc) : [],
87
113
  from: typeof envelope.from === "string" ? { email: envelope.from } : envelope.from,
114
+ reply_to: envelope.headers?.replyTo ? convertAddress(envelope.headers.replyTo)[0] : void 0,
88
115
  subject: envelope.subject ?? "",
89
116
  ...envelope.content,
90
117
  attachments: envelope.attachments,
91
118
  category: envelope.category ?? void 0,
119
+ headers: { ...getCustomHeaders(envelope.headers), ...getThreadingHeaders(envelope.headers) },
92
120
  custom_variables: Object.fromEntries(Object.entries(envelope.extras ?? {}).filter((e) => e[1] != null))
93
121
  }),
94
122
  {
@@ -165,7 +193,11 @@ function sesMailDriver(ses) {
165
193
  text: "text" in envelope.content ? envelope.content.text : void 0,
166
194
  html: "html" in envelope.content ? envelope.content.html : void 0,
167
195
  replyTo: replyToComposer,
196
+ messageId: envelope.headers?.messageId,
197
+ inReplyTo: envelope.headers?.inReplyTo,
198
+ references: envelope.headers?.references,
168
199
  headers: {
200
+ ...getCustomHeaders(envelope.headers),
169
201
  ...envelope.headers?.listUnsubscribe && { "List-Unsubscribe": envelope.headers.listUnsubscribe },
170
202
  ...envelope.headers?.listUnsubscribePost && { "List-Unsubscribe-Post": envelope.headers.listUnsubscribePost }
171
203
  },
package/package.json CHANGED
@@ -12,21 +12,21 @@
12
12
  "ics": "^3.8.1",
13
13
  "iso-fns2": "npm:iso-fns@2.0.0-alpha.26",
14
14
  "nodemailer": "^7.0.5",
15
- "@maestro-js/helpers": "1.0.0-alpha.26",
16
- "@maestro-js/service-registry": "1.0.0-alpha.26"
15
+ "@maestro-js/helpers": "1.0.0-alpha.27",
16
+ "@maestro-js/service-registry": "1.0.0-alpha.27"
17
17
  },
18
18
  "peerDependencies": {
19
- "@maestro-js/log": "1.0.0-alpha.26"
19
+ "@maestro-js/log": "1.0.0-alpha.27"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@react-email/render": "0.0.7",
23
23
  "@types/node": "^22.19.11",
24
24
  "@types/nodemailer": "^6.4.17",
25
25
  "@types/react": "^19.0.0",
26
- "@maestro-js/log": "1.0.0-alpha.26",
27
- "@maestro-js/queue": "1.0.0-alpha.26"
26
+ "@maestro-js/log": "1.0.0-alpha.27",
27
+ "@maestro-js/queue": "1.0.0-alpha.27"
28
28
  },
29
- "version": "1.0.0-alpha.26",
29
+ "version": "1.0.0-alpha.27",
30
30
  "publishConfig": {
31
31
  "access": "public"
32
32
  },