蟒蛇&smtplib:是否可以使用 oauth2 通过 gmail 发送邮件? [英] python & smtplib: Is sending mail via gmail using oauth2 possible?

查看:116
本文介绍了蟒蛇&smtplib:是否可以使用 oauth2 通过 gmail 发送邮件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

#!/usr/bin/python导入 smtplibto = '我的邮箱地址'gmail_user = '我的邮箱地址'gmail_pwd = '密码'smtpserver = smtplib.SMTP("smtp.gmail.com",587)smtpserver.ehlo()smtpserver.starttls()smtpserver.ehlosmtpserver.login(gmail_user, gmail_pwd)header = 'To:' + to + '\n' + 'From:' + gmail_user + '\n' + 'Subject:testing \n'打印标题msg = header + '\n 这是我的测试消息 \n\n'smtpserver.sendmail(gmail_user, to, msg)打印完成!"smtpserver.close();

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

#!/usr/bin/python将 oauth2 导入为 oauth导入 oauth2.clients.smtp 作为 smtplib消费者 = oauth.Consumer('匿名', '匿名')令牌 = 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(真)conn.ehlo('测试')conn.starttls()conn.authenticate(网址,消费者,令牌)header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'msg = header + '\n 这是我的测试消息 \n\n'conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

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

send: 'ehlo test\r\n'回复:'250-mx.google.com 为您服务,[75.173.8.127]\r\n'回复:'250-SIZE 35882577\r\n'回复: '250-8BITMIME\r\n'回复:'250-STARTTLS\r\n'回复: '250 增强状态代码\r\n'回复: retcode (250);消息:mx.google.com 为您服务,[75.173.8.127]尺寸 358825778BITMIME开始TLS增强状态代码发送:'STARTTLS\r\n'回复: '220 2.0.0 准备启动 TLS\r\n'回复: retcode (220);消息:2.0.0 准备启动 TLS发送: 'AUTH XOAUTH R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL3NtdHAvIG9hdXRoX2JvZHlfaGFzaD0iMmptajdsNXJTdzB5VmIlMkZ2bFdBWWtLJTJGWUJ3ayUzRCIsb2F1dGhfY29uc3VtZXJfa2V5PSJhbm9ueW1vdXMiLG9hdXRoX25vbmNlPSI3Nzc0ODMyIixvYXV0aF9zaWduYXR1cmU9IkxuckZHODdxdHRxZUhsUlQ1emRndmtEZ1UzTSUzRCIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNDIxNDI3NzIiLG9hdXRoX3Rva2VuPSIxJTJGTUk2QjJEcUpQNEZFa0RSTFVLckQ1bDQ2c1EwNzU4LTJ1Y0VLQlktRGVCMCIsb2F1dGhfdmVyc2lvbj0iMS4wIg == \ r \ n'回复: '235 2.7.0 已接受\r\n'回复: retcode (235);消息:2.7.0 接受

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

send: 'ehlo [192.168.2.4]\r\n'回复:'250-mx.google.com 为您服务,[75.173.8.127]\r\n'回复:'250-SIZE 35882577\r\n'回复: '250-8BITMIME\r\n'回复: '250-AUTH LOGIN PLAIN XOAUTH\r\n'回复: '250 增强状态代码\r\n'回复: retcode (250);消息:mx.google.com 为您服务,[75.173.8.127]尺寸 358825778BITMIME授权登录 普通 XOAUTH增强状态代码发送:'邮件发件人:<testing.oauth.1@gmail.com>大小=107\r\n'回复:'530-5.5.1 需要认证.了解更多信息\r\n'回复:'530 5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 tu7sm3163839pbc.55\r\n'回复: retcode (530);消息:5.5.1 需要身份验证.了解更多5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 tu7sm3163839pbc.55发送:'rset\r\n'回复:'250 2.1.5 刷新 tu7sm3163839pbc.55\r\n'回复: retcode (250);消息:2.1.5 冲洗 tu7sm3163839pbc.55回溯(最近一次调用最后一次): 中的文件./gmail_send3.py",第 47 行conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)sendmail 中的文件/usr/lib/python2.7/smtplib.py",第 713 行提高 SMTPSenderRefused(代码,resp,from_addr)smtplib.SMTPSenderRefused: (530, '5.5.1 Authentication Required. 了解更多信息:\n5.5.1 http://support.google.com/mail/bin/answer.py?answer=14257 tu7sm3163839pbc.55', 'testing.oauth.1@gmail.com')

