Skip to main content
By default, candidate emails send from Record’s shared AWS SES sender. An org can instead connect their own mailbox — campaign emails then send from their own address via SMTP, with automatic fallback to Record’s sender if that mailbox ever fails.

Endpoints

All under /api/v1/settings/mailbox, JWT-authenticated, restricted to org owner/admin/superadmin. orgId passed as a query param.

Connect flow

  1. Sender name, from-email, and password (or app password) entered in the UI
  2. On blur of the email field, GET /suggest looks up the domain’s MX records (or a known-provider table) and pre-fills SMTP host/port — never an IMAP port like 993
  3. On submit, the backend opens a real SMTP connection with nodemailer and calls verify() — a genuine handshake and login, 15s timeout, nothing sent
  4. On success: password encrypted with AES-256-GCM, saved to Mongo (status: "connected")
  5. On failure: the raw SMTP error is mapped to a plain-English message (below) and returned as a 400

Error mapping

Provider notes

The most common failure isn’t a bug in the flow above — it’s a provider that rejects the account’s regular login password over SMTP outright, regardless of whether it’s typed correctly. Every mainstream provider except Microsoft has a fix (an app-specific password); Microsoft has none.

Gmail / Google Workspace

Google stopped accepting a regular account password for SMTP in 2022. Any attempt with the normal login password returns 535-5.7.8 ... BadCredentials — that message fires the same way whether the password is right or wrong.
1

Turn on 2-Step Verification

Sign in as the account you want to connect, go to myaccount.google.com/security, and turn on 2-Step Verification under “How you sign in to Google.” You’ll need a phone number or an authenticator app — App Passwords do not exist until this is on.
2

Open App Passwords

Go to myaccount.google.com/apppasswords.If instead you see “The setting you are looking for is not available for your account” — this is a Google Workspace (school/company-managed) account, and an org admin has disabled App Passwords entirely. No amount of 2-Step Verification on your end unlocks it; you need the Workspace admin to enable App Passwords, or use a different, personal mailbox instead.
3

Generate the password

Name it (e.g. “Record”) and create it. Google shows a 16-character code in four groups of four letters — copy it, spaces can be included or omitted.
4

Use it in Record

Paste that 16-character code into the Password field — not the Google account login password. Leave SMTP host/port as the auto-filled smtp.gmail.com / 465 and click Connect.

Zoho Mail

Confirmed against a live custom domain account. Two-factor authentication must already be turned on — Zoho won’t offer app passwords otherwise.
1

Sign in to Zoho Accounts

Go to accounts.zoho.com and sign in with the mailbox you’re connecting — it routes to the correct regional data center (e.g. India) automatically.
2

Open App Passwords

In the left sidebar, click Security, then find App Passwords (sometimes labeled “Application-Specific Passwords”).If it doesn’t appear at all even with 2FA on: this is a custom-domain/organization account, and a Zoho org admin may have the option disabled. Check the Zoho Mail Admin Console for that policy.
3

Generate the password

Click Generate New Password, name it (e.g. “Record Mailbox”), and confirm. Zoho shows the generated password once — copy it immediately, it can’t be viewed again afterward (only regenerated).
4

Use it in Record

Paste it into the Password field — not the regular Zoho login password. SMTP host is smtppro.zoho.<region> (e.g. smtppro.zoho.in) — check the account’s own Mail Accounts settings page for the exact value rather than assuming; reaching the AUTH step on a guessed host is not proof that host is correct. Port 465, click Connect.
Separately from app passwords: SMTP access can also be switched off per-account or per-org in the Zoho Mail Admin Console (Mail Settings → POP/IMAP/SMTP access policy). A persistent 535 with a password that’s definitely correct usually means this toggle, not the credentials.

Yahoo Mail

Not yet tested against a live account in this project, but Yahoo follows the same app-password pattern as Gmail and Zoho.
1

Sign in and open Account Security

Go to login.yahoo.com, then Account Info → Account Security.
2

Turn on Two-step verification

Same hard prerequisite as Gmail/Zoho — required before app passwords are offered.
3

Generate an app password

Scroll to the app password section, choose Generate and manage app passwords, pick “Other App,” label it (e.g. “Record”), and generate.
4

Use it in Record

Paste the generated password into the Password field — not the regular Yahoo login password. SMTP host smtp.mail.yahoo.com, port 465, click Connect.

Outlook / Microsoft 365 / Hotmail / Live — no fix exists

Microsoft retired password-based SMTP entirely, for personal and business accounts alike (final cutover April 2026). No app password and no admin setting brings it back — it fires the same 535 5.7.139 ... basic authentication is disabled whether the domain is custom or default, and whether or not the plan includes Teams. The only real path is Microsoft Graph API sending via an Azure AD app registration with Mail.Send permission, admin-consented on the tenant — a separate integration, not yet built.

Host auto-suggestion

GET /suggest resolves MX records to detect the actual mail platform behind a custom domain — the SMTP host is the provider’s server, not derivable from the domain itself.
Zoho’s suggested host tracks the actual data-center region from the MX record (.in, .eu, .com, …) — defaulting every custom domain to .com is wrong for accounts provisioned elsewhere, and is exactly the kind of mismatch that produces a confusing auth rejection.

Send-time behavior

Every campaign email calls emailService.sendEmail({ orgId, ... }):
  • No connected mailbox → sends via AWS SES (Record’s default), unchanged from before this feature existed
  • Connected mailbox → sends via a pooled nodemailer transporter for that org (reused across sends, not reconnected per email — avoids provider rate limits)
  • Send fails on an auth error (535/534) → mailbox flipped to status: "failing", and this send falls back to SES so the candidate still receives it
  • A failing mailbox shows an amber badge in Settings until reconnected (Edit Configuration, or Send test email)

Credential storage

The password is never stored in plaintext. AES-256-GCM, key from MAILBOX_CREDENTIALS_ENC_KEY (server env only — never alongside the ciphertext in the database). Decrypted in memory only when actually needed (verify, send, edit-reuse). No API response — including the org’s own GET /settings/mailbox — ever returns it.