python & smtplib:是不是可以使用 oauth2 通过 gmail 发送邮件?

Posted

技术标签:

【中文标题】python & smtplib:是不是可以使用 oauth2 通过 gmail 发送邮件?【英文标题】:python & smtplib: Is sending mail via gmail using oauth2 possible?python & smtplib:是否可以使用 oauth2 通过 gmail 发送邮件? 【发布时间】:2012-07-11 19:56:15 【问题描述】:

所以我可以使用 smtplib(使用下面的脚本)登录并通过 gmail 发送邮件,但我只是想知道使用 oauth2 是否像 imaplib 一样是一个选项?我在 smtplib 文档页面上没有看到任何关于 oauth 的内容,也没有在谷歌上找到任何内容。谢谢。

#! /usr/bin/python

import smtplib

to = 'myemailaddress'
gmail_user = 'myemailaddress'
gmail_pwd = 'passwd'
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
smtpserver.login(gmail_user, gmail_pwd)
header = 'To:' + to + '\n' + 'From: ' + gmail_user + '\n' + 'Subject:testing \n'
print header
msg = header + '\n this is test msg from me \n\n'
smtpserver.sendmail(gmail_user, to, msg)
print 'done!'
smtpserver.close();

编辑:

感谢 samy.vilar 在他的回答中提供了非常详细的解释。但是,我遇到了一些麻烦。这是我的脚本:

#! /usr/bin/python

import oauth2 as oauth
import oauth2.clients.smtp as smtplib

consumer = oauth.Consumer('anonymous', 'anonymous')
token = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')

url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/smtp/"

conn = smtplib.SMTP('smtp.googlemail.com', 587)
conn.set_debuglevel(True)
conn.ehlo('test')
conn.starttls()

conn.authenticate(url, consumer, token)

header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'
msg = header + '\n this is test msg from me \n\n'
conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

让我感到困惑的是,它似乎可以通过身份验证:

send: 'ehlo test\r\n'
reply: '250-mx.google.com at your service, [75.173.8.127]\r\n'
reply: '250-SIZE 35882577\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-STARTTLS\r\n'
reply: '250 ENHANCEDSTATUSCODES\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [75.173.8.127]
SIZE 35882577
8BITMIME
STARTTLS
ENHANCEDSTATUSCODES
send: 'STARTTLS\r\n'
reply: '220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: 2.0.0 Ready to start TLS
send: 'AUTH XOAUTH R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL3NtdHAvIG9hdXRoX2JvZHlfaGFzaD0iMmptajdsNXJTdzB5VmIlMkZ2bFdBWWtLJTJGWUJ3ayUzRCIsb2F1dGhfY29uc3VtZXJfa2V5PSJhbm9ueW1vdXMiLG9hdXRoX25vbmNlPSI3Nzc0ODMyIixvYXV0aF9zaWduYXR1cmU9IkxuckZHODdxdHRxZUhsUlQ1emRndmtEZ1UzTSUzRCIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNDIxNDI3NzIiLG9hdXRoX3Rva2VuPSIxJTJGTUk2QjJEcUpQNEZFa0RSTFVLckQ1bDQ2c1EwNzU4LTJ1Y0VLQlktRGVCMCIsb2F1dGhfdmVyc2lvbj0iMS4wIg==\r\n'
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted

但是到了发送邮件的时候,好像忘记了conn已经被认证了:

send: 'ehlo [192.168.2.4]\r\n'
reply: '250-mx.google.com at your service, [75.173.8.127]\r\n'
reply: '250-SIZE 35882577\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-AUTH LOGIN PLAIN XOAUTH\r\n'
reply: '250 ENHANCEDSTATUSCODES\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [75.173.8.127]
SIZE 35882577
8BITMIME
AUTH LOGIN PLAIN XOAUTH
ENHANCEDSTATUSCODES
send: 'mail FROM:<testing.oauth.1@gmail.com> size=107\r\n'
reply: '530-5.5.1 Authentication Required. Learn more at\r\n'
reply: '530 5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 tu7sm3163839pbc.55\r\n'
reply: retcode (530); Msg: 5.5.1 Authentication Required. Learn more at
5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 tu7sm3163839pbc.55
send: 'rset\r\n'
reply: '250 2.1.5 Flushed tu7sm3163839pbc.55\r\n'
reply: retcode (250); Msg: 2.1.5 Flushed tu7sm3163839pbc.55
Traceback (most recent call last):
  File "./gmail_send3.py", line 47, in <module>
    conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)
  File "/usr/lib/python2.7/smtplib.py", line 713, in sendmail
    raise SMTPSenderRefused(code, resp, from_addr)