解决方案

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

更新
https://github.com/google/gmail-oauth2-tools/wiki/OAuth2DotPyRunThrough
这是使用 oauth2 的新演练,似乎 xoauth 已被声明为过时,我已经更新了 URL 以获取旧版本的 xoauth.py 文件,以防万一仍然需要它Google 似乎更改了他们的 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.comxoauth.py:74: DeprecationWarning: sha 模块已弃用;改用 hashlib 模块进口沙oauth_token_secret:HFJEvjcTfiXSPxgLzDh-1yaHoauth_token:4/EwUxCtY9ye1kdtb4uNJIcaUe9KXloauth_callback_confirmed: 真要授权令牌,请访问此网址并按照说明生成验证码:https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=4%2FEwUxCtY9ye1kdtb4uNJIcaUe9KXl输入验证码:7XjT15fqk1aNe8152d9oTRcJoauth_token:1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0oauth_token_secret:NysqNqVTulFsdHpSRrPP56sF

让我们测试一下:

$ python xoauth.py --test_imap_authentication --user=testing.oauth.1@gmail.com \--oauth_token=1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0 --oauth_token_secret=NysqNqVTulFsdHpSRrPP56sFxoauth.py:74: DeprecationWarning: sha 模块已弃用;改用 hashlib 模块xoauth 字符串(在 base64 编码之前):获取 https://mail.google.com/mail/b/testing.oauth.1@gmail.com/imap/oauth_consumer_key="anonymous",oauth_nonce="18010070659685102619",oauth_signature="jTJv%2FAFATpzTLmDiFx%3NFA,oauth_signature_method="HMAC-SHA1",oauth_timestamp="1342084141",oauth_token="1%2FMI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0",oauth_version="1.0"XOAUTH串(base64编码):R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL2ltYXAvIG9hdXRoX2NvbnN1bWVyX2tleT0iYW5vbnltb3VzIixvYXV0aF9ub25jZT0iMTgwMTAwNzA2NTk2ODUxMDI2MTkiLG9hdXRoX3NpZ25hdHVyZT0ialRKdiUyRkFGQVRwemZxJTJCWlRMQUF4Rk5tV1BpMCUzRCIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNDIwODQxNDEiLG9hdXRoX3Rva2VuPSIxJTJGTUk2QjJEcUpQNEZFa0RSTFVLckQ1bDQ2c1EwNzU4LTJ1Y0VLQlktRGVCMCIsb2F1dGhfdmVyc2lvbj0iMS4wIg ==09:01.40 >COKI1 认证 XOAUTH09:01.44 <+09:01.45 写入文字大小 44409:02.68 <* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE09:02.68 <COKI1 OK testing.oauth.1@gmail.com 测试 Oauth 认证(成功)09:02.68 >COKI2 选择收件箱09:03.09 <* 标志 (\Answered \Flagged \Draft \Deleted \Seen)09:03.09 <* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] 允许标记.09:03.09 <* OK [UIDVALIDITY 3] UID 有效.09:03.09 <* 3 存在09:03.09 <* 0 最近09:03.09 <* OK [UIDNEXT 4] 预测下一个 UID.09:03.09 <COKI2 OK [READ-WRITE] 已选择收件箱.(成功)

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

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

直接从文档中获取:

导入 oauth2 作为 oauth导入 oauth2.clients.imap 作为 imaplib# 像往常一样设置你的消费者和令牌.就像任何其他# 三足 OAuth 请求.消费者 = oauth.Consumer('匿名', '匿名')令牌 = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')# 根据谷歌的 XOAUTH 实现设置 URL.确定# 用适当的电子邮件地址替换此处的电子邮件# 你想访问.url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/imap/"conn = imaplib.IMAP4_SSL('imap.googlemail.com')连接调试 = 4# 这是impaplib.IMAP4_SSL 的API 中唯一具有#变了.您现在使用 URL、使用者和令牌进行身份验证.conn.authenticate(网址,消费者,令牌)# 一旦认证了来自impalib.IMAP4_SSL 类的所有内容# 照常工作,无需对代码进行任何修改.conn.select('收件箱')打印 conn.list()>>>conn.authenticate(网址,消费者,令牌)20:11.73 >EPKK1 验证 XOAUTH20:11.78 <+20:11.78 写入文字大小 49620:11.93 <* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE20:11.93 <EPKK1 OK testing.oauth.1@gmail.com 测试 Oauth 认证(成功)>>>conn.select('收件箱')20:17.47 >EPKK2 选择收件箱20:17.58 <* 标志 (\Answered \Flagged \Draft \Deleted \Seen)20:17.58 <* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen \*)] 允许标记.20:17.58 <* OK [UIDVALIDITY 3] UID 有效.20:17.58 <* 3 存在20:17.58 <* 0 最近20:17.58 <* OK [UIDNEXT 4] 预测下一个 UID.20:17.58 <EPKK2 OK [READ-WRITE] 已选择收件箱.(成功)('好的', ['3'])>>>打印 conn.list()20:20.23 >EPKK3 列表"" *20:20.28 <* LIST (\HasNoChildren) "/" "收件箱"20:20.28 <* LIST (\Noselect \HasChildren) "/" "[Gmail]"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/所有邮件"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/Drafts"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/重要"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/已发送邮件"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/垃圾邮件"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/Starred"20:20.28 <* LIST (\HasNoChildren) "/" "[Gmail]/垃圾箱"20:20.28 <EPKK3 OK 成功('OK', ['(\\HasNoChildren) "/" "INBOX"', '(\\Noselect \\HasChildren) "/" "[Gmail]"', '(\\HasNoChildren) "/" "[Gmail]/所有邮件"', '(\\HasNoChildren) "/" "[Gmail]/Drafts"', '(\\HasNoChildren) "/" "[Gmail]/Important"', '(\\HasNoChildren)"/" "[Gmail]/Sent Mail"', '(\\HasNoChildren) "/" "[Gmail]/Spam"', '(\\HasNoChildren) "/" "[Gmail]/Starred"', '(\\HasNoChildren) "/" "[Gmail]/垃圾箱"'])>>>

对于 smtp:

导入 oauth2 作为 oauth导入 oauth2.clients.smtp 作为 smtplib# 像往常一样设置你的消费者和令牌.就像任何其他# 三足 OAuth 请求.# 像往常一样设置你的消费者和令牌.就像任何其他# 三足 OAuth 请求.消费者 = oauth.Consumer('匿名', '匿名')令牌 = oauth.Token('1/MI6B2DqJP4FEkDRLUKrD5l46sQ0758-2ucEKBY-DeB0', 'NysqNqVTulFsdHpSRrPP56sF')# 根据谷歌的 XOAUTH 实现设置 URL.确定# 用适当的电子邮件地址替换此处的电子邮件# 你想访问.url = "https://mail.google.com/mail/b/testing.oauth.1@gmail.com/smtp/"conn = smtplib.SMTP('smtp.googlemail.com', 587)conn.set_debuglevel(真)conn.ehlo('测试')conn.starttls()# 再次从 smtplib.SMTP 修改的唯一内容是身份验证# 方法,其工作方式与 imaplib.IMAP4_SSL 方法相同.conn.authenticate(网址,消费者,令牌)>>>conn.ehlo('测试')发送:'ehlo 测试\r\n'回复:'250-mx.google.com 为您服务,[142.255.57.49]\r\n'回复:'250-SIZE 35882577\r\n'回复: '250-8BITMIME\r\n'回复:'250-STARTTLS\r\n'回复: '250 增强状态代码\r\n'回复: retcode (250);消息:mx.google.com 为您服务,[142.255.57.49]尺寸 358825778BITMIME开始TLS增强状态代码(250,mx.google.com 为您服务,[142.255.57.49]\nSIZE 35882577\n8BITMIME\nSTARTTLS\nENHANCEDSTATUSCODES")>>>conn.starttls()发送:'STARTTLS\r\n'回复: '220 2.0.0 准备启动 TLS\r\n'回复: retcode (220);消息:2.0.0 准备启动 TLS(220, '2.0.0 准备启动 TLS')>>>conn.authenticate(网址,消费者,令牌)发送: 'AUTH XOAUTH R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL3NtdHAvIG9hdXRoX2JvZHlfaGFzaD0iMmptajdsNXJTdzB5VmIlMkZ2bFdBWWtLJTJGWUJ3ayUzRCIsb2F1dGhfY29uc3VtZXJfa2V5PSJhbm9ueW1vdXMiLG9hdXRoX25vbmNlPSI4MTEyMDkxNCIsb2F1dGhfc2lnbmF0dXJlPSJSaUFsTGdQWnpBSkNQJTJGWmx5aGRpYU1CV0xiTSUzRCIsb2F1dGhfc2lnbmF0dXJlX21ldGhvZD0iSE1BQy1TSEExIixvYXV0aF90aW1lc3RhbXA9IjEzNDIwODU2NzIiLG9hdXRoX3Rva2VuPSIxJTJGTUk2QjJEcUpQNEZFa0RSTFVLckQ1bDQ2c1EwNzU4LTJ1Y0VLQlktRGVCMCIsb2F1dGhfdmVyc2lvbj0iMS4wIg == \ r \ n'回复: '235 2.7.0 已接受\r\n'回复: retcode (235);消息:2.7.0 接受>>>

和发送电子邮件:

<预><代码>>>>conn.authenticate(网址,消费者,令牌)发送: 'AUTH XOAUTH R0VUIGh0dHBzOi8vbWFpbC5nb29nbGUuY29tL21haWwvYi90ZXN0aW5nLm9hdXRoLjFAZ21haWwuY29tL3NtdHAvIG9hdXRoX2JvZHlfaGFzaD0iMmptajdsNXJTdzB5VmIlMkZ2bFdBWWtLJTJGWUJ3ayUzRCIsb2F1dGhfY29uc3VtZXJfa2V5PSJhbm9ueW1vdXMiLG9hdXRoX25vbmNlPSI2OTg3ODM3NiIsb2F1dGhfc2lnbmF0dXJlPSIlMkZjUGslMkJ​​RVWVJY1RaYXp1ekkwR1FzdkdtbDFBJTNEIixvYXV0aF9zaWduYXR1cmVfbWV0aG9kPSJITUFDLVNIQTEiLG9hdXRoX3RpbWVzdGFtcD0iMTM0MjA4NjAxNCIsb2F1dGhfdG9rZW49IjElMkZNSTZCMkRxSlA0RkVrRFJMVUtyRDVsNDZzUTA3NTgtMnVjRUtCWS1EZUIwIixvYXV0aF92ZXJzaW9uPSIxLjAi \ r \ n'回复: '235 2.7.0 已接受\r\n'回复: retcode (235);消息:2.7.0 接受>>>header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'>>>msg = header + '\n 这是我的测试消息 \n\n'>>>conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)发送:'邮件发件人:<testing.oauth.1@gmail.com>大小=107\r\n'回复: '250 2.1.0 OK gb7sm6540492qab.12\r\n'回复: retcode (250);消息:2.1.0 OK gb7sm6540492qab.12发送:'rcpt TO:<testing.oauth.1@gmail.com>\r\n'回复: '250 2.1.5 OK gb7sm6540492qab.12\r\n'回复: retcode (250);消息:2.1.5 OK gb7sm6540492qab.12发送:'数据\r\n'回复: '354 继续 gb7sm6540492qab.12\r\n'回复: retcode (354);消息:继续 gb7sm6540492qab.12数据:(354,'继续 gb7sm6540492qab.12')send: 'To:testing.oauth.1@gmail.com\r\nFrom: testing.oauth.1@gmail.com\r\nSubject:testing \r\n\r\n 这是我的测试信息 \r\n\r\n.\r\n'回复:'250 2.0.0 OK 1342086030 gb7sm6540492qab.12\r\n'回复: retcode (250);消息:2.0.0 OK 1342086030 gb7sm6540492qab.12数据:(250,'2.0.0 OK 1342086030 gb7sm6540492qab.12'){}>>>

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

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

