SMTPLIB
Python smtplib "Username and Password not accepted" (SMTP 535 5.7.8) means the server rejected SMTP.login(). Fix it with a Gmail App Password or OAuth 2.0.
Updated Jul 1, 2026
The short answer
"Username and Password not accepted" is the message Python's smtplib raises as SMTPAuthenticationError when an SMTP server rejects your SMTP.login() credentials — typically Gmail returning "535-5.7.8". It almost never means a typo: Gmail stopped accepting regular passwords from scripts, so you must authenticate with a 16-character App Password (2-Step Verification required) or OAuth 2.0.
This message comes from Python's smtplib. When SMTP.login(user, password) fails, smtplib raises smtplib.SMTPAuthenticationError, and the text you see is the server's reply echoed back. With Gmail the full reply is almost always:
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Username and Password not accepted. For more information, go to\n5.7.8 https://support.google.com/mail/?p=BadCredentials ...')
The 535 reply code and the 5.7.8 enhanced status code ("Authentication credentials invalid") are both defined by RFC 4954, the SMTP authentication extension. RFC 3463 provides the underlying enhanced-status-code framework (the class.subject.detail structure and the X.7 "Security or Policy" subject, covering X.7.0 through X.7.7), but the specific .8 detail for invalid credentials comes from RFC 4954. It is a permanent failure — retrying with the same credentials will not help.
The server received your AUTH attempt and explicitly rejected the credentials. With Gmail and Google Workspace, the dominant cause today is not a typo — it is that Google no longer accepts your normal account password from scripts:
myaccount.google.com/lesssecureapps toggle no longer exists — ignore any guide that tells you to enable it.)you@gmail.com), not the local part.login() instead of SMTP.auth() with a proper auth object will fail.1. Turn on 2-Step Verification for the Google account at myaccount.google.com/security. App Passwords are unavailable without it.
2. Generate an App Password at myaccount.google.com/apppasswords. Google shows a 16-character code in four groups.
3. Use the App Password in login() — your full email as the username, the 16 characters with the spaces removed:
import smtplib, sslcontext = ssl.create_default_context()with smtplib.SMTP("smtp.gmail.com", 587) as server:server.starttls(context=context)server.login("you@gmail.com", "abcdefghijklmnop") # App Password, no spacesserver.sendmail("you@gmail.com", "to@example.com", "Subject: hi\n\nbody")
Port 587 (STARTTLS) and port 465 (implicit TLS via smtplib.SMTP_SSL) are both valid per RFC 8314 — pick one and match the connection class. Do not call starttls() on a 465/SMTP_SSL connection.
4. Prefer OAuth 2.0 for production. App Passwords are a stopgap; Google recommends OAuth 2.0 (XOAUTH2) for server applications. Build the SASL XOAUTH2 string and authenticate with server.auth("XOAUTH2", lambda: auth_string) rather than login().
No. Any SMTP server can return 535 / 5.7.8, and smtplib will surface it the same way. For SendGrid the username must be the literal string apikey and the password your API key; for Amazon SES, your raw AWS access key/secret cannot be pasted directly into an SMTP password field — use the SMTP credentials generated in the SES console; for Mailgun use the SMTP username and password from the domain's settings. If you are not on Gmail, confirm you are using the provider's SMTP credentials, which are frequently distinct from your dashboard login or API key.
If you route mail through Courier, you supply provider SMTP credentials once in the Courier dashboard rather than embedding them in smtplib, which removes this class of credential-handling error from your application code.
References
FAQ
Because Google no longer accepts regular account passwords from scripts or third-party SMTP clients. Even a perfectly correct password is rejected. Enable 2-Step Verification and authenticate with a 16-character App Password, or use OAuth 2.0. The old 'less secure apps' toggle was removed in 2022 and is not an option.
One API, every provider
Courier connects to your email, SMS, and push providers, handles retries and failover, and surfaces delivery errors in plain language.
Reply-code definitions per RFC 4954 (5.7.8) / RFC 3463 (X.7 framework). Last reviewed Jul 1, 2026. Courier is not affiliated with third-party providers; error behavior may vary by implementation.
© 2026 Courier. All rights reserved.