smtplib.SMTPSenderRefused: (530, '5.5.1 Authentication Required. Learn more at\n5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 tu7sm3163839pbc.55', 'testing.oauth.1@gmail.com')

【问题讨论】:

你保持这条线完整吗? consumer = oauth.Consumer('anonymous', 'anonymous') 或者您是否将这两个参数替换为您的实际消费者密钥和消费者秘密?如果您使用 xoauth.py 生成了用户令牌和用户密码,请执行前者。否则,做后者。 【参考方案1】:

有意思,我觉得有可能,我找到了以下链接https://developers.google.com/google-apps/gmail/oauth_overview

更新https://github.com/google/gmail-oauth2-tools/wiki/OAuth2DotPyRunThrough 这是使用 oauth2 的新演练,似乎 xoauth 已被宣布为过时,我已更新 URL 以获取旧版本 xoauth.py 文件,以防有人仍然需要它,尽管看起来谷歌已经改变了他们的API 和本演练不再适用。

您可以直接使用 xoauth 或 https://github.com/simplegeo/python-oauth2/ 进行实际交流,我推荐后者,它更通用。

显然你首先需要下载xoauth.py脚本。

$ wget https://raw.githubusercontent.com/google/gmail-oauth2-tools/master/obsolete/python/xoauth.py
$ python xoauth.py --generate_oauth_token --user=testing.oauth.1@gmail.com

xoauth.py:74: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
oauth_token_secret: HFJEvjcTfiXSPxgLzDh-1yaH
oauth_token: 4/EwUxCtY9ye1kdtb4uNJIcaUe9KXl
oauth_callback_confirmed: true
To authorize token, visit this url and follow the directions to generate a verification code:
https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=4%2FEwUxCtY9ye1kdtb4uNJIcaUe9KXl
Enter verification code: 7XjT15fqk1aNe8152d9oTRcJ
oauth_token: 1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0
oauth_token_secret: NysqNqVTulFsdHpSRrPP56sF

让我们测试一下:

$ python xoauth.py --test_imap_authentication --user=testing.oauth.1@gmail.com \
 --oauth_token=1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0 --oauth_token_secret=NysqNqVTulFsdHpSRrPP56sF

xoauth.py:74: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
xoauth string (before base64-encoding):
GET https://mail.google.com/mail/b/testing.oauth.1@gmail.com/imap/ oauth_consumer_key="anonymous",oauth_nonce="18010070659685102619",oauth_signature="jTJv%2FAFATpzfq%2BZTLAAxFNmWPi0%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1342084141",oauth_token="1%2FMI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0",oauth_version="1.0"

XOAUTH string (base64-encoded): R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL2ltYXAvIG9hdXRoX2NvbnN1bWVyX2tleT0iYW5vbnltb3VzIixvYXV0aF9ub25jZT0iMTgwMTAwNzA2NTk2ODUxMDI2MTkiLG9hdXRoX3NpZ25hdHVyZT0ialRKdiUyRkFGQVRwemZxJTJCWlRMQUF4Rk5tV1BpMCUzRCIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNDIwODQxNDEiLG9hdXRoX3Rva2VuPSIxJTJGTUk2QjJEcUpQNEZFa0RSTFVLckQ1bDQ2c1EwNzU4LTJ1Y0VLQlktRGVCMCIsb2F1dGhfdmVyc2lvbj0iMS4wIg==

