{"record":{"id":"9c7756e76ca1ad5f","repo":"hcengineering/platform","slug":"smtp-config-is-required-for-custom-transporter","errorCode":null,"errorMessage":"SMTP config is required for custom transporter","messagePattern":"SMTP config is required for custom transporter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"services/mail/pod-mail/src/mail.ts","lineNumber":81,"sourceCode":"  getTransporter (email: string, password?: string): Transporter {\n    if (config.smtpConfig !== undefined && password != null && password !== '') {\n      return this.getCachedTransporter(email, password)\n    }\n    return this.transporter\n  }\n\n  private getCachedTransporter (email: string, password: string): Transporter {\n    const cacheKey = this.generateCacheKey(email, password)\n\n    // Check if transporter exists in cache\n    const cachedTransporter = this.transporterCache.get(cacheKey)\n    if (cachedTransporter !== undefined) {\n      return cachedTransporter\n    }\n\n    // Create new transporter and cache it\n    if (config.smtpConfig === undefined) {\n      throw new Error('SMTP config is required for custom transporter')\n    }\n    const newTransporter = getSmtpTransport(config.smtpConfig, email, password)\n    this.transporterCache.set(cacheKey, newTransporter)\n\n    return newTransporter\n  }\n\n  private generateCacheKey (email: string, password: string): string {\n    const passwordHash = this.generateHash(password)\n    return `${email}:${passwordHash}`\n  }\n\n  private generateHash (input: string): string {\n    return createHash('sha256').update(input).digest('hex')\n  }\n\n  close (): void {\n    this.transporterCache.clear()","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/mail/pod-mail/src/mail.ts#L63-L99","documentation":"The mail service caches nodemailer transporters per sender/identity (cacheKey). When a cache miss occurs and the request is for a custom (non-default) transporter, a valid smtpConfig must be present to build an SMTP transport; if config.smtpConfig is undefined the service cannot construct the transporter and throws. It is a configuration error, not a transient failure.","triggerScenarios":"Calling getTransporter (via getCachedTransporter) with a cache key that maps to a custom SMTP identity while the pod was started without smtpConfig (SMTP_HOST/SMTP_PORT/etc. unset), so the first send after startup fails; cache was cold because the process restarted.","commonSituations":"Deployed mail pod without SMTP env vars; ops removed SMTP config assuming a managed relay; different configuration between environments (staging had smtpConfig, prod doesn't); transporter cache evicted/restarted process surfacing the previously hidden misconfig.","solutions":["Provide SMTP configuration (host, port, credentials) to the mail pod via environment/config so config.smtpConfig is defined","Restart/redeploy the pod after adding the SMTP config","If using a default/managed transporter instead, route the send through the default identity rather than a custom one","Check that the code path selecting the custom transporter is intended for this sender"],"exampleFix":"// before (env)\n// SMTP settings missing\n// after (env)\nSMTP_HOST=smtp.example.com\nSMTP_PORT=587\nSMTP_USERNAME=...\nSMTP_PASSWORD=...","handlingStrategy":"validation","validationCode":"if (config.smtpConfig === undefined) {\n  throw new Error('Startup check failed: SMTP config missing for custom transporter')\n}","typeGuard":"function hasSmtpConfig(c: MailConfig): c is MailConfig & { smtpConfig: SmtpConfig } {\n  return c.smtpConfig !== undefined && typeof c.smtpConfig.host === 'string' && typeof c.smtpConfig.port === 'number'\n}","tryCatchPattern":"try {\n  await sendEmail(...)\n} catch (e) {\n  if (e.message.includes('SMTP config is required')) {\n    logger.error('SMTP not configured for custom transporter; check SMTP_* env vars')\n  } else throw e\n}","preventionTips":["Fail fast at pod startup if custom-transporter feature is enabled but smtpConfig is missing","Keep SMTP_* env vars in the deployment checklist for every environment","Monitor transporter-cache misses in prod to catch cold-start misconfigs","Document which senders require custom SMTP"],"tags":["configuration","smtp","email","missing-env-var"],"backgroundTag":"missing-smtp-config","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}