hcengineering/platform · error · Error

Both SMTP and SES configuration are specified, please specif

Error message

Both SMTP and SES configuration are specified, please specify only one

What it means

pod-mail supports exactly one delivery backend: SMTP or AWS SES, selected by the presence of SMTP_HOST / SES_ACCESS_KEY. If both are set, the config IIFE throws this error rather than guessing which backend to use.

Source

Thrown at services/mail/pod-mail/src/config.ts:154

    Host: host as string,
    Port: port,
    Username: username,
    Password: password,
    TlsMode: tlsMode ?? TlsOptions.UPGRADE,
    DebugLog: debugLog,
    AllowSelfSigned: allowSelfSigned
  }
}

const config: Config = (() => {
  const port = parseNumber(process.env[envMap.Port])
  if (port === undefined) {
    throw Error('Missing env variable: Port')
  }
  const isSmtpConfig = !isEmpty(process.env[envMap.SmtpHost])
  const isSesConfig = !isEmpty(process.env[envMap.SesAccessKey])
  if (isSmtpConfig && isSesConfig) {
    throw Error('Both SMTP and SES configuration are specified, please specify only one')
  }
  if (!isSmtpConfig && !isSesConfig) {
    throw Error('Please specify SES or SMTP configuration')
  }
  const params: Config = {
    port,
    source: process.env[envMap.Source],
    replyTo: process.env[envMap.ReplyTo],
    sesConfig: isSesConfig ? buildSesConfig() : undefined,
    smtpConfig: isSmtpConfig ? buildSmtpConfig() : undefined
  }

  return params
})()

export default config

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Decide on one backend and delete the other's variables: remove SES_ACCESS_KEY/SES_SECRET_KEY/SES_REGION to use SMTP, or remove SMTP_HOST (and SMTP_PORT etc.) to use SES.
  2. Audit layered env files (base + override) so only one backend's variables survive.
  3. Check for stale variables in k8s ConfigMaps/Secrets from previous deployments and strip them.

Example fix

// before
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SES_ACCESS_KEY=AKIA...
SES_SECRET_KEY=...
SES_REGION=us-east-1
// after
SMTP_HOST=smtp.example.com
SMTP_PORT=587
Defensive patterns

Strategy: validation

Validate before calling

const smtp = !!process.env.SMTP_HOST;
const ses = !!process.env.SES_ACCESS_KEY;
if (smtp && ses) {
  throw new Error('Both SMTP and SES configured; remove one backend before starting');
}

Try / catch

try {
  await import('./config');
} catch (err) {
  if (err instanceof Error && err.message.includes('Both SMTP and SES')) {
    console.error('Conflicting mail backends: keep only SMTP_HOST or only SES_ACCESS_KEY set');
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: Environment contains both a non-empty SMTP_HOST and a non-empty SES_ACCESS_KEY when pod-mail starts.

Common situations: Merging old SMTP config with newly added SES variables in the same .env; a shared base env plus an override layer each contributing one backend; leftover variables from a backend migration.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/ba3314e040385e3d. Report an issue: GitHub.