09:01.40 > COKI1 AUTHENTICATE XOAUTH
09:01.44 < + 
09:01.45 write literal size 444
09:02.68 < * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
09:02.68 < COKI1 OK testing.oauth.1@gmail.com Testing Oauth authenticated (Success)
09:02.68 > COKI2 SELECT INBOX
09:03.09 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
09:03.09 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] Flags permitted.
09:03.09 < * OK [UIDVALIDITY 3] UIDs valid.
09:03.09 < * 3 EXISTS
09:03.09 < * 0 RECENT
09:03.09 < * OK [UIDNEXT 4] Predicted next UID.
09:03.09 < COKI2 OK [READ-WRITE] INBOX selected. (Success)

看来我们可以走了。 你可能想设置一个virtualenv

$ git clone https://github.com/simplegeo/python-oauth2.git
$ cd python-oauth2/
$ sudo python setup.py install

并直接取自文档:

import oauth2 as oauth
import oauth2.clients.imap as imaplib

# Set up your Consumer and Token as per usual. Just like any other
# three-legged OAuth request.
consumer = oauth.Consumer('anonymous', 'anonymous')
token = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')

# Setup the URL according to Google's XOAUTH implementation. Be sure
# to replace the email here with the appropriate email address that
# you wish to access.
url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/imap/"

conn = imaplib.IMAP4_SSL('imap.googlemail.com')
conn.debug = 4 

# This is the only thing in the API for impaplib.IMAP4_SSL that has 
# changed. You now authenticate with the URL, consumer, and token.
conn.authenticate(url, consumer, token)

# Once authenticated everything from the impalib.IMAP4_SSL class will 
# work as per usual without any modification to your code.
conn.select('INBOX')
print conn.list()


>>> conn.authenticate(url, consumer, token)
20:11.73 > EPKK1 AUTHENTICATE XOAUTH
20:11.78 < + 
20:11.78 write literal size 496
20:11.93 < * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
20:11.93 < EPKK1 OK testing.oauth.1@gmail.com Testing Oauth authenticated (Success)
>>> conn.select('INBOX')
20:17.47 > EPKK2 SELECT INBOX
20:17.58 < * FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
20:17.58 < * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] Flags permitted.
20:17.58 < * OK [UIDVALIDITY 3] UIDs valid.
20:17.58 < * 3 EXISTS
20:17.58 < * 0 RECENT
20:17.58 < * OK [UIDNEXT 4] Predicted next UID.
20:17.58 < EPKK2 OK [READ-WRITE] INBOX selected. (Success)
('OK', ['3'])
>>> print conn.list()
20:20.23 > EPKK3 LIST "" *
20:20.28 < * LIST (\HasNoChildren) "/" "INBOX"
20:20.28 < * LIST (\Noselect \HasChildren) "/" "[Gmail]"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/All Mail"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/Drafts"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/Important"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/Sent Mail"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/Spam"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/Starred"
20:20.28 < * LIST (\HasNoChildren) "/" "[Gmail]/Trash"
20:20.28 < EPKK3 OK Success
('OK', ['(\\HasNoChildren) "/" "INBOX"', '(\\Noselect \\HasChildren) "/" "[Gmail]"', '(\\HasNoChildren) "/" "[Gmail]/All Mail"', '(\\HasNoChildren) "/" "[Gmail]/Drafts"', '(\\HasNoChildren) "/" "[Gmail]/Important"', '(\\HasNoChildren) "/" "[Gmail]/Sent Mail"', '(\\HasNoChildren) "/" "[Gmail]/Spam"', '(\\HasNoChildren) "/" "[Gmail]/Starred"', '(\\HasNoChildren) "/" "[Gmail]/Trash"'])
>>> 

对于 smtp:

import oauth2 as oauth
import oauth2.clients.smtp as smtplib

# Set up your Consumer and Token as per usual. Just like any other
# three-legged OAuth request.
# Set up your Consumer and Token as per usual. Just like any other
# three-legged OAuth request.
consumer = oauth.Consumer('anonymous', 'anonymous')
token = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')

