实现邮箱管理之gmail邮箱、office365(Azure)邮箱之披荆斩棘问题一览

要进行Office365邮箱的授权对接,你需要先申请一个应用,并获取授权访问令牌。

以下是一个简单的步骤:

  1. 登录 Azure 门户:https://portal.azure.com/
  2. 创建一个新的应用程序,或者使用现有的应用程序。要创建新的应用程序,请选择“Azure Active Directory”仪表板中的“应用注册”。
  3. 在应用程序设置中,配置重定向 URI 或网页回调以获取授权代码。
  4. 授权应用程序向 Office 365 发送电子邮件并访问电子邮件内容。这可以通过 Azure 中的“API 权限”设置或“管理访问”设置轻松完成。
  5. 通过 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请求,以获取访问令牌:
    POST https://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 为什么您需要访问敏感和/或受限用户数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/56946.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot引入MyBatisGenerator

1.引入插件 <plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.5</version><configuration><!--generator配置文件所在位置--><configuratio…

【CSS】3D卡片效果

效果 index.html <!DOCTYPE html> <html><head><title> Document </title><link type"text/css" rel"styleSheet" href"index.css" /></head><body><div class"card"><img…

Spring:IOC技术、Bean、DI

前言 Spring是一个开源的项目&#xff0c;并不是单单的一个技术&#xff0c;发展至今已形成一种开发生态圈。也就是说我们可以完全使用Spring技术完成整个项目的构建、设计与开发。Spring是一个基于IOC和AOP的架构多层j2ee系统的架构。 SpringFramework&#xff1a;Spring框架…

Jenkins Gerrit Trigger实践

1.创建Gerrit Trigger 2.jenkins master节点生成gerrit用户的密钥 这里的用户名得写登录gerrit后个人信息中的 Username 3.gerrit 配置刚刚jenkins生成密钥的公钥 4.gerrit 用户加入群组 不加这个群组&#xff0c;下一步测试就会报错“User aeshare has no capability conn…

TCP连接的状态详解以及故障排查(五)

同时打开 两个应用程序同时执行主动打开的情况是可能的&#xff0c;虽然发生的可能性较低。每一端都发送一个SYN,并传递给对方&#xff0c;且每一端都使用对端所知的端口作为本地端口。例如&#xff1a; 主机a中一应用程序使用7777作为本地端口&#xff0c;并连接到主机b 888…

UG\NX二次开发 属性值连接到表达式

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: 利用表达式参数驱动模型形状实现参数化建模,同时将表达式关联到部件属性中,实现自动更新属性值。这将为建模过程带来更大的灵活性和可扩展性。通过将属性值连接到表达式,可以动态地…

安全测试国家标准解读——函数调用安全、异常处理安全、指针安全

下面的系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解&#xff0c;该标准是2020年4月28日&#xff0c;由国家市场监督管理总局、国家标准化管理委员会发布&#xff0c;2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理&…

Git分布式版本控制工具和GitHub(一)--简介

一.Git概述 1.Git简介 【1】什么是Git? Git就是代码版本管理工具。 【2】为什么要使用Git &#xff08;1&#xff09;版本控制 写代码就是不断写BUG的过程&#xff08;当然我们是不会这么说的&#xff09;&#xff0c;很多时候你写了100行代码之后&#xff0c;突然醒悟&…

安卓音视频多对多级联转发渲染

最近利用自己以前学习和用到的音视频知识和工程技能做了一个android的sdk,实现了本地流媒体ipc rtsp 拉流以及自带mip usb等camera audio节点产生的流媒体通过webrtc sfu的方式进行多对多级联发布共享,网状结构&#xff0c;p2p组网&#xff0c;支持实时渲染以及转推rtmp&#x…

bean作用域和生命周期

