All files / lib/email/providers mailpit.provider.ts

100% Statements 13/13
100% Branches 2/2
100% Functions 2/2
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55                9x 9x               5x   5x 5x                         4x 1x 1x         3x 3x 3x   2x       2x            
import type { EmailProvider, EmailConfig } from "./base";
 
export class MailpitProvider implements EmailProvider {
	private apiUrl: string;
	private from: string;
 
	constructor(host: string, config: EmailConfig) {
		// Mailpit HTTP API endpoint (port 8025)
		this.apiUrl = `http://${host}:8025/api/v1/send`;
		this.from = config.from;
	}
 
	async sendEmail(params: {
		to: string;
		subject: string;
		html: string;
	}): Promise<{ id: string }> {
		const { to, subject, html } = params;
 
		try {
			const response = await fetch(this.apiUrl, {
				method: "POST",
				headers: {
					"Content-Type": "application/json",
				},
				body: JSON.stringify({
					From: { Email: this.from },
					To: [{ Email: to }],
					Subject: subject,
					HTML: html,
				}),
			});
 
			if (!response.ok) {
				const errorText = await response.text();
				throw new Error(
					`Mailpit API error: ${response.status} ${response.statusText} - ${errorText}`,
				);
			}
 
			const messageId = `mailpit-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
			console.log(`[EMAIL-MAILPIT] Email sent to ${to}: ${subject}`);
			return { id: messageId };
		} catch (error) {
			console.error(
				"[EMAIL-MAILPIT] Failed to send. Make sure Mailpit is running: docker-compose up mailpit",
				error,
			);
			throw new Error(
				`Failed to send email via Mailpit: ${(error as Error).message}`,
			);
		}
	}
}