# Setup the URL according to Google's XOAUTH implementation. Be sure
# to replace the email here with the appropriate email address that
# you wish to access.
url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/smtp/"

conn = smtplib.SMTP('smtp.googlemail.com', 587)
conn.set_debuglevel(True)
conn.ehlo('test')
conn.starttls()

# Again the only thing modified from smtplib.SMTP is the authenticate
# method, which works identically to the imaplib.IMAP4_SSL method.
conn.authenticate(url, consumer, token)



>>> conn.ehlo('test')
send: 'ehlo test\r\n'
reply: '250-mx.google.com at your service, [142.255.57.49]\r\n'
reply: '250-SIZE 35882577\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-STARTTLS\r\n'
reply: '250 ENHANCEDSTATUSCODES\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [142.255.57.49]
SIZE 35882577
8BITMIME
STARTTLS
ENHANCEDSTATUSCODES
(250, 'mx.google.com at your service, [142.255.57.49]\nSIZE 35882577\n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES')
>>> conn.starttls()
send: 'STARTTLS\r\n'
reply: '220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: 2.0.0 Ready to start TLS
(220, '2.0.0 Ready to start TLS')
>>> conn.authenticate(url, consumer, token)
send: 'AUTH XOAUTH R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL3NtdHAvIG9hdXRoX2JvZHlfaGFzaD0iMmptajdsNXJTdzB5VmIlMkZ2bFdBWWtLJTJGWUJ3ayUzRCIsb2F1dGhfY29uc3VtZXJfa2V5PSJhbm9ueW1vdXMiLG9hdXRoX25vbmNlPSI4MTEyMDkxNCIsb2F1dGhfc2lnbmF0dXJlPSJSaUFsTGdQWnpBSkNQJTJGWmx5aGRpYU1CV0xiTSUzRCIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNDIwODU2NzIiLG9hdXRoX3Rva2VuPSIxJTJGTUk2QjJEcUpQNEZFa0RSTFVLckQ1bDQ2c1EwNzU4LTJ1Y0VLQlktRGVCMCIsb2F1dGhfdmVyc2lvbj0iMS4wIg==\r\n'
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted
>>>

并发送电子邮件:

>>> conn.authenticate(url, consumer, token)
send: 'AUTH XOAUTH R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL3NtdHAvIG9hdXRoX2JvZHlfaGFzaD0iMmptajdsNXJTdzB5VmIlMkZ2bFdBWWtLJTJGWUJ3ayUzRCIsb2F1dGhfY29uc3VtZXJfa2V5PSJhbm9ueW1vdXMiLG9hdXRoX25vbmNlPSI2OTg3ODM3NiIsb2F1dGhfc2lnbmF0dXJlPSIlMkZjUGslMkJRVWVJY1RaYXp1ekkwR1FzdkdtbDFBJTNEIixvYXV0aF9zaWduYXR1cmVfbWV0aG9kPSJITUFDLVNIQTEiLG9hdXRoX3RpbWVzdGFtcD0iMTM0MjA4NjAxNCIsb2F1dGhfdG9rZW49IjElMkZNSTZCMkRxSlA0RkVrRFJMVUtyRDVsNDZzUTA3NTgtMnVjRUtCWS1EZUIwIixvYXV0aF92ZXJzaW9uPSIxLjAi\r\n'
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted
>>> header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'
>>> msg = header + '\n this is test msg from me \n\n'
>>> conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)
send: 'mail FROM:<testing.oauth.1@gmail.com> size=107\r\n'
reply: '250 2.1.0 OK gb7sm6540492qab.12\r\n'
reply: retcode (250); Msg: 2.1.0 OK gb7sm6540492qab.12
send: 'rcpt TO:<testing.oauth.1@gmail.com>\r\n'
reply: '250 2.1.5 OK gb7sm6540492qab.12\r\n'
reply: retcode (250); Msg: 2.1.5 OK gb7sm6540492qab.12
send: 'data\r\n'
reply: '354  Go ahead gb7sm6540492qab.12\r\n'
reply: retcode (354); Msg: Go ahead gb7sm6540492qab.12
data: (354, 'Go ahead gb7sm6540492qab.12')
send: 'To:testing.oauth.1@gmail.com\r\nFrom: testing.oauth.1@gmail.com\r\nSubject:testing \r\n\r\n this is test msg from me \r\n\r\n.\r\n'
reply: '250 2.0.0 OK 1342086030 gb7sm6540492qab.12\r\n'
reply: retcode (250); Msg: 2.0.0 OK 1342086030 gb7sm6540492qab.12
data: (250, '2.0.0 OK 1342086030 gb7sm6540492qab.12')

