#12933·neon

Console Auth SMTP test/save posts masked password (****last4) → SMTP 535

Author: 0xxmemoCreated Aug 20, 2026Updated Aug 20, 2026

Summary

Managed Better Auth custom SMTP in the Neon Console posts the UI-masked password (**** + last 4 characters) to POST .../auth/send_test_email instead of the real SMTP secret. Upstream (e.g. Resend) then returns 535 Authentication credentials invalid.

This is a console UI bug, not an SMTP-provider bug. The same credentials succeed when sent unmasked to the same API.

Steps to reproduce

  1. Project → branch → Auth → Configuration → Custom SMTP.
  2. Enter valid SMTP settings (example: Resend smtp.resend.com:465, username resend, password a live re_… API key, verified from-address).
  3. Save (password field becomes a mask like ****hDTh).
  4. Click Send test email.
  5. In Chrome DevTools → Network → send_test_email → Copy as fetch.

Actual result

Request body contains:

json
"password": "****hDTh"

(last 4 of the real secret, not the secret). Response:

json
{"success":false,"error_message":"Failed to send email to …: Invalid login: 535 Authentication credentials invalid"}

Expected result

Test (and save) should send the live password, or omit password and use the server-stored secret. Masked display values must never be used as AUTH credentials.

Proof the API is fine

From the same logged-in console origin, posting the unmasked password to the same endpoint:

POST /api/v2/projects/{project_id}/branches/{branch_id}/auth/send_test_email

returns { "success": true } and the message is delivered.

Direct SMTP with the same host/user/password (outside Neon) also authenticates and delivers.

Environment

  • Neon Console (production), universe web release around universe-86d2d274348ee (from Sentry release header on the failing request)
  • Auth: Managed Better Auth, custom SMTP (type: standard)
  • SMTP: Resend (smtp.resend.com, port 465)
  • Reproduced 2026-08-20

Suggested fix

  • Do not bind the password input’s submitted value when it still holds the display mask (/^\*+\S{0,4}$/ or equivalent).
  • For test-send: if the field is unchanged/masked, omit password and use the stored secret server-side.
  • For save: if the field is masked, treat as “no password change”.

Happy to share a HAR (redacted) if useful.