@softure-ai/mailing 0.2.4 → 0.2.5

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.
@@ -4,6 +4,7 @@ import { z } from "zod";
4
4
  import { hasLineBreak, isHeaderName, isIdempotencyKey, isListMailHeader, isMailKind, isReservedHeader, isSingleAddress, MAX_SUBJECT_LENGTH } from "../address.js";
5
5
  import { DEFAULT_ATTACHMENT_LIMITS, getContentTypeEssence, isAttachmentFilename, isContentType, type AttachmentLimits } from "../attachments.js";
6
6
  import { TRANSACTIONAL_KIND, type MailAttachment } from "../contract.js";
7
+ import { SENDER_NAME } from "../options.js";
7
8
 
8
9
  const headersSchema = z.record(z.string(), z.string()).superRefine((headers, context) => {
9
10
  for (const [name, value] of Object.entries(headers)) {
@@ -42,6 +43,7 @@ const mailFields = {
42
43
  .optional(),
43
44
  headers: headersSchema.optional(),
44
45
  replyTo: z.string().trim().refine(isSingleAddress).optional(),
46
+ sender: z.string().regex(SENDER_NAME).optional(),
45
47
  kind: z.string().refine(isMailKind).default(TRANSACTIONAL_KIND),
46
48
  };
47
49
 
@@ -78,6 +80,8 @@ export interface ValidMail {
78
80
  readonly headers: Readonly<Record<string, string>>;
79
81
  /** The mail's own reply-to; null to use the configured one. */
80
82
  readonly replyTo: string | null;
83
+ /** The name of a configured sender; null for `from`. Its value is looked up in the config (`resolveSender`). */
84
+ readonly sender: string | null;
81
85
  /** `transactional` or a list kind. */
82
86
  readonly kind: string;
83
87
  readonly idempotencyKey: string | null;
@@ -90,7 +94,7 @@ export type MailValidation = { readonly ok: true; readonly value: ValidMail } |
90
94
  /**
91
95
  * Checks one mail and its send options, its attachments against `limits` (default: the module's defaults; `sendMail`
92
96
  * passes the configured ones). `fields` lists what failed (`to`, `subject`, `text`, `html`, `headers`, `replyTo`,
93
- * `kind`, `attachments`, `idempotencyKey`, or `mail` when the input is not an object).
97
+ * `sender` (its shape only: whether the app configured it is `resolveSender`'s check), `kind`, `attachments`, `idempotencyKey`, or `mail` when the input is not an object).
94
98
  */
95
99
  export function validateMail(mail: unknown, options: unknown = {}, limits: AttachmentLimits = DEFAULT_ATTACHMENT_LIMITS): MailValidation {
96
100
  const parsedMail = getMailSchema(limits).safeParse(mail);
@@ -100,7 +104,7 @@ export function validateMail(mail: unknown, options: unknown = {}, limits: Attac
100
104
  const fields = new Set(issues.map((issue) => (issue.path.length === 0 ? "mail" : String(issue.path[0]))));
101
105
  return { ok: false, fields: [...fields] };
102
106
  }
103
- const { to, subject, text, html, headers, replyTo, kind, attachments = [] } = parsedMail.data;
107
+ const { to, subject, text, html, headers, replyTo, sender, kind, attachments = [] } = parsedMail.data;
104
108
  return {
105
109
  ok: true,
106
110
  value: {
@@ -110,6 +114,7 @@ export function validateMail(mail: unknown, options: unknown = {}, limits: Attac
110
114
  html: html ?? null,
111
115
  headers: headers ?? {},
112
116
  replyTo: replyTo ?? null,
117
+ sender: sender ?? null,
113
118
  kind,
114
119
  idempotencyKey: parsedOptions.data.idempotencyKey ?? null,
115
120
  attachments,