Skip to content
Groundmail

SMTP errors

535 5.7.8 error: what it means and how to fix it

535 5.7.8 means the SMTP server rejected your login. Check the username, app password, Workspace policy, env vars and TLS, then test before you redeploy.

By GroundmailUpdated All SMTP error codes →

535 5.7.8 at a glance

A generic reply

535 5.7.8 Error: authentication failed

Type
Permanent refusal
About
Your SMTP login, not your mail
Retry
Not until the login is fixed
Do this
Fix the username or password

Short answer

535 5.7.8 means the mail server refused your SMTP login. Your app connected and started the AUTH step, and the server said the username and password it got were not acceptable. No message was sent and none will be retried, because a 5xx reply is permanent.

The fix is almost always in your own config: the username, an app password, an admin policy, an environment variable or the TLS settings. Test the login by hand before you redeploy.

What 535 5.7.8 means

The full reply usually looks like one of these:

The full reply
535-5.7.8 Username and Password not accepted. For more information, go to
535 5.7.8 https://support.google.com/mail/?p=BadCredentials ... - gsmtp

535 5.7.8 Error: authentication failed

The first is Gmail and Google Workspace. The second is the generic form from Postfix-style servers and many hosting providers. The steps below are in the order that finds the problem fastest.

The 535 reply code is the SMTP server's answer to a failed AUTH command. The 5.7.8 enhanced status code narrows that to "authentication credentials invalid." The rejection happens before any message content moves. Your recipient, your HTML and your domain's DNS have nothing to do with it.

That matters for triage. A 550 5.7.1 or a 550 5.7.26 is a delivery decision about your mail. A 535 5.7.8 is a login decision about your account. If you are working through a different code, our index of SMTP error codes covers each one.

Three causes account for most of these errors:

  • Gmail and Google Workspace reject the normal account password for SMTP and expect an app password.
  • Microsoft 365 returns 535 when SMTP AUTH is turned off for the tenant or the mailbox, even when the password is correct.
  • Wrong credentials cause the rest, and the wrong value is often not the one you typed. It is the one your app actually read at runtime.

Check the username: use the full Gmail address

For Gmail and Workspace, the SMTP username is the full address: you@gmail.com or info@yourcompany.com. A bare local part like info will fail.

If you send as an alias, the login still uses the mailbox that owns the alias. The From header can be the alias, but auth.user must be the real account. Other servers vary. Some want the full address and some want only the local part, so check your provider's settings page before guessing.

Use an app password, not your account password

Google does not accept your regular account password over SMTP. You need an app password, and app passwords only exist on accounts with 2-Step Verification turned on.

To create one:

  1. Sign in to the Google account and open the Security settings.
  2. Under "Signing in to Google," turn on 2-Step Verification if it is off.
  3. Open App passwords and generate a new one.
  4. Use that generated password in your SMTP config in place of the account password.

Two details trip people up.

  • Changing your Google password revokes app passwords. If mail worked for months and stopped on a particular day, a password change or a security event on the account is a likely cause. Generate a fresh app password.
  • Google displays the app password in groups separated by spaces. Paste it without the spaces. In a nodemailer issue on GitHub, the original poster reported trying it both with and without spaces. Rule this out early.

Google Workspace: check what your admin allows

On a Workspace account, your admin's settings decide what you can do. If App passwords is missing from your security page, or a new one still fails, the organization may have blocked app passwords or SMTP access for your account. You cannot fix that from your own settings. Ask the admin what is allowed for the account you are sending from.

Microsoft 365 behaves the same way. SMTP AUTH can be disabled for the whole tenant or for one mailbox, and a disabled mailbox answers a correct password with 535. The admin has to turn SMTP AUTH on for that mailbox, or the app has to move to a different sending method.

Check how your app reads the credentials

A large share of 535 errors come from code that sends a different string than the one you think you set. Check what the process actually has at runtime.

  • Trailing whitespace and newlines. A secret pasted into a .env file or a CI variable can carry a trailing space or \n. Trim it, or print JSON.stringify(process.env.SMTP_PASS) once in a debug build to see the exact characters, then remove the print.
  • Quotes. SMTP_PASS="abcd efgh" in one loader becomes abcd efgh and in another becomes "abcd efgh" with the quotes. Know which loader you use.
  • Unset variables with fallbacks. Code like pass: process.env.APP_PASSWORD || '' sends an empty password when the variable is missing on the server. The login fails with 535 rather than with an error telling you the variable is missing. Fail at startup instead:
Fail at startup
const user = process.env.SMTP_USER;
const pass = process.env.SMTP_PASS?.trim();
if (!user || !pass) throw new Error("SMTP_USER or SMTP_PASS is not set");
  • Local works, production fails. This is the most common shape in the nodemailer thread. One commenter's code worked on their machine and failed on an AWS EC2 instance. If the same credential works locally, compare the environment variables on the server first. They are usually different.

