An SMTP 535 error means the server refused your login. The connection worked, the server was ready to talk, and then it rejected the user name and password (or the credential type) your application offered. The full reply usually reads 535 5.7.8 Authentication credentials invalid, and you may also see 535 5.7.3 Authentication unsuccessful, 535 Authentication failed or, in application logs, "SMTP Error: Could not authenticate". The fix is almost always in how the credentials are stored, copied or presented, not in the server. This guide explains exactly what the code means, lists the causes in the order we check them, shows how to reproduce the login by hand so you can tell a credential problem from a software problem, and gives a fix table for common setups. If you are looking for the wider family of reply codes, see SMTP bounce codes explained.
What error 535 actually means
SMTP authentication is defined in RFC 4954. After the connection is encrypted, the client sends an AUTH command with a mechanism such as PLAIN or LOGIN and its credentials. The server checks them and answers. A 235 reply means success. A 535 reply means the server understood the request but the credentials are not valid for that server. Because the check happens before any recipient or message is processed, a 535 never produces a bounce message. Your application gets the error immediately and the email is not sent or queued at the provider.
Related codes appear in the same stage and are worth knowing, because the fix differs. A 530 5.7.0 Authentication required reply means you tried to send without logging in at all. A 534 5.7.9 reply means the mechanism you chose is too weak for the server. A 538 5.7.11 reply means encryption is required for that mechanism. A 454 4.7.0 reply is a temporary authentication failure on the server side and is worth retrying after a short wait. Only 535 says that the credentials themselves were rejected.
The causes, in the order we check them
Most 535 errors come from a short list. Work through it from the top, because the first few explain the large majority of cases.
| Cause | What it looks like | Fix |
|---|---|---|
| Wrong user name or password | Worked before a change, or was copied from an old note | Open the SMTP settings page of your provider, copy the credentials again and paste them into a plain-text editor first |
| Hidden characters | A trailing space or a line break was copied with the password | Paste into a plain-text editor, remove spaces at both ends and copy again |
| Account password used instead of SMTP credentials | The dashboard login works but SMTP does not | Use the SMTP user name and password, or API key, generated for sending, not the web login |
| Special characters in a URL or DSN | Passwords with @, #, /, : or % fail in connection strings | URL-encode the password in the connection string, or use separate host, user and password settings |
| Credentials rotated or revoked | Everything stopped at the same moment | Create a new key, update every system that uses the old one and restart long-running workers |
| Wrong server | Credentials are valid but belong to another service | Check the host name against the dashboard and make sure staging and production values are not swapped |
| Wrong mechanism or no encryption first | The server wants TLS before it accepts AUTH | Use port 587 with STARTTLS or port 465 with implicit TLS and let the library negotiate the mechanism |
| Sender not allowed | The login works but the server restricts which From address the account may use | Send from an address on a domain you have verified in the account |
| Security rule at the provider | Repeated failures from one address lead to a temporary block | Stop the retry loop, fix the credentials and wait for the block to clear |
Check the settings before you test anything
Start with the plain facts. A correct SMTP configuration has five parts: a host name, a port, an encryption mode, a user name and a password. A mismatch in any one can end in a 535, because some servers answer a failed TLS negotiation or a wrong host with the same message. Use port 587 with STARTTLS unless you have a reason not to, or port 465 with implicit TLS. Port 25 is for server-to-server mail and is often blocked for application use, as we explain in which SMTP port to use. Our overview SMTP settings: ports, TLS and authentication lists the combinations that work.
Then look at where the credentials are stored. In a web application they usually live in environment variables, a .env file, a framework configuration file or a database table. Every one of those has its own quoting rules. A password containing a hash sign is cut off in some .env parsers unless it is wrapped in quotes. A password containing a dollar sign can be expanded as a variable in a shell. A password stored in a YAML or JSON file may need escaping. When credentials "look right" but fail, compare the length of the stored value with the length of the one in the dashboard. A difference of one character is a hidden space or a lost symbol.
Reproduce the login by hand
The quickest way to tell a credential problem from a software problem is to log in without your application. If the manual login fails, the credentials or the server are wrong. If it works, the problem is in your code or library configuration. You need nothing special: openssl and a base64 tool are on most systems. Replace the host with the one from your dashboard and keep the credentials out of shell history where you can.
openssl s_client -starttls smtp -crlf -connect smtp.example.com:587
# After the 250 replies, type:
EHLO test.local
AUTH LOGIN
# server answers 334 VXNlcm5hbWU6 (that is "Username:" in base64)
<base64 of your user name>
# server answers 334 UGFzc3dvcmQ6 (that is "Password:")
<base64 of your password>Create the base64 strings with printf %s "your-user" | base64. Use printf %s rather than echo so that no newline is added to the value, because a newline changes the result and produces a 535 that has nothing to do with your credentials. A reply of 235 2.7.0 Authentication successful means the login is good. A reply of 535 means it is not.
If you prefer one command, swaks sends a full test message and prints the whole conversation:
swaks --server smtp.example.com --port 587 --tls --auth LOGIN --auth-user "$SMTP_USER" --auth-password "$SMTP_PASS" --from [email protected] --to [email protected]The output shows which stage failed: connection, TLS, AUTH or the message itself. Our guide how to test an SMTP connection covers more variations, including PowerShell.
Special characters in passwords and connection strings
This cause deserves its own section because it is the one that surprises experienced developers. Many libraries accept a single connection string such as smtp://user:password@host:587. The characters @, :, /, #, ? and % have meaning in a URL, so a password that contains one of them is split in the wrong place and the server receives a different password than the one you typed. The fix is to percent-encode the user name and password inside the string. For example, p@ss becomes p%40ss. Most languages have a function for this: encodeURIComponent in JavaScript, rawurlencode in PHP and urllib.parse.quote in Python. If your framework also accepts separate fields for host, user and password, prefer those and avoid the problem altogether.
If you generate passwords, choose a long random string made of letters and digits. It is easier to move between systems and removes this class of error. Length gives the strength, not symbols.
Rotated keys and old values in long-running processes
When you create a new SMTP credential or rotate an API key, the old one stops working, and every place that still holds it starts to fail with a 535. The place people forget is a long-running process. A queue worker, a scheduler or a container started before the change keeps the old value in memory until it is restarted. If a framework caches its configuration, the cache holds the old value too. After any credential change, update the stored value, clear the configuration cache, restart workers and containers, and then send a test. Our guide how to rotate an API key lists the steps in order, and API key security and rotation explains how to plan it so that nothing breaks.
Fix table for common setups
| Where you see it | Typical message | What to check first |
|---|---|---|
| WordPress SMTP plugin | SMTP Error: Could not authenticate | Re-enter the user name and password by hand, set encryption to match the port and turn off any "use PHP mail" fallback |
| PHPMailer | SMTP ERROR: Password command failed: 535 | Check SMTPAuth, SMTPSecure and Port together, and read the credentials from the same source your tests use |
| Nodemailer | Invalid login: 535 | Set secure to match the port and check that the environment variables are loaded in the process that sends |
| Python smtplib | SMTPAuthenticationError: (535, ...) | Call starttls() before login(), and use SMTP_SSL on 465 |
| Laravel or Symfony Mailer | Failed to authenticate on SMTP server | Clear the configuration cache, quote values in .env and URL-encode special characters in a DSN |
| Outlook, Thunderbird or a device | Authentication failed | Set the outgoing server user name to the full SMTP user, enable authentication for outgoing mail and use an app-specific value if the provider offers one |
| Cron job or script | 535 after it worked for weeks | Look for a rotated credential, an expired key or an environment that no longer exports the variables |
When the credentials are correct but the login still fails
If a manual test with the same values also fails, check the server side. Confirm that the account is active and not suspended for a billing or verification reason. Confirm that the credential belongs to the right environment, because a key created for one project does not work in another. Look for an IP allowlist: some accounts only accept SMTP logins from listed addresses, and a server that moved to a new IP address starts failing at once. Check whether the credential has a permission scope that excludes sending. If you are on shared hosting, ask whether outbound connections on the port are filtered, because a firewall that drops the connection can surface in some libraries as an authentication error instead of a timeout.
Finally, look at your provider logs. A message log or event stream that shows a rejected login with a reason is faster than guessing. In MigoSMTP you can find recent activity in the dashboard and in the message logs, and our documentation lists the connection settings in one place. Use the host and credentials shown in your own dashboard rather than values from a tutorial.
Stop the retry loop before it makes things worse
An application that retries a failed login every second can trigger a protective block, which turns a simple credential problem into a longer outage. Treat 535 as a permanent failure for that attempt. Do not retry it with the same credentials. Log it once with a clear message such as "SMTP login rejected", alert a human and pause the sending job until the credential is fixed. Only retry temporary errors such as 454 or a connection timeout, and do it with a growing delay. Our guide to rate limits, retries and backoff shows a sensible pattern.
A short checklist
- Copy the SMTP host, user name and password again from the dashboard into a plain-text editor.
- Confirm port and encryption: 587 with STARTTLS, or 465 with implicit TLS.
- Test the login by hand with
opensslorswaks. - URL-encode special characters if the credentials are inside a connection string.
- Clear framework caches and restart workers after any credential change.
- Check the account status, scope and any IP allowlist.
- Stop automatic retries on 535 and alert someone.
When you have fixed the login, send a test message and read the delivery result as well. A successful login only proves that you can connect. Whether the message reaches the inbox depends on authentication of your domain, which is covered in authenticating your sending domain.
Test your connection with a real send Create an account, copy the SMTP settings from the dashboard and send a first message to confirm the login.
References and further reading
Frequently asked questions
What does SMTP error 535 5.7.8 mean?
The server rejected the credentials sent in the AUTH command. The connection and encryption worked, but the user name, password or credential type was not accepted.
Is error 535 a bounce?
No. It happens at login, before any message is accepted, so no bounce message is created. Your application receives the error immediately and the email is not queued.
Why does my password work on the website but not in SMTP?
Many providers use separate SMTP credentials or API keys for sending. The password you use for the web dashboard is often not accepted for SMTP.
Should my app retry after a 535?
No. A 535 is a permanent failure for those credentials. Retrying only adds failed logins and can trigger a protective block. Fix the credential, then resume sending.
Can a firewall cause a 535?
Usually a firewall causes a timeout or a refused connection. Some libraries report those as authentication errors, so test the connection with openssl to see which stage fails.