UNPKG

@upyo/core

Version:

Simple email sending library for Node.js, Deno, Bun, and edge functions

62 lines (60 loc) 2.96 kB
import { parseAddress } from "./address.js"; import { isAttachment } from "./attachment.js"; //#region src/message.ts /** * Creates a new email {@link Message} based on the provided constructor * parameters. This function provides a more convenient API for creating * messages compared to constructing a {@link Message} object directly. * * @example * ```typescript * const message = createMessage({ * from: "sender@example.com", * to: "recipient1@example.com", * subject: "Hello World", * content: { text: "This is a test message" } * }); * ``` * * @param constructor The constructor parameters for the message. Uses more * user-friendly types like accepting strings for email * addresses and `File` objects for attachments. * @returns A new {@link Message} object with all properties normalized and * validated. * @throws {TypeError} When any email address string cannot be parsed or when * an attachment object is invalid. */ function createMessage(constructor) { const sender = typeof constructor.from === "string" ? parseAddress(constructor.from) ?? throwTypeError(`Invalid sender address: ${JSON.stringify(constructor.from)}`) : constructor.from; return { sender, recipients: esureArray(constructor.to).map((to) => typeof to === "string" ? parseAddress(to) ?? throwTypeError(`Invalid recipient address: ${JSON.stringify(to)}`) : to), ccRecipients: esureArray(constructor.cc).map((cc) => typeof cc === "string" ? parseAddress(cc) ?? throwTypeError(`Invalid CC address: ${JSON.stringify(cc)}`) : cc), bccRecipients: esureArray(constructor.bcc).map((bcc) => typeof bcc === "string" ? parseAddress(bcc) ?? throwTypeError(`Invalid BCC address: ${JSON.stringify(bcc)}`) : bcc), replyRecipients: esureArray(constructor.replyTo).map((replyTo) => typeof replyTo === "string" ? parseAddress(replyTo) ?? throwTypeError(`Invalid reply-to address: ${JSON.stringify(replyTo)}`) : replyTo), attachments: esureArray(constructor.attachments).map((attachment) => { if (attachment instanceof File) return { inline: false, filename: attachment.name, content: attachment.arrayBuffer().then((b) => new Uint8Array(b)), contentType: attachment.type == null || attachment.type === "" ? "application/octet-stream" : attachment.type, contentId: `${crypto.randomUUID()}@${sender.address.replace(/^[^@]*@/, "")}` }; else if (isAttachment(attachment)) return attachment; else throwTypeError(`Invalid attachment: ${JSON.stringify(attachment)}`); }), subject: constructor.subject, content: constructor.content, priority: constructor.priority ?? "normal", tags: esureArray(constructor.tags), headers: new Headers(constructor.headers ?? {}) }; } function throwTypeError(message) { throw new TypeError(message); } function esureArray(value) { return Array.isArray(value) ? value : value == null ? [] : [value]; } //#endregion export { createMessage };