535 Authentication Failed — App Password Required
Triệu chứng
- SMTP client logs show "535 5.7.8 Username and Password not accepted"
- The same username and password log into the webmail interface without issues
- Error began after enabling 2-factor authentication (2FA) on the account
- Django/Python `smtplib.SMTPAuthenticationError: (535, b'5.7.8 ...')` exception
- Nodemailer, PHPMailer, or similar library returns authentication failure on port 587
- The same username and password log into the webmail interface without issues
- Error began after enabling 2-factor authentication (2FA) on the account
- Django/Python `smtplib.SMTPAuthenticationError: (535, b'5.7.8 ...')` exception
- Nodemailer, PHPMailer, or similar library returns authentication failure on port 587
Nguyên nhân gốc rễ
- Google and Microsoft disabled 'less secure app' access — regular passwords are rejected for SMTP
- 2FA is enabled on the account but the SMTP client is using the regular account password
- App Password was not generated, or was entered with spaces (Google displays it in 4-char groups)
- OAuth2 is required by the provider's policy instead of password-based AUTH PLAIN/LOGIN
- Account temporarily locked due to suspicious login activity from a new IP or location
Chẩn đoán
**Step 1 — Confirm the error is 535, not a connection error**
```bash
# Manual SMTP AUTH test with openssl
openssl s_client -connect smtp.gmail.com:587 -starttls smtp
# After connection:
EHLO yourdomain.com
AUTH LOGIN
# Server asks for base64-encoded username, then password
# python3 -c "import base64; print(base64.b64encode(b'[email protected]').decode())"
```
**Step 2 — Check if 2FA is enabled on the account**
- Gmail: https://myaccount.google.com/security → 2-Step Verification
- Microsoft 365: https://account.activedirectory.windowsazure.com/ → Security info
If 2FA is enabled, a regular password will always fail for SMTP.
**Step 3 — Verify you're using the App Password, not the account password**
App Passwords are 16 characters (Gmail) or 8–16 characters (Microsoft). When you copy-paste from Google's display, remove the spaces between character groups.
```bash
# Manual SMTP AUTH test with openssl
openssl s_client -connect smtp.gmail.com:587 -starttls smtp
# After connection:
EHLO yourdomain.com
AUTH LOGIN
# Server asks for base64-encoded username, then password
# python3 -c "import base64; print(base64.b64encode(b'[email protected]').decode())"
```
**Step 2 — Check if 2FA is enabled on the account**
- Gmail: https://myaccount.google.com/security → 2-Step Verification
- Microsoft 365: https://account.activedirectory.windowsazure.com/ → Security info
If 2FA is enabled, a regular password will always fail for SMTP.
**Step 3 — Verify you're using the App Password, not the account password**
App Passwords are 16 characters (Gmail) or 8–16 characters (Microsoft). When you copy-paste from Google's display, remove the spaces between character groups.
Giải quyết
**Fix 1 — Generate a Gmail App Password**
1. Go to https://myaccount.google.com/apppasswords
2. Select 'Mail' and your device
3. Copy the 16-character password (ignore the spaces in the display)
4. Use this password in your SMTP config instead of your account password:
```python
# Django settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'abcdabcdabcdabcd' # 16-char App Password, no spaces
```
**Fix 2 — Generate a Microsoft 365 App Password**
1. Sign in → My Account → Security Info → Add method → App password
2. Use `smtp.office365.com:587` with STARTTLS and the generated password.
**Fix 3 — Use OAuth2 (modern, recommended for production)**
```python
# Use google-auth + smtplib for OAuth2 SMTP
# pip install google-auth google-auth-oauthlib
from google.oauth2 import service_account
from google.auth.transport.requests import Request
# Configure a service account with Gmail API scope and domain-wide delegation
# See: https://developers.google.com/gmail/api/guides/sending
```
**Fix 4 — Use a dedicated SMTP provider**
Avoid Gmail/O365 SMTP for applications. Use SES, SendGrid, or Mailgun — they issue API keys instead of account passwords and have no 2FA complications.
1. Go to https://myaccount.google.com/apppasswords
2. Select 'Mail' and your device
3. Copy the 16-character password (ignore the spaces in the display)
4. Use this password in your SMTP config instead of your account password:
```python
# Django settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'abcdabcdabcdabcd' # 16-char App Password, no spaces
```
**Fix 2 — Generate a Microsoft 365 App Password**
1. Sign in → My Account → Security Info → Add method → App password
2. Use `smtp.office365.com:587` with STARTTLS and the generated password.
**Fix 3 — Use OAuth2 (modern, recommended for production)**
```python
# Use google-auth + smtplib for OAuth2 SMTP
# pip install google-auth google-auth-oauthlib
from google.oauth2 import service_account
from google.auth.transport.requests import Request
# Configure a service account with Gmail API scope and domain-wide delegation
# See: https://developers.google.com/gmail/api/guides/sending
```
**Fix 4 — Use a dedicated SMTP provider**
Avoid Gmail/O365 SMTP for applications. Use SES, SendGrid, or Mailgun — they issue API keys instead of account passwords and have no 2FA complications.
Phòng ngừa
- Never use personal Gmail/O365 accounts for application email — use a dedicated SMTP provider with API keys
- Store App Passwords in a secrets manager (1Password, AWS Secrets Manager) rather than in code or plain config files
- Switch to OAuth2 SMTP when the provider supports it — App Passwords are a transitional workaround, not a long-term solution
- When rotating App Passwords, update all applications before revoking the old one to avoid outages
- Monitor for `535` errors in your application logs and alert immediately — it means all outbound email is silently failing
- Store App Passwords in a secrets manager (1Password, AWS Secrets Manager) rather than in code or plain config files
- Switch to OAuth2 SMTP when the provider supports it — App Passwords are a transitional workaround, not a long-term solution
- When rotating App Passwords, update all applications before revoking the old one to avoid outages
- Monitor for `535` errors in your application logs and alert immediately — it means all outbound email is silently failing