要进行Office365邮箱的授权对接,你需要先申请一个应用,并获取授权访问令牌。
以下是一个简单的步骤:
- 登录 Azure 门户:https://portal.azure.com/
- 创建一个新的应用程序,或者使用现有的应用程序。要创建新的应用程序,请选择“Azure Active Directory”仪表板中的“应用注册”。
- 在应用程序设置中,配置重定向 URI 或网页回调以获取授权代码。
- 授权应用程序向 Office 365 发送电子邮件并访问电子邮件内容。这可以通过 Azure 中的“API 权限”设置或“管理访问”设置轻松完成。
- 通过 OAuth2 流程获取授权代码,使用代码获取令牌并调用 Office 365 API。
在你获取了授权令牌后,你可以使用相应的库或SDK来与 Office 365 邮箱进行交互。例如,使用Microsoft Graph API 来发送和接收邮件,或者使用 Office 365 REST API 来集成邮件和日历等其他功能。
要进行Gmail邮箱的授权对接,你需要先拥有一个gmail邮箱,设置凭据及OAuth同意屏幕相关配置,并获取授权访问令牌。你可以按照以下步骤进行操作:
创建Google Cloud Platform (GCP) 项目:
- 前往Google Cloud Console(https://console.cloud.google.com/)并登录。
- 创建一个新的项目并为其命名。
启用Gmail API:
- 在GCP控制台的导航菜单中,找到API和服务并点击进入。
- 点击“+启用API和服务”按钮。
- 在搜索栏中输入“Gmail”并选择“Gmail API”。
- 点击“启用”按钮以启用Gmail API。
创建OAuth 2.0凭据:
- 在API和服务页面,点击“凭据”选项卡,然后点击“+创建凭据”按钮。
- 选择“OAuth客户端ID”选项。
- 选择应用类型,如网页应用程序或桌面应用程序。
- 填写必要的信息,例如名称和重定向URL。
- 完成后,将生成客户端ID和客户端密钥。
配置OAuth 2.0访问权限:
- 在GCP控制台的导航菜单中,找到API和服务并点击进入。
- 点击“OAuth同意屏幕”选项卡,并选择应用程序类型。
- 填写必要的信息,如应用名称和开发者联系信息。
- 在“范围”部分,添加对Gmail API的访问权限,例如
https://www.googleapis.com/auth/gmail.readonly
。 - 点击“保存”按钮。
进行授权访问:
在浏览器中打开以下授权URL,并将其中的参数替换为你的实际值:
https://accounts.google.com/o/oauth2/auth?client_id=[YOUR_CLIENT_ID]&redirect_uri=[YOUR_REDIRECT_URI]&response_type=code&scope=https://www.googleapis.com/auth/gmail.readonly&access_type=offline
用户将被要求授予访问权限,并返回一个授权代码。
交换授权码以获取访问令牌:
- 使用前面步骤中的授权代码,向以下URL发送POST请求,以获取访问令牌:
POSThttps://accounts.google.com/o/oauth2/token
- 在请求中包含以下参数:
code
:前面步骤中获得的授权代码。
client_id
:你的应用程序的客户端ID。
client_secret
:你的应用程序的客户端密钥。
redirect_uri
:你的重定向URI。
grant_type
:设置为authorization_code
。
使用访问令牌访问Gmail API:
- 使用获得的访问令牌,发送HTTP请求以通过Gmail API访问用户的邮件数据。
以上是进行Gmail邮箱的授权对接的基本步骤。你可以根据你的具体需求和开发环境进一步调整和配置。
邮箱项目实施中所遇到的问题:
1、选中一个邮箱的收件箱,之前选中的邮箱的收件箱还被选中bug
2、未读数未显示bug
3、No refreshToken in msal-node when providing scope "offline-access"
1、控制抖动频率,防止用户过快刷新导致崩溃,骨架屏时,用户切换其他邮箱的文件夹,又可以刷新列表,现在要做一个限制用户在骨架屏没加载完毕前,点击刷新不做处理。
2、第一次安装完electron客户端包后,收件人输入一个错误地址,然后弹出了那个编辑收件人的引导语,引导语消失以后,这个错误的收件人前面有个空白区域。 只有把vv-debug 这个文件夹删除掉,才能复现。
3、刷新令牌过期后,365刷新逻辑有问题。可能是初始化机制问题。
4、针对错序问题,需要给获取邮箱文件夹和文件夹列表的sdk提供时间戳,必要的话前端通过id处理判断是否是同一个邮箱发起的请求。
5、删除邮箱成功的图标是错误时的打叉图标,并且删除在还没弹框确认时就删成功了!
1、点击第二个邮箱的收件箱,选中后会刷新邮件列表,此时选中状态会被撤销掉【bug】。
2、过期时,google会有警告图标,但是刷新后code=0页还是出现了该图标,退出邮箱重进才恢复正常。【bug】。
3、草稿收件人 输入4 韦毅(下拉搜索选人组件) 会发现无法选中,可能是该数据是脏数据。
4、选择一个邮箱,点击一个邮件,再点击切换其他邮件,居然会变成拖拽多选?(变成了默认展示的数据了,默认是开启的允许多选拖拽,属于错误的状态)
1、写一个google的demo,同步scopes和其他配置,用来对照google auth2认证是否稳定。
2、UI如果有提供再进行还原。
3、365过期无法通过刷新令牌验证成功。
4、调用update接口后的回调里,进行valifyPassword验证发现该函数所有参数都没有数据!
5、当超时后,会进行update更新令牌数据,但是列表没有获取到,这时需要同步更新验证verifyPd,但是看起来好像不是这个问题导致的,像是因为新令牌验证不通过
google阶段问题总结
-
gmail 的2个测试邮箱在令牌有效期内,都可以接收邮件。
-
gmail 的2个测试邮箱在令牌有效期内,都可以发送邮件。
-
gmail在token有效期内可以发送成功邮件。并且发现添加有时候可以通过,有时候通不过。
-
gmail只剩下超时情况还没有进行复盘!
-
发现bug,点击已发送,收件箱未读数量变29,点回收件箱数量变30。
-
gmail测试账户1用刷新令牌获取访问令牌验证失败了,猜测是帐户本身出了问题导致无法访问。
-
gmail测试账户2用刷新令牌获取访问令牌验证成功了,但是首次刷新的时候,文件夹打开没有内容,说明没有在更新时进行文件夹列表的获取!!!
-
并且gmail测试账户1更新访问令牌后可以获取到新邮件,也可以发送邮件。
其他bug
【bug】从126发邮件到gmail和office365邮箱,gmail邮箱在不退出邮箱Tab重新打开的情况下,点击中间区域的刷新图标,发现收件箱没有刷新新的数据。退出邮箱Tab重新打开则可以刷出来!!!最后发现是因为每3分钟轮询了未读邮件和未读数,与点击刷新无关。但是可能出问题的那个时候轮询是未生效的。最后纠正,前面的现象是错误的,手动点击刷新也是会获取未读数和未读邮件的。结论:可能是刚好那个时候梯子网络不好或者gmail服务器繁忙。
【PS】:一开始进来邮箱tab页面的时候,可能获取到了邮箱和邮箱文件夹,但是中间的邮件区显示暂无数据,这边的做法是通过轮询定时去查数据,后面就有数据了!!!
1、删除gmail邮箱后不关闭tab重新添加3次,全部verifyPsd失败。关闭tab后重进,再添加gmail成功。成功后再删掉,再新增仍旧成功。那么引起首次失败的原因是什么?关闭tab,再次打开tab,删掉gmail,添加gmail,添加成功了。
2、超期的gmail邮箱以及365邮箱收不到新邮件,即便已经刷新了token,这个时候需要关闭邮箱TAB重新进才能收到,此时又再次获取了token以及update了一次。可能是缺少了初始化的数据导致的该BUG!并且,提示有问题,提示删除,其实不一定要删除。
阶段问题总结:
-
office365支持PC换机保存状态 google支持(但是不稳定)。
-
office365目前没有支持登录多个,因为只要登录一次,下次就不走登录逻辑了,改成内部弹窗形式。
-
google 路径重定向被篡改问题。
-
google支持跨PC设备、365暂不支持。跨设备文件夹都为空。
-
google令牌失效及文件夹为空、365令牌失效及文件夹为空。
-
跨端暂不支持,数据不互通,因为接口没有统一成一个端进行调用。
-
google添加帐户有可能在verifyPassword环节验证失败。
PS: vv release命令执行后,会吃掉其他非release命令打印的控制台日志(仅供vv桌面端参考)
渲染进程IPC和主进程通信有2种方式:
1、IpcRenderer.invoke针对需要传递参数的同步或者异步操作
const res = await IpcRenderer.invoke('EMAIL_AUTH_LOGIN', params);
返回值会一直等待主进程返回消息才继续往下传递执行。
2、IpcRenderer.send;针对只需要事件触发的异步通信操作
IpcRenderer.send('EMAIL_AUTH_SIGN_OUT');
主进程IPC和渲染进程通信有2种方式:
// 登录
ipcMain.handle('EMAIL_AUTH_LOGIN', async (_, params) => {
console.log('>>>>>>> EMAIL_AUTH_LOGIN ipcMain.on', params);
const respInfo = await authProvider?.login();
// ipcMain
console.log('>>>>>>> EMAIL_AUTH_LOGIN respInfo', respInfo);
return respInfo;
});
// 退出
ipcMain.on('EMAIL_AUTH_SIGN_OUT', () => {
authProvider?.logout();
});
1、主进程只处理非交互的事情,比如调用auth2的授权接口返回数据给渲染进程,再由渲染进程进行UI交互处理,例如打开一个Tab窗口。
2、桌面端主进程console可以打印在TERMINAL窗口,但渲染进程(渲染主进程、渲染辅助进程)不能,它需要用Log打印才能在vscode的TERMINAL窗口打印,否则它会在浏览器的console里打印。
1、快速删除google邮箱2个时,有一个弹窗列表已删除,但是上面的列表上还存在,数据可能没更新
2、优化进入邮箱调用了两次list接口(第二次是token令牌过期后去刷新的列表)
3、google收件箱的未读数没有显示,后来出现了,可能是拉取google接口数据太慢导致的
【***】 google出现了无法添加成功的原因是因为经过了首次获取到了刷新令牌,后面的测试环节获取到的都是只有访问令牌,而且可能访问令牌失效了,两个原因叠加造成无法绑定。
但是,新获取到的访问令牌是有效的,以上可能只有刷新令牌缺少这一点论据成立。
google auth2有了刷新令牌后,添加成功了
【***】 office365出现token报错的原因,缺少了origin只是表象,实际是因为首次使用刷新令牌后,没有更新成功,而旧的刷新令牌365是会失效的,因此无法使用导致70000报错,PKCE授权码授权流方式只支持Spa。
【***】 office 365 的accessToken如果过期 会导致邮箱文件夹的内容获取不到,如果已加载过的文件夹是存在缓存的。
服务端提供2个接口:
一个上传token和refreshtoken,旧的会被新上传的覆盖。
另一个用来获取token和refreshtoken,在前端自己做一个轮询方案,每隔3秒判断是否过期,
如果过期了就再次调用365或google接口获取token和refreshtoken。
验证google令牌的有效性:
访问基础邮箱账户信息接口:
https://content-gmail.googleapis.com/gmail/v1/users/me/profile
Authorization
值(等同于于token):
Bearer ya29.a0AWY7CkmOojfCwzRGf5iQhAaAL8uKWDEwe9tf8Lga1EDd-1ChS00IDwsjmd2DREbBzksAKLpk8KxowXBErYW3MlwlmACxMLqo9p4IfHAzGZQDik94mJoOOgukIdi30GJ9E0mdGYLJyTzymmqUJpjtWUoGZtkJaCgYKAVQSARMSFQG1tDrp13argMBe8kcNlqXOb4YCIw0163
PS:Bearer后面有个空格,请不要漏掉
验证office365令牌的有效性:
访问基础邮箱账户信息接口:
https://graph.microsoft.com/v1.0/me
Authorization
值(等同于于token):
Bearer ya29.a0AWY7CkmOojfCwzRGf5iQhAaAL8uKWDEwe9tf8Lga1EDd-1ChS00IDwsjmd2DREbBzksAKLpk8KxowXBErYW3MlwlmACxMLqo9p4IfHAzGZQDik94mJoOOgukIdi30GJ9E0mdGYLJyTzymmqUJpjtWUoGZtkJaCgYKAVQSARMSFQG1tDrp13argMBe8kcNlqXOb4YCIw0163
PS:Bearer后面有个空格,请不要漏掉
office365的scopes:
“user.read openid profile offline_access https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20 https%3A%2F%2Foutlook.office365.com%2FSMTP.Send”
其他早期阻塞点备注:
1、micro-app的沙箱问题,在沙箱开启后,无法调用google auth2接口,关闭沙箱后能正常使用
2、针对第三方请求,谨慎处理请求头的添加,避免第三方请求由于严格安全校验导致请求失败
3、桌面、子应用内的iframe缺少执行jsbridge的宿主环境,缺少全局属性及数据
4、子应用中打开窗体,仍旧无法将请求发送完全,react-google-login组件实现的谷歌认证按钮无法静默请求成功谷歌认证接口
5、采用邮箱内封装的request.post请求谷歌接口,请求发送不出去,但axios可以
6、采用electron打开一个窗体内嵌webview的方式打开授权页,在webview内部无法关闭webview授权页面本身(因为是窗体,但主应用本身没有关闭的api提供),并且无法通过协议的方式传递消息(没有开放window.open权限),使用postMessage传递消息在主应用也无法监听到。
7、独立的窗体承载webview实现auth2是不需要用到我们应用内的用户认证相关的逻辑的,又因为所有路由都会默认在BasicLayout布局组件里渲染,且在BasicLayout中有一些用户获取及窗体tab等相关操作,注意,这意味着里边的获取用户信息,获取窗体tab等等信息也会同时加载,但我们只是单纯的一个auth2认证页面,不需要这些,因此我们需要把auth2的路由单独提到最顶级,和/路径对应的BasicLayout布局组件并列,并且需要保证auth2的路由在/路由上方,这是为了防止/在上方时,默认把auth2组件的路由第一级给匹配到,这样会导致下面的与/路由同级的auth2路由不再被匹配。
PS:使用preload的方式在预加载时注入全局方法到webview里的window对象上
8、需要对electron打开的webview里的auth2页面修改Navigator.userAgent的值,目的是为了
过滤掉我们的判断逻辑(isElectronEnv,判断是否是electron的开发环境),它是通过判断userAgent判断是否存在electron字符串作为客户端的依据来给isElectronEnv赋值的。
如下所示:
<webview
src={webviewUrl}
style={{ flex: 1 }}
useragent={userAgent}
preload={preloadJs}
webpreferences="enableRemoteModule=true,nodeIntegration=true,nativeWindowOpen=yes,contextIsolation=false"
/>
Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests
为单页应用程序客户端类型颁发的令牌只能通过跨来源请求兑换。
解决:给请求添加“Origin”标头
headers: {
'Origin': 'http://localhost'
}
谷歌登录发布生产所需材料(office365 Azure不区分环境,不需要提交材料到微软审核):
1、应用名称
2、用户支持电子邮件地址
3、应用icon 100px*100px
4、应用域-----
应用主页地址(为用户提供指向您主页的链接)
应用程序隐私政策链接
申请服务条款链接(为用户提供指向您的公共服务条款的链接)非必须
5、授权域-----
授权登录所要访问我们的域名(vv.cn、vvtechnology.cn)
6、开发商联系方式(电子邮件地址)
7、一段 YouTube 视频,展示了您计划如何使用从范围获取的 Google 用户数据
8、一份书面解释,告诉 Google 为什么您需要访问敏感和/或受限用户数据