The same thread has a harder variant. The original poster said a new server with identical code and credentials could send, while the old server kept getting the password error, and Google's support told them everything was fine on Google's side. When the credentials and config are identical and only the host differs, the problem is no longer in your code. The cause is likely on the provider's side, where you cannot inspect it. We come back to this below.

Check the port and TLS settings: 587 with STARTTLS

Most servers only advertise AUTH after the connection is encrypted. Use one of these two pairings and don't mix them:

PortTLS modeNodemailer setting
587STARTTLS (upgrade after connect)port: 587, secure: false
465Implicit TLS from the first byteport: 465, secure: true

Port 587 with secure: true, or 465 with secure: false, fails before or during the handshake. Our guide to SMTP ports explains when each port applies.

While you debug, remove tls: { rejectUnauthorized: false }. Both configs in the nodemailer issue had it set. It does not fix authentication, and it hides certificate problems that tell you whether you reached the right host.

Test the login outside your app before you redeploy

Don't push another config change and wait for a failed reset email. Test the login by hand. You can use our SMTP tester in the browser, or run this from the server that is failing:

Open a session
openssl s_client -connect smtp.gmail.com:587 -starttls smtp -crlf -quiet

Then type:

Say hello
EHLO test.local

Read the 250-AUTH line in the reply. It lists the mechanisms the server accepts, such as LOGIN PLAIN XOAUTH2. Then authenticate with base64-encoded credentials:

Encode the credentials
printf '%s' 'you@gmail.com' | base64
printf '%s' 'yourapppassword' | base64
Log in
AUTH LOGIN
<base64 username>
<base64 password>

The reply tells you which of three cases you are in:

  • 235 2.7.0 Accepted. The credential and host are fine, and the bug is in how your app builds its config. Go back to the environment variable checks.
  • 535 5.7.8 from your laptop and the server. The credential itself is wrong, or the account is not allowed to use SMTP.
  • 535 5.7.8 only from the server. If the credential really is identical, the provider may be treating that host differently, and a config change may not fix it.

Why a Gmail login is a weak sender for password resets and sign-in codes

A Gmail or Workspace mailbox is built for a person reading and writing mail. When an app uses it to send password resets, receipts and sign-in codes, every failure mode above sits between your user and the code they are waiting for:

  • A password change silently breaks sending.
  • An admin policy change breaks it with no notice.
  • One server can get 535 while another works with the same credentials.

Support may not be able to help with that last one. In the nodemailer issue, the original poster said Google's support told them everything was fine on Google's side.

Transactional mail is better sent through a relay built for it, where the credential belongs to an application, not a person, and the people running the servers can read the logs for your connection. If a reset email is also landing in spam once it does send, our password reset email debugging checklist covers the delivery side.

Send the same mail through Groundmail's SMTP relay

Groundmail sends transactional email from mail servers and IP space it operates itself. Marketing and cold email are not allowed on its shared pool. Its SMTP relay takes the same nodemailer, PHPMailer or framework mailer config you already have. Only the host and the credential change.

SettingGmail loginGroundmail SMTP relay
Hostsmtp.gmail.comsmtp.groundmail.dev
Port587587
TLSSTARTTLS (secure: false)STARTTLS (secure: false)
UsernameYour full Gmail or Workspace addressgroundmail, always
PasswordAn app password, which requires 2-Step VerificationAn SMTP credential from your Groundmail dashboard (gmsmtp_…)
Tied toA person's mailbox and its security settingsAn application credential you create and revoke
Groundmail SMTP relay in nodemailer
const transporter = nodemailer.createTransport({
  host: "smtp.groundmail.dev",
  port: 587,
  secure: false, // STARTTLS
  auth: {
    user: "groundmail",
    pass: process.env.GROUNDMAIL_SMTP_PASS,
  },
});

Verify your domain, send a first test and go live

  1. Verify your sending domain so mail goes out with your own SPF, DKIM and DMARC alignment. The From address has to be on a verified domain, or the relay refuses it with a 554.
  2. Create an SMTP credential in the dashboard and put it in your environment variables, with the startup check from earlier.
  3. Send one message to your account email from an address on that domain and confirm it arrives.
  4. Add a card, which you need to send to anyone else even on the free plan, and switch production traffic over.

The free plan covers 3,000 emails a month, 100 a day and 3 domains. Pay as you go is $15 a month with 20,000 emails included. The pricing page has the per-1,000 rates above that.

Start sending free

If your reset and sign-in emails depend on a mailbox login that can return 535 without warning, move them to a relay built for that mail. You can create your free Groundmail account and send your first test from smtp.groundmail.dev today.

Sources

Facts on this page about other companies' products, prices and policies come from these public pages. They change, so check them before you decide.

Email for apps. Set up by your agent.

Sign-in codes, receipts and alerts kept separate from marketing mail, with inbound, templates and automations included. Start free with 3,000 emails a month, and move to a dedicated IP or server without changing your code.