Python &引用;“错误请求”;(400)在Google上使用XOAUTH2时';具有服务帐户的SMTP服务

Python &引用;“错误请求”;(400)在Google上使用XOAUTH2时';具有服务帐户的SMTP服务,python,smtp,google-oauth,Python,Smtp,Google Oauth,我想使用谷歌的SMTP服务从我的谷歌账户发送电子邮件 因此,我转到谷歌API控制台,创建了一个服务帐户,即…@developer.gserviceaccount.com,并下载了私有证书 使用Python,您可以使用库为这样一对获取凭证对象:SignedJwtAssertionCredentials。您提供了范围”https://mail.google.com“用于SMTP服务 谷歌的运行文档中对此进行了解释,但其中的示例假设您已经安装了一个“已安装的应用程序”,并且您将使用web流提示用户授权

我想使用谷歌的SMTP服务从我的谷歌账户发送电子邮件

因此,我转到谷歌API控制台,创建了一个服务帐户,即
…@developer.gserviceaccount.com
,并下载了私有证书

使用Python,您可以使用库为这样一对获取凭证对象:
SignedJwtAssertionCredentials
。您提供了范围
”https://mail.google.com“
用于SMTP服务

谷歌的运行文档中对此进行了解释,但其中的示例假设您已经安装了一个“已安装的应用程序”,并且您将使用web流提示用户授权从其帐户发送电子邮件

在我的情况下,这是从我自己的帐户,所以我已经建立了一个服务帐户,并带有一个私人证书,我可以用它来授权凭据

此Python脚本演示了问题:

import httplib2
import smtplib
import base64
import datetime

from oauth2client.client import SignedJwtAssertionCredentials

http = httplib2.Http()

google_user = "some-account@developer.gserviceaccount.com"
google_cert = open('some-private-cert.p12', 'rb').read()

credentials = SignedJwtAssertionCredentials(
    google_user, google_cert,
    scope='https://mail.google.com/',
)

credentials.refresh(http)

# To demonstrate that we've got a valid access token, let's make a
# couple of assertions:
#
# 1. The credentials have been refreshed:
assert credentials.access_token is not None
#
# 2. The access token hasn't expired (and isn't about to):
assert (credentials.token_expiry - datetime.datetime.utcnow()).total_seconds() > 60

auth_string = 'user=%s\1auth=Bearer %s\1\1' % (
    google_user, credentials.access_token
)

smtp_conn = smtplib.SMTP('smtp.gmail.com', 587)
smtp_conn.set_debuglevel(True)
smtp_conn.ehlo()
smtp_conn.starttls()
smtp_conn.ehlo()

# Now, authenticate (but this fails):
smtp_conn.docmd('AUTH', 'XOAUTH2 ' + base64.b64encode(auth_string))
错误响应为(base64已解码):

我不知道它是否有效,但我不明白为什么不行

{"status":"400",
 "schemes":"Bearer",
 "scope":"https://mail.google.com/"}