How to Fix SMTP Authentication Errors (535, 530, 534)
A practical, copy-paste friendly guide to debugging SMTP authentication failures across Gmail, Microsoft 365, SendGrid, and self-hosted servers.
A practical, copy-paste friendly guide to debugging SMTP authentication failures across Gmail, Microsoft 365, SendGrid, and self-hosted servers.
SMTP authentication errors return a 5xx response code that tells you exactly what the server rejected. The most common ones you will see are 535 (invalid credentials), 530 (authentication required), and 534 (mechanism too weak). Decoding the response is the fastest way to fix the problem instead of guessing.
When SMTPTester runs your check, it shows the exact reply string from the server. Read that first — it almost always names the cause. A server that says "5.7.8 Username and Password not accepted" is telling you something very different from "5.7.0 Must issue a STARTTLS command first", even though both look like generic failures inside your application logs.
The single most useful habit you can build is this: never debug SMTP from your application's error message. Application frameworks wrap, translate, and truncate SMTP replies. Always reproduce the failure against the raw server, then fix the root cause.
Before you change any code, run through this list. In our experience roughly nine out of ten authentication tickets are solved here:
Work top to bottom. Each step depends on the one above it, so fixing step 4 while step 2 is still wrong will simply produce a different error message.
This is the classic "wrong username or password" reply, but the underlying cause is usually subtler. Walk through this checklist:
A useful trick: change the password to a simple alphanumeric test value for five minutes. If authentication suddenly succeeds, your problem was encoding or escaping — not credentials.
A 530 reply means the server accepted your connection but refused to relay until you authenticate. Two common causes:
There is a third, less obvious cause. Some servers advertise AUTH only *after* STARTTLS completes. If your client reads the EHLO response before upgrading the connection, it sees no AUTH capability, silently skips authentication, and then trips over 530 at MAIL FROM. The fix is to re-issue EHLO after the TLS upgrade — a step the SMTP specification requires and a surprising number of hand-rolled clients skip.
The server requires a stronger mechanism than the one you offered. The most common scenario is presenting AUTH LOGIN over an unencrypted channel. Fix it by enabling STARTTLS on port 587 (or switch to implicit TLS on 465). If your client only supports plain auth, upgrade the library — modern providers will eventually drop legacy mechanisms entirely.
You will also meet 534 when a mailbox is protected by conditional access or modern authentication policies. In that case no password-based mechanism will ever succeed; the tenant expects XOAUTH2 with a token issued by the identity provider.
| Code | Meaning | Usual fix |
|---|---|---|
| 421 | Service not available, closing channel | Rate limit or throttling — slow down and retry |
| 454 4.7.0 | Temporary authentication failure | Provider-side issue; retry with backoff |
| 501 | Syntax error in parameters | Malformed Base64 or missing argument |
| 538 | Encryption required for requested mechanism | Enable STARTTLS before AUTH |
| 550 5.7.1 | Relay access denied | Authenticated, but not allowed to send as that address |
The distinction between 4xx and 5xx matters a great deal in production. A 4xx is temporary: queue the message and retry with exponential backoff. A 5xx is permanent: retrying the identical request will fail identically and only damages your sender reputation.
Understanding the wire protocol makes every error obvious. Here is a healthy session on port 587:
S: 220 smtp.example.com ESMTP ready
C: EHLO client.example.org
S: 250-smtp.example.com
S: 250-STARTTLS
S: 250-SIZE 35882577
S: 250 8BITMIME
C: STARTTLS
S: 220 2.0.0 Ready to start TLS
<TLS handshake>
C: EHLO client.example.org
S: 250-AUTH LOGIN PLAIN XOAUTH2
S: 250 8BITMIME
C: AUTH LOGIN
S: 334 VXNlcm5hbWU6
C: <base64 username>
S: 334 UGFzc3dvcmQ6
C: <base64 password>
S: 235 2.7.0 AcceptedThree details are worth memorising. First, AUTH is only advertised after STARTTLS on a correctly configured server. Second, the 334 challenges are Base64-encoded prompts, not errors. Third, 235 is the only success code for authentication — anything else is a failure, even if your library reports "connected".
For smtp.gmail.com on port 587 with STARTTLS:
Username: you@gmail.com
Password: <16-char app password>If you use Google Workspace, an administrator may also need to enable "Less secure app access" alternatives — typically by issuing OAuth-based credentials and switching to XOAUTH2. SMTP with app passwords still works for most Workspace tenants as of 2025.
Common Gmail-specific gotchas:
Microsoft 365 disables SMTP AUTH on new tenants by default. As an admin:
Use smtp.office365.com:587 with STARTTLS and the user's full UPN.
If the tenant enforces security defaults or a conditional access policy requiring multi-factor authentication, basic SMTP AUTH will keep failing no matter what you do to the mailbox. The supported paths are a high-volume connector with IP allow-listing, or OAuth 2.0 client credentials with the SMTP.Send permission.
Transactional providers use a fixed username (often the literal string apikey) and an API key as the password. Always generate a dedicated, scoped key for each application so you can rotate without breaking other services.
Provider-specific notes worth knowing:
apikey — not your account email.postmaster@yourdomain and a domain-scoped password; the EU and US regions have different hostnames.On a self-hosted stack the authentication decision is normally delegated from Postfix to Dovecot's SASL service. When authentication fails, check in this order:
/var/log/mail.log on the server — it names the exact reason, unlike the client-side reply.smtpd_sasl_auth_enable = yes in main.cf.smtpd_sasl_path matches Dovecot's unix_listener block.postfix user to read it.smtpd_tls_security_level = may (or encrypt on the submission port).A misconfigured socket permission is the single most common cause of a self-hosted 535 with correct credentials, and nothing in the client-side error hints at it.
Debugging tempts people into dangerous shortcuts. Avoid these:
A green check from SMTPTester means the server accepts you as a valid sender. Inbox placement is a separate layer:
Save yourself the next outage by codifying the process:
If you are seeing 5xx replies that are not on this list, paste the full server response into SMTPTester and we will surface the most likely cause in the recommendations panel.
The same authentication failure surfaces differently depending on your stack, and knowing the idiom saves time.
Node.js (Nodemailer). Set secure: false with requireTLS: true for port 587, or secure: true for 465. The most common mistake is leaving secure: true on port 587, which makes the client attempt a TLS handshake against a plaintext listener and hang until the timeout fires. Enable logger: true and debug: true while diagnosing to see the raw transcript.
Python (smtplib). Use SMTP(host, 587) followed by starttls(context=ssl.create_default_context()) and then login(). Use SMTP_SSL(host, 465) for implicit TLS. Calling login() before starttls() raises an SMTPNotSupportedError because AUTH is not advertised yet. smtp.set_debuglevel(1) prints the full conversation.
PHP (PHPMailer). Set SMTPSecure = 'tls' with Port = 587, or 'ssl' with Port = 465. SMTPDebug = 2 prints server replies. Never set SMTPOptions to disable peer verification, which is unfortunately the most-copied snippet on the internet.
Java (JavaMail). Set mail.smtp.starttls.enable=true and mail.smtp.starttls.required=true. Without the second property, JavaMail silently falls back to plaintext when the upgrade fails.
Go (net/smtp). The standard library refuses to send plaintext auth over an unencrypted connection, which trips people up on local test servers. Build the TLS connection explicitly and pass it to smtp.NewClient.
Most authentication outages are self-inflicted: someone rotated a password and a forgotten service kept using the old one.
A rotation that does not cause an incident looks like this:
The reason so many teams get this wrong is that they treat rotation as an edit rather than an add-then-remove. Overlapping credentials turn a risky change into a routine one.
Pair this with an inventory: a short document listing every system that authenticates to your mail server, which credential it uses, and who owns it. It takes an hour to write and prevents the "which service just started failing?" scramble entirely.
Credentials expire, get revoked, and get invalidated by policy changes that nobody told you about. The only reliable defence is a synthetic check.
Build a job that runs hourly, opens a connection to your relay, negotiates TLS, authenticates, and issues QUIT without sending a message. Alert if it fails twice in a row. This costs nothing, adds no sending volume, and turns a silent multi-hour outage into a five-minute fix.
Also alert on the failure *rate* in your application. A slow rise in 535s often precedes total failure — for example when a provider begins phasing out a mechanism and rejects a growing percentage of attempts.
Apply what you just learned. Free, no signup, results in seconds.
Open the tool →A complete guide to testing SMTP servers — online testing, telnet and openssl commands, TLS verification, authentication checks and a repeatable diagnostic workflow.
DeliverabilityHow bounces work, the difference between hard and soft bounces, how to parse DSN messages, build a suppression list, and keep bounce rates under control.