nohup python3 -u g.py 300 >/dev/null 2>error.log &
做这个功能费了我老大劲了,首先想到的还是利用现成的软件,尝试了一圈发现都不满意。然后不想重复造轮子,就搜索如何把 Gmail 推送到钉钉,结果只搜到了诸如 Python 如何调用 Gmail API、钉钉群机器人使用这样的相关文章,竟然没找到完整造这个轮子的文章。最后就自力更生了。目前的使用体验还行,有个小问题是有时可能要登一下远程服务器手动重启程序。
本文实现方法需要一个能同时调用 Gmail API、钉钉群机器人 API 的服务器。
实现效果:
先说下已经尝试的现成的软件。(测试时间 2020-06)
首先当然要试试钉钉能不能登录 Gmail,Mac、Android 端都无法登录(当然代理是开着的),我登的邮箱是 Gmail 的企业邮箱。Android 端开代理可以登录,但属于未验证的应用,Google 拒绝登录。
用 Gmail 生成的应用专用密码登录,会收到邮件:
然后,没找到 Gmail 的官方 macOS 客户端。
最后是各类 Android 端第三方邮件 APP,主要要求是不用代理也能收信。
网易邮箱大师:登录、收信均不需要代理,但登不上我司企业 Gmail 邮箱
Outlook:登录需要代理、收信不需要,Android 端邮件推送一直抽风
MIUI 自带电子邮件:登录需要代理、收信不需要,连接不稳定,有时看不了邮件
QQ 邮箱:没亲自用,据说推送也有问题
其他邮箱 APP 不想试了,而且有信息泄露风险。
下面是本文的主要内容,如何把 Gmail 邮件推送到钉钉。
主要参考
Python 读取gmail, Python 搜索gmail, Python操作gmail, How to access Gmail using Python
这篇即可,Google 现在支持中文界面。
印象中需要注意的部分是选择创建个人或组织的应用,我的是 Gmail 企业邮箱,所以创建的应用是属于组织的,个人的应用我不确定能不能以及如何创建。
本来我是打算这部分也全部自己截图做一遍的,但写文章时距离我完成程序已经过了 2 个月,就不想写这部分了。
一开始我尝试用 Cloud Pub/Sub API 推送通知到钉钉 Webhook,结果出错:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/watch?alt=json returned "Error sending test message to Cloud PubSub projects/gmail-push-XXXXX/topics/my-topic : User not authorized to perform this action.">
而且该方式推送的消息格式不能自定义,与钉钉机器人消息格式不匹配
下面讲解代码。注释我已经写得比较详细了。主要功能就是调用 Gmail API 读邮件,调用钉钉 API 发邮件。代码里的函数比较多,我只用了一部分,其他调用 Gmai API 函数的功能无法保证可用。
具体我与前人不同,自己实现的函数是 check_new_email,功能是通过 historyId 检查新邮件。
无符号整数,按时间顺序增长,增量随机。通常有效期至少一周,少数情况下只有几小时。如果 startHistoryId 无效或过期会返回 404。
可以确定的是:读取邮件(网页上读取)会导致 HistoryId 增加。感觉:每次调用 service.users().history().list() 响应的 HistoryId 都会增长(即使收件箱无变化)
get_messages_by_query 函数具有搜索功能,搜索时用的 subject 好像不支持中文,用了邮件的编码也搜不到。
在 Gmail 网页上能看到的 Message-ID 不是 Gmail API 的邮件 id。
代码部分就这么多(隔时间太久,想不起来细节了。)
创建单人群聊:手机,面对面建群,不添加其他人
添加机器人:智能群助手 - 添加机器人 - 自定义机器人
记录 WebHook 地址里面的 access_token,这个要写在文件里。
测试钉钉机器人:
curl 'https://oapi.dingtalk.com/robot/send?access_token=token' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text","text": {"content": "关键词"}}'
我的 VPS 在美国,调用一次 API 花 7 秒时间,在服务器上解析域名,查到的 IP 地址是阿里在美国的服务器,不需要考虑跨墙问题。
钉钉每个机器人每分钟最多发送 20 条,如果超过 20 条,会限流 10 分钟。
第一次运行前需要准备下列文件:创建并填写 access_token 文件,创建 history_id 文件,准备好 credentials.json。
第一次运行程序后,会弹出一个页面,此时需要把权限授予应用。
查看 Google 帐号第三方访问权限
使用 virtualenv(可选):source venv/bin/activate
安装程序运行所需模块:pip3 install 。各人环境不同,具体模块请看代码
设为 5 分钟推送一次。解释一下参数,文件名的面的 300,是指 300 秒,其他的一般无需修改。
nohup python3 -u g.py 300 >/dev/null 2>error.log &
查看是否运行成功:
ps aux | grep "g.py"
成功的回显应该有 2 行
每隔不定期的时间,会产生:BrokenPipeError: [Errno 32] Broken pipe 错误,错误原因我不明白。可能只是 VPS 网络波动。如果有读者亲自解决过这个问题,还请赐教。
Gmail API 调用:Python 读取gmail, Python 搜索gmail, Python操作gmail, How to access Gmail using Python
官方文档:Gmail API Reference