Files
accounted/extensions/general/email/lib/email-provider.ts
T
Jakob Wennberg 523fba0419 feat(email): SMTP mailer behind the EmailService seam (EMAIL_PROVIDER=smtp); Resend stays the hosted default (#1746)
SmtpEmailService (nodemailer 9.0.5, exact-pinned) behind the existing EmailService seam. Provider resolution: EMAIL_PROVIDER wins, else RESEND_API_KEY selects Resend (hosted byte-identical), else SMTP_HOST selects SMTP. From header is built exactly like the Resend service after #1956 (no 'via <app>', fromAddress honored, platform-sender retry). STARTTLS is required by default (requireTLS) with SMTP_REQUIRE_TLS=false as an explicit opt-out for a plaintext LAN relay. Docs, env examples and the generated extension registry updated.
2026-08-30 11:54:47 +02:00

29 lines
1.2 KiB
TypeScript

import type { EmailService } from '@/lib/email/service'
import { ResendEmailService } from './resend-service'
import { SmtpEmailService } from './smtp-service'
export type EmailProviderKind = 'resend' | 'smtp'
/**
* Which outbound-mail implementation this deployment uses.
*
* 1. EMAIL_PROVIDER=resend|smtp wins when set (the escape hatch for a
* deployment that has both configured).
* 2. RESEND_API_KEY present: Resend. This keeps hosted byte-identical:
* adding SMTP variables on the side can never move hosted mail.
* 3. SMTP_HOST present: SMTP. The sovereign self-host path.
* 4. Otherwise Resend, whose isConfigured() is false, so email-dependent
* features degrade exactly as before (PDF download, no send).
*/
export function resolveEmailProvider(): EmailProviderKind {
const explicit = (process.env.EMAIL_PROVIDER ?? '').trim().toLowerCase()
if (explicit === 'resend' || explicit === 'smtp') return explicit
if (process.env.RESEND_API_KEY) return 'resend'
if (process.env.SMTP_HOST) return 'smtp'
return 'resend'
}
export function createEmailService(provider: EmailProviderKind = resolveEmailProvider()): EmailService {
return provider === 'smtp' ? new SmtpEmailService() : new ResendEmailService()
}