>>>

确保在发送电子邮件之前进行身份验证。 希望这会有所帮助...

更新 可能存在需要重新身份验证的错误,以下应该可以工作。

import oauth2 as oauth
import oauth2.clients.smtp as smtplib

consumer = oauth.Consumer('anonymous', 'anonymous')
token = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')

url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/smtp/"

conn = smtplib.SMTP('smtp.googlemail.com', 587)
conn.set_debuglevel(True)
conn.ehlo('test')
conn.starttls()

conn.authenticate(url, consumer, token)

header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'
msg = header + '\n this is test msg from me \n\n'
try:
    conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)
except Exception as ex:
    print str(ex)
    print 'retying ...'
    conn.authenticate(url, consumer, token)
    conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

虽然你也可以直接使用xoauth

import time
import smtplib
import xoauth

consumer = xoauth.OAuthEntity('anonymous', 'anonymous')
access_token = xoauth.OAuthEntity('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')

xoauth_string = xoauth.GenerateXOauthString(consumer, access_token, 'testing.oauth.1@gmail.com', 'smtp', 'testing.oauth.1@gmail.com', str(xoauth.random.randrange(2**64 - 1)), str(int(time.time())))

smtp_conn = smtplib.SMTP('smtp.gmail.com', 587)
smtp_conn.set_debuglevel(True)
smtp_conn.ehlo()
smtp_conn.starttls()
smtp_conn.ehlo()
smtp_conn.docmd('AUTH', 'XOAUTH ' + xoauth.base64.b64encode(xoauth_string))

header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'
msg = header + '\n this is test msg from me \n\n'
smtp_conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

这似乎总是有效,我应该向python-oauth2 团队提交一张票,谢谢。

虽然这似乎总是有效的

import oauth2 as oauth
import oauth2.clients.smtp as smtplib

consumer = oauth.Consumer('anonymous', 'anonymous')
token = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')

url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/smtp/"

conn = smtplib.SMTP('smtp.googlemail.com', 587)
conn.set_debuglevel(True)
conn.ehlo('test')
conn.starttls()
conn.ehlo()
conn.authenticate(url, consumer, token)
header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'
msg = header + '\n this is test msg from me \n\n'
conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

看来您需要在进行身份验证之前致电conn.ehlo()

【讨论】:

感谢您非常彻底的回答。但是,我遇到了一些麻烦。我编辑了我的原始问题以包括我的新脚本和我得到的输出。你能看看吗?谢谢。 @nomadicME 看起来他们可能是oauth2 的错误更新了答案以包括一个简单的补丁以及直接使用 xoauth,这似乎总是有效。 @nomadicME 没问题 请记住我刚刚创建了这个帐户testing.oauth.1@gmail.com 并且我似乎无法再访问它了,要么有人更改了密码,要么我只是忘记了对不起,你可以按照说明操作... 这么详细的回答!荣誉 这篇文章需要更新……链接坏了

以上是关于python & smtplib:是不是可以使用 oauth2 通过 gmail 发送邮件?的主要内容,如果未能解决你的问题,请参考以下文章

Python 发邮件用 smtplib & email

python3 发邮件 smtplib & email 库

python smtplib发送邮件可直接运行代码

python之发送邮件(smtplib)

python之发送邮件(smtplib)

Python发送邮件smtplib.SMTP各报错问题的解决方法