GitHub App如何获取用户非公开邮箱并实现Git用户与自有系统用户映射
问题定位
- API调用逻辑存在错误
https://api.github.com/user/emails是当前授权用户专属的邮箱查询端点,不能在路径后拼接用户名查询其他用户的邮箱,不符合GitHub API规范,自然会返回异常结果。
如果要查询指定用户的公开邮箱,需调用https://api.github.com/users/{username},但该接口返回的email字段仅对应用户在个人主页主动公开的邮箱,用户设置不公开的话返回值为null。不存在任何方式可以绕过该隐私限制获取用户未公开的个人资料邮箱,这是GitHub官方的隐私保护规则。 - 权限匹配错误
你当前持有的user:read权限仅支持读取用户公开的基础资料,要获取授权用户的完整邮箱列表(包括未公开的),需要申请user:email的OAuth scope,且只能获取主动授权过你的GitHub App的用户的邮箱,无法获取未授权用户的邮箱。
可行的映射方案
结合你监听合并事件、仅持有用户邮箱和姓名的现状,推荐以下落地路径:
- 方案1:从提交记录中提取邮箱
你监听的合并事件本身包含对应的PR信息,可以通过PR的提交记录接口GET /repos/{owner}/{repo}/pulls/{pull_number}/commits获取该PR下所有提交的作者、提交者邮箱,不管用户个人资料是否公开邮箱,提交记录里的commit.author.email、commit.committer.email都是用户本地Git配置的真实邮箱,可直接提取该字段和你系统内的用户做匹配。该方案不需要额外申请用户相关权限,只要你的App有仓库的读取权限即可。 - 方案2:引导用户主动绑定
在用户首次访问你的服务时,引导用户通过GitHub OAuth授权登录你的App,申请user:email权限后即可获取该用户的所有关联邮箱,同时绑定GitHub用户唯一ID(id字段,永久不变,不会因为用户修改用户名/邮箱失效)和你系统内的用户信息,映射准确性最高。 - 方案3:组织内场景申请成员读取权限
如果你的App仅服务于特定组织,可以在申请组织安装时申请组织成员读取权限,组织管理员同意后即可获取组织内所有成员的内部可见邮箱,不需要用户单独授权。
正确的API调用示例(获取授权用户的邮箱)
如果你需要获取主动授权用户的邮箱,参考以下修正后的代码:
// 注意该端点不需要拼接用户名,用用户的OAuth token而非installation token调用 Request req = new Request.Builder() .url("https://api.github.com/user/emails") .header("Authorization", "Bearer " + userOauthToken) .get() .build(); Response resp = client.newCall(req).execute(); String jsonResp = resp.body().string(); // 该接口返回的是数组,包含用户所有关联邮箱,primary为true的是主邮箱 List<Map> emails = gson.fromJson(jsonResp, List.class); for(Map emailInfo : emails) { if((boolean) emailInfo.get("primary")) { String primaryEmail = emailInfo.get("email").toString(); // 匹配你系统内的用户 } }
内容的提问来源于stack exchange,提问作者Rishi Saraf
相关产品推荐
相关产品推荐

