为了从 Gmail 联系人中提取电子邮件地址并将其保存到文本文件中,编写了一个简单的 Python 脚本,该脚本基于 Python gdata 库(当前版本为 2.0.18)运行在 cron 作业中。但在本月早些时候,由于 Google 不再支持 ClientLogin 协议,该脚本停止工作,错误信息如下:
{'status': 401, 'body': '<?xml version="1.0" encoding="UTF-8"?>\n<errors xmlns="http://schemas.google.com/g/2005">\n <error>\n <domain>GData</domain>\n <code>required</code>\n <location type="header">Authorization</location>\n <internalReason>Login Required</internalReason>\n </error>\n</errors>\n', 'reason': 'Unauthorized'}
过去曾处理过其他地方(如 App Engine 应用程序)的类似问题,但这次忘记了需要对脚本进行转换。现在发现不知道该如何让它工作。
找到的所有参考,如 Google Apps 开发者博客或 StackOverflow 上的链接,都建议使用 OAuth2Token。但是,这需要一个客户端 ID 和客户端密钥,这些密钥来自与应用程序绑定的 Google API 控制台。而我并没有一个应用程序,只想通过我的脚本进行认证。
是否有适当的方法可以在独立脚本中完成此操作?或者真的无法再完成此操作了?
以下是如何在 gdata 中使用 ClientLogin 的代码:
from gdata.contacts.service import ContactsService, ContactsQuery
user = "myuser@gmail.com"
password = "mypassword"
addresses = set()
client = ContactsService(additional_headers={"GData-Version":"2"})
client.ssl = True
client.ClientLogin(user, password)
groups = client.GetGroupsFeed()
for group in groups.entry:
if group.content.text == "System Group: My Contacts":
query = ContactsQuery()
query.max_results = 9999 # large enough that we'll get "everything"
query.group = group.id.text
contacts = client.GetContactsFeed(query.ToUri())
for contact in contacts.entry:
for email in contact.email:
addresses.add(email.address.lower())
break
return addresses
希望可以找到其他方法来替换 client.ClientLogin(),同时保留使用 gdata 的其他部分。或者,如果无法使用 gdata 完成此操作,可以考虑转向其他提供类似功能的库。
2、解决方案
由于 gdata 库不再支持 ClientLogin 协议,需要使用 OAuth2 进行认证。
根据推荐,可以使用 OAuth2 设备流程,这对于独立脚本来说可能更简单。
以下是如何使用 OAuth2 设备流程进行认证的步骤:
- 创建一个 Cloud Developer 项目,并启用 Contacts API。
- 在 API 控制台中创建 OAuth2 凭据,并选择“其他”作为应用程序类型。
- 在脚本中使用 OAuth2Client 库,可以在此链接上找到库的文档:github.com/google/oaut…
- 使用 OAuth2Client 库中的
refresh_grant来调用刷新令牌,以获取新的访问令牌。 - 将新的访问令牌传递给 gdata 库,以进行认证。
以下是如何使用 OAuth2Client 库进行认证的代码示例:
import oauth2client
# 创建 OAuth2 凭据
credentials = oauth2client.client.OAuth2Credentials(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
refresh_token="YOUR_REFRESH_TOKEN"
)
# 刷新令牌以获取新的访问令牌
credentials.refresh(oauth2client.client.GoogleCredentials.get_application_default())
# 使用新的访问令牌对 gdata 库进行认证
client = ContactsService()
client.ssl = True
client.additional_headers['Authorization'] = f'Bearer {credentials.access_token}'
使用此方法,就可以在独立 Python 脚本中使用 gdata 库对 Google 进行认证,从而提取 Gmail 联系人中的电子邮件地址。