Bean 默认情况下是单例状态&#xff08;singleton&#xff09;&#xff0c;也就是所有⼈的使⽤的都是同⼀个对象&#xff0c;之前我们学单例模式的时候都知道&#xff0c;使⽤单例可以很⼤程度上提⾼性能&#xff0c;所以在 Spring 中 Bean 的作⽤域默认也是 singleton 单例模式…

企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图 tbms

&#xfeff; 项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&am…

批量计算直角三角形两个直角边对应斜边的numpy.hypot()方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 给出多个三角形的两条直角边长度 批量计算出这些三角形的斜边长度 numpy.hypot() [太阳]选择题 以下代码的输出结果是? import numpy as np a np.array([3, 4, 30]) b np.array([4, 3, 40])…

HDFS中数据迁移的使用场景和考量因素

HDFS中数据迁移的使用场景和考量因素 数据迁移使用场景数据迁移要素考量HDFS分布式拷贝工具-DistCpdistcp的优势性能命令 数据迁移使用场景 冷热集群数据同步、分类存储集群数据整体搬迁 当公司业务迅速的发展&#xff0c;导致的当前的服务器数量资源出现临时紧张的时候&#…

解密外接显卡:笔记本能否接外置显卡?如何连接外接显卡?

伴随着电脑游戏和图形处理的需求不断增加&#xff0c;很多笔记本电脑使用者开始考虑是否能够通过外接显卡来提升性能。然而&#xff0c;外接显卡对于笔记本电脑是否可行&#xff0c;以及如何连接外接显卡&#xff0c;对于很多人来说仍然是一个迷。本文将为您揭秘外接显卡的奥秘…

二重积分1

目录 二重积分 二重积分的性质 ​编辑 中值定理 二重积分的计算 方法1&#xff1a;利用直角坐标计算 方法2&#xff1a;利用极坐标进行计算 适用于极坐标的二重积分的特征 对称性和奇偶性的应用 题目 例题1&#xff1a; 题目2&#xff1a; 题目3&#xff1a; 题目4&#x…

0基础学习VR全景平台篇 第76篇:全景相机-圆周率全景相机如何直播推流

圆周率科技&#xff0c;成立于2012年&#xff0c;是中国最早投身嵌入式全景算法研发的团队之一&#xff0c;亦是全球市场占有率最大的全景算法供应商。相继推出一体化智能屏、支持一键高清全景直播的智慧全景相机--Pilot Era和Pilot One&#xff0c;为用户带来实时畅享8K的高清…

在Volo.Abp微服务中使用SignalR

假设需要通过SignalR发送消息通知&#xff0c;并在前端接收消息通知的功能 创建SignalR服务 在项目中引用 abp add-package Volo.Abp.AspNetCore.SignalR在Module文件中添加对模块依赖 [DependsOn(...typeof(AbpAspNetCoreSignalRModule))] public class IdentityApplicati…

【Spring】学习Spring需要掌握的核心设计思想

目录 一、Spring是什么 二、什么是IoC容器 1、什么是容器 2、什么是IoC 3、Spring IoC 4、DI&#xff08;依赖注入&#xff09; 4.1、IoC和DI的区别 5、 DL&#xff08;依赖查找&#xff09; 一、Spring是什么 我们通常所说的Spring指的是Spring Framework&#xff08;…

Vue3徽标数(Badge)

APIs 参数说明类型默认值必传color自定义小圆点的颜色string‘’falsecount展示的数字&#xff0c;大于 overflowCount 时显示为 overflowCount&#xff0c;为 0 时隐藏number | slot0falseoverflowCount展示封顶的数字值number99falseshowZero当数值为 0 时&#xff0c;是否展…

Django实现音乐网站 ⑵

使用Python Django框架制作一个音乐网站&#xff0c;在系列文章1的基础上继续开发&#xff0c;本篇主要是后台歌手表模块开发。 目录 表结构设计 歌手表&#xff08;singer&#xff09;结构 创建表模型 设置图片上传路径 创建上传文件目录 生成表迁移 执行创建表 后台管…