说到邮件通知,简单的试了一下,发觉里面的坑蛮深的。
很多云服务直接把端口给封了。。。
邮件服务商也满满的套路,巴不得你用他们的app才好(海外一样)。
开启第三方SMTP服务各种身份验证。隔三岔五“你是不是本人?”
真正的spam拦也拦不住,尽给真正用户增加使用门槛。
抢市场的时候总是野蛮生长,当大头后根据相关规范!
有的时候还发现你的邮件躺在垃圾邮箱里。。。
得了,通知而已,让人代发吧。
前言
- Github在什么时候会给我发邮件呢?
- 我设置关注的repo发布了新的release
- 我设置关注的repo有了新的issue
- 我设置关注的repo有了新的pull request
- 我设置关注的issue下有了新的回复
- 我设置关注的pull request有了新的回复
- 我设置关注的gist有了新的回复
- 我参加并设置关注的team有了讨论
- …
- Github给我发邮件的标题/内容是什么呢?
- 基本是事件主体的内容。
因为需求是通知,控制正文的文本内容很容易达到。
更复杂的,比如格式要求、附件、回执等这里就不做考虑了。
- 基本是事件主体的内容。
- 隐私和安全性问题
- 如果不考虑邮件通知的隐私问题,对象直接取用公开的repo即可。
- 项目可以设为私有(由此可能引发实现的某些问题,但可以解决。)
- Gist可以设为secret,但其内容仍然是对任何人可见的。
- 关于实现的考量
- 由于Github不可能发邮件提示你本人自己的操作,故而需要两个账号。
- 由于个人私有项目无法对第二人可见,故而只能采用组织私有项目的形式。
这需要再创建一个组织。
实现思路
- 一种利用issue(comment)的实现思路
- 准备账号A,该账号的注册邮箱用于接收邮件
- 准备账号B,并生成用于github操作的token。该账号用于创建issue和issue comment
- A(或者B)创建一个组织C,并邀请B(或者A)加入
- A(或者B)在组织C创建一个私有的项目repo
- 确认AB对repo的接入权限
- 确认A对repo的关注
- 接下来,考虑B如何在repo新建issue和issue comment即可
- 先人为在repo创建一个issue
- api查询最近的issue信息
- 若最近的comment数量大于20,api新建一个issue
- 若最近的comment数量小于等于20,在该issue下api新建一个issue comment
示例代码
#!/usr/bin/env python
# coding:utf-8
import os
import requests,json
import time
def load_from_env():
repo_full_name = os.environ.get('MY_REPOSITORY')
owner = os.environ.get('MY_OWNER')
repo = repo_full_name[len(owner) + 1:]
token = os.environ.get('MY_GITHUB_TOKEN')
github_config = {
"repo": repo,
"owner": owner,
"token": token,
}
return github_config
class GithubHelper:
def __init__(self, owner, repo, token, **args):
self.auth = token
self.owner = owner
self.repo = repo
def getLatestRelease(self, **args):
url = 'https://api.github.com/repos/%s/%s/releases/latest'%(self.owner, self.repo)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
res = requests.get(url, headers=headers).json()
#print(res)
return res
def updateReleaseBody(self, release_id, body, **args):
url = 'https://api.github.com/repos/%s/%s/releases/%d'%(self.owner, self.repo, release_id)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
param = {
"body": body
}
res = requests.request("PATCH", url, data=json.dumps(param), headers=headers).json()
#print(res)
return res
def updateReleaseAsset(self, asset_id, name, **args):
url = 'https://api.github.com/repos/%s/%s/releases/assets/%d'%(self.owner, self.repo, asset_id)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
param = '{"name":"%s"}'%name
res = requests.request("PATCH", url, data=param, headers=headers).json()
#print(res)
return res
def deleteReleaseAsset(self, asset_id, **args):
url = 'https://api.github.com/repos/%s/%s/releases/assets/%d'%(self.owner, self.repo, asset_id)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
res = requests.request("DELETE", url, headers=headers)
#print(res.text)
return res
def uploadReleaseAsset(self, release_id:int, name, data, **args):
url = 'https://uploads.github.com/repos/%s/%s/releases/%d/assets?name=%s'%(self.owner, self.repo, release_id, name)
headers = {'content-type': 'application/octet-stream', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
res = requests.request("POST", url, data=data, headers=headers).json()
#print(res)
return res
def replaceLatestReleaseAssets(self, name, data, **args):
if not "releaseInfo" in locals():
releaseInfo = self.getLatestRelease()
release_id = releaseInfo['id']
assets = releaseInfo['assets']
# 删除原来的附件
for asset in assets:
if name == asset["name"]:
self.deleteReleaseAsset(asset['id'])
break;
# 上传新的附件
return self.uploadReleaseAsset(release_id, name, data)
def createIssueComment(self, issue_id:int, content:str, **args):
url = 'https://api.github.com/repos/%s/%s/issues/%d/comments'%(self.owner, self.repo, issue_id)
data = {"body":content}
headers = {
'Accept': 'application/vnd.github.v3.+json',
'Content-Type': 'application/json; charset=utf-8',
"Authorization": "token "+ self.auth
}
#d = encode_multipart_formdata(data, boundary=boundary)
res = requests.request("POST", url, data = json.dumps(data), headers=headers).text
print(res)
return res
def createIssue(self, title, body, **args):
url = 'https://api.github.com/repos/%s/%s/issues'%(self.owner, self.repo)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
param = {
"title": title,
"body": body,
}
res = requests.request("POST", url, data=json.dumps(param), headers=headers).json()
print(res)
return res
def getLatestIssue(self, **args):
url = 'https://api.github.com/repos/%s/%s/issues?per_page=1'%(self.owner, self.repo)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.v3.+json', "Authorization": "token "+ self.auth}
res = requests.request("GET", url, headers=headers).json()
print(res)
return res
def send_notice(self, content, **args):
res = self.getLatestIssue()
if isinstance(res, list) and len(res) <= 20:
self.createIssueComment(res[0]["number"], content)
else:
self.createIssue('邮件通知issue[%d]'%issue["number"], content)
def createGist(self, gist_id, content, **args):
url = 'https://api.github.com/gists/%s/comments'%(gist_id)
print(url)
headers = {'User-Agent': 'None', 'Accept': 'application/vnd.github.raw', "Authorization": "token "+ self.auth}
param = {
"body": content,
}
res = requests.request("POST", url, data=json.dumps(param), headers=headers).json()
print(res)
return res
if __name__ == "__main__":
github_config = load_from_env()
"""或者这样,repo是项目名,owner是组织名,token是B的tokan
github_config = {
"repo": repo,
"owner": owner,
"token": token,
}
"""
helper = GithubHelper(**github_config)
#helper.getLatestRelease()
#helper.updateReleaseAsset(asset_id = 123,name = "test.zip")
#helper.uploadReleaseAsset(release_id = 123,name = "test.zip",data = 'hahaha')
#helper.deleteReleaseAsset(asset_id = 123)
#helper.replaceLatestReleaseAssets(name = "test.zip", data = '1234测试'.encode("utf-8"))
#date_now = get_now_date_str()
#body = '更新于%s'%date_now
#helper.updateReleaseBody(release_id = 123, body=body)
#helper.createIssueComment(123, "test @xxx")
#helper.createIssue('邮件通知issue', "test @xxx")
helper.send_notice("快点干活啦~~")