要进行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();// ipcMainconsole.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、使用replace+正则表达式过滤邮箱内容提取摘要时,在多封邮件,且邮件内容好几万个字符时,发现邮箱列表(列表获取的摘要是从内容过滤出文本拿到的)明显卡顿。排查后发现是正则替换导致的。卡顿具体原因如下:
- 当字符数量较多时,使用replace配合正则表达式可能会有性能问题的原因主要有两个:
-
- 正则表达式的处理复杂度:正则表达式的匹配和替换操作通常比较复杂,特别是当需要处理大量字符时,正则表达式的处理复杂度会相应增加。正则表达式引擎在处理长字符串时可能需要进行多次匹配和回溯操作,这会导致性能下降。
-
- replace 的执行次数:replace方法会在字符串中搜索并替换所有匹配的字符或模式。如果字符数量很多,那么替换操作也会频繁执行很多次,这会增加整体的执行时间。
0、office365的azure邮箱在测试过程中,由于频繁登进登出,会触发微软的安全机制,限制连接邮箱服务器,因此这会导致授权登录成功,但是实际上后台sdk连接不上微软的邮箱服务器,导致获取邮箱信息失败!!!【排查难度*****】
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赋值的。
如下所示:
<webviewsrc={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 为什么您需要访问敏感和/或受限用户数据