Endpoints
All under/api/v1/settings/mailbox, JWT-authenticated, restricted to org owner/admin/superadmin. orgId passed as a query param.
Connect flow
- Sender name, from-email, and password (or app password) entered in the UI
- On blur of the email field,
GET /suggestlooks up the domain’s MX records (or a known-provider table) and pre-fills SMTP host/port — never an IMAP port like 993 - On submit, the backend opens a real SMTP connection with
nodemailerand callsverify()— a genuine handshake and login, 15s timeout, nothing sent - On success: password encrypted with AES-256-GCM, saved to Mongo (
status: "connected") - 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 returns535-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
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 callsemailService.sendEmail({ orgId, ... }):
- No connected mailbox → sends via AWS SES (Record’s default), unchanged from before this feature existed
- Connected mailbox → sends via a pooled
nodemailertransporter 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
failingmailbox 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 fromMAILBOX_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.
