使用Google OAuth从Django admin action在Gmail中创建草稿

6bc51xsx  于 2023-08-02  发布在  Go
关注(0)|答案(1)|浏览(89)

我正在尝试创建一个Django管理员操作,它将在我的Gmail帐户中创建一个草稿电子邮件,并发送给选定的联系人。我被Google OAuth流程卡住了。

admin.py:

...

DEBUG = os.getenv('DEBUG', 'False') == 'True'
if DEBUG:
    os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

SCOPES = ['https://www.googleapis.com/auth/gmail.compose']

def email_contacts(modeladmin, request, queryset):
    flow = Flow.from_client_secrets_file(
        'contacts/client_secret.json',
        scopes=SCOPES)
    flow.redirect_uri = "http://localhost:8000/callback"
    authorization_url, state = flow.authorization_url(
        access_type='offline',
        include_granted_scopes='true')
    return HttpResponseRedirect(authorization_url)

def auth_callback(request):
    code = request.GET.get('code')
    flow = Flow.from_client_secrets_file(
        'contacts/client_secret.json',
        scopes=SCOPES)
    flow.redirect_uri = "http://localhost:8000"
    flow.fetch_token(code=code)
    creds = flow.credentials
    send_email(creds)

def send_email(creds):
    message_body = "Test content"
    message = MIMEMultipart()
    message['to'] = 'test.address@example.com'
    message.attach(MIMEText(message_body, "plain"))
    try:
        service = build('gmail', 'v1', credentials=creds)
        message = {'message': {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()}}
        service.users().drafts().create(userId='me', body=message).execute()
    except HttpError as err:
        print(err)

...

class ContactAdmin(admin.ModelAdmin):
    actions = [emails_contacts]

字符串
(Just到目前为止,正在尝试起草一封测试电子邮件;尚未尝试用来自查询集的数据填充电子邮件)

url.py:

... 

from contacts.admin import auth_callback

urlpatterns = [
    path('callback/', auth_callback, name='oauth_callback'),
    path('admin/', admin.site.urls),
...

client_secret.json:

{"web":{"client_id":"....apps.googleusercontent.com","project_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","...":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"...","redirect_uris":["http://localhost:8000/callback","http://localhost:8000/callback/","http://localhost/callback","http://localhost/callback/","http://localhost:8000/","http://localhost:8000","http://localhost","http://localhost/"]}}


(列出了大量的redirect_uris以确保安全)

错误:

CustomOAuth2Error at /callback/
(redirect_uri_mismatch)错误请求
申请方式:GET请求URL:http://localhost:8000/callback/?state=...&code=...&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.compose Django版本:4.2.1异常类型:CustomOAuth 2 Error异常值:
(redirect_uri_mismatch)错误请求
异常位置:/home/me/.local/share/virtualenvs/contacts/lib/python3.9/site-packages/oauthlib/oauth2/rfc 6749/errors.py,line 400,in raise_from_error在以下期间引发:contacts.admin.auth_callback Python可执行文件:/home/me/.local/share/virtualenvs/contacts/bin/python Python版本:3.9.5
...
在这行代码上触发错误:第一个月

7uzetpgm

7uzetpgm1#

我修好了。我不知道到底是什么问题,但这里是工作代码的相关部分。

admin.py:

...

DEBUG = os.getenv('DEBUG', 'False') == 'True'
if DEBUG:
    redirect_uri='https://127.0.0.1:8000/oauth/'
else:
    redirect_uri='https://my-url.com/oauth/'

SCOPES = ['https://www.googleapis.com/auth/gmail.compose']

def authenticate(request):
    flow = Flow.from_client_secrets_file('contacts/client_secret.json',
        scopes=SCOPES,
        redirect_uri=redirect_uri,
    )
    authorization_url, state = flow.authorization_url(
        access_type='offline',
        include_granted_scopes='true'
    )
    request.session['oauth2_state'] = state
    return redirect(authorization_url)

def oauth2callback(request):
    state = request.session.get('oauth2_state', '')
    flow = Flow.from_client_secrets_file('contacts/client_secret.json',
        scopes=SCOPES,
        state=state,
        redirect_uri=request.build_absolute_uri('/oauth/')
    )
    flow.fetch_token(authorization_response=request.build_absolute_uri())
    credentials_json = flow.credentials.to_json()
    request.session['gmail_credentials'] = credentials_json
    messages.success(request, 'OAuth authentication successful but no emails drafted. Please perform action again.')
    return redirect(request.build_absolute_uri('/admin/contacts/contact/'))

def get_gmail_credentials(request):
    credentials_json = request.session.get('gmail_credentials')
    if not credentials_json:
        return None
    credentials_info = json.loads(credentials_json)
    info = {
        "client_id": credentials_info['client_id'],
        "client_secret": credentials_info['client_secret'],
        "token": credentials_info['token'],
        "refresh_token": credentials_info['refresh_token'],
        "token_uri": credentials_info['token_uri'],
        "scopes": SCOPES,
    }
    return credentials.Credentials.from_authorized_user_info(info)

...

class ContactAdmin(admin.ModelAdmin):
    actions = [emails_contacts]

字符串

url.py:

...
urlpatterns = [
    path('authenticate/', authenticate, name='authenticate'),
    path('oauth/', oauth2callback, name='oauth'),
    path('compose-email/', compose_emails, name='compose_email'),
...

client_secret.json:

{"web":{"client_id":"MASKED.apps.googleusercontent.com","project_id":"MASKED","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"MASKED","redirect_uris":["https://127.0.0.1:8000/oauth/","https://my-url.com/oauth/"]}}

相关问题