Gmail с Oauth отклоняет мой токен/пароль
Я пытаюсь отправить почту из Django. Я пробовал два разных способа, оба из которых не работают по-разному.
Когда я попробовал использовать пароль приложения, у меня не возникло никаких ошибок, но письмо просто не пришло. И ящик отправителя тоже пуст.
Но это было после того, как я попробовал современный метод, OAuth. После процесса, который я никогда бы не закончил без ChatGPT (потому что никто другой не создал руководство, которое я могу найти), я установил что-то, что почти работает. У меня есть файл с маркером обновления и пользовательский бэкэнд, который его использует.
Но когда приходит время отправить письмо, мне сообщают: «Имя пользователя и пароль не приняты»
Вот как выглядит файл с токенами:
{
"token": "[secret]",
"refresh_token": "[secret]",
"token_uri": "https://oauth2.googleapis.com/token",
"client_id": "[secret]",
"client_secret": "[secret]",
"scopes": ["https://www.googleapis.com/auth/gmail.send"],
"universe_domain": "googleapis.com",
"account": "",
"expiry": "2025-01-05T07:39:06.980351Z"
}
А это бэкэнд:
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from django.core.mail.backends.smtp import EmailBackend
from pathlib import Path
import os
class GmailOAuth2Backend(EmailBackend):
def _get_access_token(self):
dir = Path(__file__).resolve().parent
file = os.path.join(dir, 'oauth2tokenfile.secret.json')
creds = Credentials.from_authorized_user_file(file)
if creds.expired and creds.refresh_token:
creds.refresh(Request())
return creds.token
def open(self):
self.password = self._get_access_token()
super().open()
И, наконец, мои настройки
EMAIL_BACKEND = "[secret].GmailOAuth2Backend"
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[my email]@gmail.com'
Согласно отладчику, creds.valid = True (после обновления).
Ему нельзя не есть этот приход. У меня MFE с реакцией.
Ошибка «Имя пользователя и пароль не приняты» обычно возникает, когда smtp-сервер gmail не распознает или не принимает используемые учетные данные.
Отладьте токен доступа, который передается в качестве пароля на smtp-сервер gmail, это может помочь
def _get_access_token(self):
dir = Path(__file__).resolve().parent
file = os.path.join(dir, 'oauth2tokenfile.secret.json')
try:
creds = Credentials.from_authorized_user_file(file)
if creds.expired and creds.refresh_token:
creds.refresh(Request())
print(f"Access Token: {creds.token}") # debugging
return creds.token
except Exception as e:
raise Exception(f"Error loading or refreshing credentials: {e}")
Еще одна вещь, которую вы можете попробовать, - это изолировать проблему и протестировать SMTP-аутентификацию вручную, используя библиотеку, такую как smtplib
import smtplib
# Ensure the EMAIL_HOST_USER in your Django settings matches the account associated with the oauth2 token (email field)
EMAIL = 'your_email@gmail.com'
ACCESS_TOKEN = 'your_access_token'
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(EMAIL, ACCESS_TOKEN)
print("login successful!")
except smtplib.SMTPAuthenticationError as e:
print("authentication failed:", e)
Если этот тест не проходит с той же ошибкой, проблема заключается в настройках токена или учетной записи Gmail.