导入 oauth2 作为 oauth导入 oauth2.clients.smtp 作为 smtplib消费者 = oauth.Consumer('匿名', '匿名')令牌 = 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(真)conn.ehlo('测试')conn.starttls()conn.authenticate(网址,消费者,令牌)header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'msg = header + '\n 这是我的测试消息 \n\n'尝试:conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)除了例外,例如:打印 str(ex)打印 'reying ...'conn.authenticate(网址,消费者,令牌)conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

虽然你也可以直接使用 xoauth:

导入时间导入 smtplib导入 xoauth消费者 = xoauth.OAuthEntity('匿名', '匿名')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(真)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 这是我的测试消息 \n\n'smtp_conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

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

虽然这似乎总是有效

导入 oauth2 作为 oauth导入 oauth2.clients.smtp 作为 smtplib消费者 = oauth.Consumer('匿名', '匿名')令牌 = 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(真)conn.ehlo('测试')conn.starttls()连接.elo()conn.authenticate(网址,消费者,令牌)header = 'To:testing.oauth.1@gmail.com\n' + 'From: testing.oauth.1@gmail.com\n' + 'Subject:testing \n'msg = header + '\n 这是我的测试消息 \n\n'conn.sendmail('testing.oauth.1@gmail.com', 'testing.oauth.1@gmail.com', msg)

看起来你需要在认证之前调用 conn.ehlo().

So I can login to and send mail through gmail using smtplib (using the script below), but I was just wondering if using oauth2 was an option like with imaplib? I didn't see anything on the smtplib documentation page about oauth and I haven't found anything googling. Thanks.

#! /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();

Edit:

Thanks to samy.vilar for the very detailed explaination provided in his answer. However, I'm having a little trouble. Here is my script:

#! /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)

What is puzzling me, is that it appears to authenticate ok:

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

But then when it comes to sending the email, it seems to forget that conn was already authenticated:

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')

解决方案

Interesting, I think it is possible, I found the following links
https://developers.google.com/google-apps/gmail/oauth_overview

UPDATE
https://github.com/google/gmail-oauth2-tools/wiki/OAuth2DotPyRunThrough
This is the new walk through using oauth2, it seems like xoauth has being declared obsolete, I've update the URL to get the older version xoauth.py file, in case any one still needs it, though it looks like Google has changed their API and this walkthrough is no longer applicable.

you can use xoauth directly or https://github.com/simplegeo/python-oauth2/ to actually communicate I recommend the latter, its more versatile.

Apparently you first need to download xoauth.py script.

$ 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

lets test it:

$ 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)

looks like we are good to go. you may want to set up a virtualenv

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

and taken right from the docs:

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"'])
>>> 

for 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
>>>

and to send emails:

>>> 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')
{}
>>>

make sure you authenticate before sending out emails.
hope this helps ...

UPDATE
There may be a bug that requires re-authentication, the following should work.

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)

though you can also use xoauth directly as such:

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)

this seems to always work, I should submit a ticket to python-oauth2 team, thank you.

THOUGH THIS ALSO SEEM TO ALWAYS WORK

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)

it looks you need to call conn.ehlo() before authenticating.

这篇关于蟒蛇&amp;smtplib:是否可以使用 oauth2 通过 gmail 发送邮件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