Skip to content
← Public packages

@kody/agent-mail

AgentMail inboxes for agents: create/list inboxes, messages, threads, and Svix webhook ingress.

src/send-message.ts

79 lines · 2.6 KB · TypeScript
import {
	agentMailRequest,
	clean,
	encodePathSegment,
	requireConfirmOrDryRun,
} from './core.ts'

export type SendMessageInput = {
	inboxId: string
	to?: string | string[]
	cc?: string | string[]
	bcc?: string | string[]
	replyTo?: string | string[]
	subject?: string
	text?: string
	html?: string
	labels?: string[]
	headers?: Record<string, string>
	trackOpens?: boolean
	attachments?: Array<Record<string, unknown>>
	/** Preview the request without calling AgentMail. */
	dryRun?: boolean
	/** Required true for a live send (unless dryRun). */
	confirm?: boolean
}

/**
 * Send a new message from an AgentMail inbox.
 * Requires confirm: true for a live POST, or dryRun: true to preview.
 * Uses POST /v0/inboxes/{inbox_id}/messages/send.
 *
 * @param input.inboxId - AgentMail inbox id (required)
 * @param input.to - Recipient address or addresses
 * @param input.subject - Message subject
 * @param input.text - Plain text body
 * @param input.html - HTML body
 * @param input.dryRun - Preview without sending
 * @param input.confirm - Must be true for a live send
 * @returns Send result or dry-run preview
 *
 * @example
 * import sendMessage from 'kody:@kody/agent-mail/send-message'
 * const preview = await sendMessage({
 *   inboxId: 'inbox_123',
 *   to: 'user@example.com',
 *   subject: 'Hello',
 *   text: 'Hi from an agent',
 *   dryRun: true,
 * })
 */
export default async function sendMessage(input: SendMessageInput) {
	const mode = requireConfirmOrDryRun(input, 'send a live message')
	const inboxId = encodePathSegment(input.inboxId, 'inboxId')
	const body: Record<string, unknown> = {}
	if (input.to !== undefined) body.to = input.to
	if (input.cc !== undefined) body.cc = input.cc
	if (input.bcc !== undefined) body.bcc = input.bcc
	if (input.replyTo !== undefined) body.reply_to = input.replyTo
	if (clean(input.subject)) body.subject = clean(input.subject)
	if (input.text !== undefined) body.text = input.text
	if (input.html !== undefined) body.html = input.html
	if (Array.isArray(input.labels)) body.labels = input.labels
	if (input.headers && typeof input.headers === 'object') body.headers = input.headers
	if (input.trackOpens !== undefined) body.track_opens = Boolean(input.trackOpens)
	if (Array.isArray(input.attachments)) body.attachments = input.attachments

	const path = `/v0/inboxes/${inboxId}/messages/send`
	if (mode === 'dryRun') {
		return { dryRun: true as const, inboxId: clean(input.inboxId), path, body }
	}

	const result = await agentMailRequest({
		method: 'POST',
		path,
		body,
		label: 'AgentMail send message',
	})
	return { dryRun: false as const, inboxId: clean(input.inboxId), result }
}