Beginner 5 min SMTP 535

535 Authentication Failed — App Password Required

症状

- 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

根本原因

  • 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

诊断

**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.

解决

**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.

预防

- 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

相关状态码

相关术语