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.

Вернуться на верх