diff --git a/packages/server/modules/emails/utils/transporter.ts b/packages/server/modules/emails/utils/transporter.ts index 8fdbfc733..805c9ad5e 100644 --- a/packages/server/modules/emails/utils/transporter.ts +++ b/packages/server/modules/emails/utils/transporter.ts @@ -1,6 +1,14 @@ import { emailLogger as logger } from '@/observability/logging' import { MisconfiguredEnvironmentError } from '@/modules/shared/errors' -import { isEmailEnabled, isTestEnv } from '@/modules/shared/helpers/envHelper' +import { + getEmailHost, + getEmailPassword, + getEmailPort, + getEmailUsername, + isEmailEnabled, + isSecureEmailEnabled, + isTestEnv +} from '@/modules/shared/helpers/envHelper' import type { Transporter } from 'nodemailer' import { createTransport } from 'nodemailer' @@ -11,18 +19,23 @@ const createJsonEchoTransporter = () => createTransport({ jsonTransport: true }) const initSmtpTransporter = async () => { try { const smtpTransporter = createTransport({ - host: process.env.EMAIL_HOST || '127.0.0.1', - port: parseInt(process.env.EMAIL_PORT || '587'), - secure: process.env.EMAIL_SECURE === 'true', + host: getEmailHost(), + port: getEmailPort(), + secure: isSecureEmailEnabled(), auth: { - user: process.env.EMAIL_USERNAME, - pass: process.env.EMAIL_PASSWORD + user: getEmailUsername(), + pass: getEmailPassword() }, pool: true, maxConnections: 20, maxMessages: Infinity }) - await smtpTransporter.verify() + const transporterVerified = await smtpTransporter.verify() + if (!transporterVerified) { + logger.error( + '📧 Email provider is likely misconfigured as validation failed, check config variables' + ) + } return smtpTransporter } catch (e) { logger.error(e, '📧 Email provider is misconfigured, check config variables.') diff --git a/packages/server/modules/shared/helpers/envHelper.ts b/packages/server/modules/shared/helpers/envHelper.ts index 22c6fbedc..d229007b1 100644 --- a/packages/server/modules/shared/helpers/envHelper.ts +++ b/packages/server/modules/shared/helpers/envHelper.ts @@ -334,10 +334,6 @@ export function getOnboardingStreamCacheBustNumber() { return parseInt(val) || 1 } -export function getEmailFromAddress() { - return getStringFromEnv('EMAIL_FROM') -} - export function getMaximumProjectModelsPerPage() { return getIntFromEnv('MAX_PROJECT_MODELS_PER_PAGE', '500') } @@ -373,6 +369,30 @@ export function isEmailEnabled() { return getBooleanFromEnv('EMAIL') } +export function getEmailFromAddress() { + return getStringFromEnv('EMAIL_FROM') +} + +export function getEmailHost() { + return process.env.EMAIL_HOST || '127.0.0.1' +} + +export function getEmailPort() { + return getIntFromEnv('EMAIL_PORT', '587') +} + +export function isSecureEmailEnabled() { + return getBooleanFromEnv('EMAIL_SECURE', true) // default to secure +} + +export function getEmailUsername() { + return getStringFromEnv('EMAIL_USERNAME', { unsafe: true }) // can be empty +} + +export function getEmailPassword() { + return getStringFromEnv('EMAIL_PASSWORD', { unsafe: true }) // can be empty +} + export const getFileImporterQueuePostgresUrl = () => process.env['FILEIMPORT_QUEUE_POSTGRES_URL'] ?? null