import { GetSystemSmtp, Patterns } from '../../util' import { InputSpec } from './builder/inputSpec' import { Value } from './builder/value' import { Variants } from './builder/variants' const securityVariants = Variants.of({ tls: { name: 'TLS', spec: InputSpec.of({ port: Value.dynamicText(async () => ({ name: 'Port', required: true, default: '465', disabled: 'Fixed for TLS', })), }), }, starttls: { name: 'STARTTLS', spec: InputSpec.of({ port: Value.select({ name: 'Port', default: '587', values: { '25': '25', '587': '587', '2525': '2525' }, }), }), }, }) /** * Creates an SMTP field spec with provider-specific defaults pre-filled. */ function smtpFields( defaults: { host?: string security?: 'starttls' | 'tls' hostDisabled?: boolean } = {}, ) { const hostSpec = Value.text({ name: 'Host', required: true, default: defaults.host ?? null, placeholder: 'smtp.example.com', }) return InputSpec.of({ host: defaults.hostDisabled ? hostSpec.withDisabled('Fixed for this provider') : hostSpec, security: Value.union({ name: 'Connection Security', default: defaults.security ?? 'tls', variants: securityVariants, }), from: Value.text({ name: 'From Address', required: true, default: null, placeholder: 'Example Name ', patterns: [Patterns.emailWithName], }), username: Value.text({ name: 'Username', required: true, default: null, }), password: Value.text({ name: 'Password', required: false, default: null, masked: true, }), }) } /** * Base SMTP settings with no provider-specific defaults. */ export const customSmtp = smtpFields() /** * Provider presets for SMTP configuration. * Each variant has SMTP fields pre-filled with the provider's recommended settings. */ export const smtpProviderVariants = Variants.of({ gmail: { name: 'Gmail', spec: smtpFields({ host: 'smtp.gmail.com', security: 'tls', hostDisabled: true, }), }, ses: { name: 'Amazon SES', spec: smtpFields({ host: 'email-smtp.us-east-1.amazonaws.com', security: 'tls', }), }, sendgrid: { name: 'SendGrid', spec: smtpFields({ host: 'smtp.sendgrid.net', security: 'tls', hostDisabled: true, }), }, mailgun: { name: 'Mailgun', spec: smtpFields({ host: 'smtp.mailgun.org', security: 'tls', hostDisabled: true, }), }, protonmail: { name: 'Proton Mail', spec: smtpFields({ host: 'smtp.protonmail.ch', security: 'tls', hostDisabled: true, }), }, other: { name: 'Other', spec: customSmtp, }, }) /** * System SMTP settings with provider presets. * Wraps smtpProviderVariants in a union for use by the system email settings page. */ export const systemSmtpSpec = InputSpec.of({ provider: Value.union({ name: 'Provider', default: 'gmail', variants: smtpProviderVariants, }), }) const smtpVariants = Variants.of({ disabled: { name: 'Disabled', spec: InputSpec.of({}) }, system: { name: 'System Credentials', spec: InputSpec.of({ customFrom: Value.text({ name: 'Custom From Address', description: 'A custom from address for this service. If not provided, the system from address will be used.', required: false, default: null, placeholder: 'Name ', patterns: [Patterns.emailWithName], }), }), }, custom: { name: 'Custom Credentials', spec: InputSpec.of({ provider: Value.union({ name: 'Provider', default: null as any, variants: smtpProviderVariants, }), }), }, }) /** * For service inputSpec. Gives users 3 options for SMTP: (1) disabled, (2) use system SMTP settings, (3) use custom SMTP settings with provider presets */ export const smtpInputSpec = Value.dynamicUnion(async ({ effects }) => { const smtp = await new GetSystemSmtp(effects).once() const disabled = smtp ? [] : ['system'] return { name: 'SMTP', description: 'Optionally provide an SMTP server for sending emails', default: 'disabled', disabled, variants: smtpVariants, } }, smtpVariants.validator)