利用飞书集成平台达成 Outlook 邮件实时飞书消息提醒 - 飞书官网
解决方案

利用飞书集成平台达成Outlook邮件实时飞书消息提醒

飞书

2024-12-23

推荐理由​
原始诉求​
解决思路​
实现路径​
总结回顾​
作者:Junxian DIAO 刁俊先​
推荐理由​
我们团队重度使用飞书,但是很多重要的消息提醒仍然依赖公司邮箱系统,能否做到把 Outlook 邮件在制定好规则后实时转发到飞书消息?​
​
原始诉求​
1.团队重度使用飞书,但是很多重要的消息提醒仍然依赖公司邮箱系统,能否做到把Outlook 邮件在制定好规则后实时转发到飞书消息?​
2.需要具备实时性,如果实时性无法达成,可接受每天定时转发亦可。​
​
解决思路​
通过飞书捷径​
​
2.但是目前飞书捷径已经去除了 Outlook 的连接器;​
​
250px|700px|reset
​
​
通过 Microsoft Graph API 提取邮件​
思路是通过 Microsoft Graph API 提取并识别最新邮件,找到符合规则的邮件,然后通过飞书消息实现转发;​
​
实现路径​
手动实践过程​
第一步:创建 Azure Active Directory 应用​
注册成功后,在应用概述页面可以看到client id和tenant id​
​
250px|700px|reset
​
​
第二步:创建证书和密码​
第三步:添加阅读邮件的委托权限​
这里特别注意添加的应用委托权限,而不是应用程序权限,是因为应用程序权限是对工作账户内所有账号都有权限的,可能会有安全隐私等问题。使用 oauth 获取的 access_token 可以仅对登陆的账号有效,应用注册时也无需单独配置权限。​
​
250px|700px|reset
​
​
第四步:添加重定向地址,方便提取 access token 和 refresh token​
第五步:本地登录,提取 access token 和 refresh token​
​
​
from authlib.integrations.flask_client import OAuth​
from flask import Flask, url_for, request​
import urllib​
import json​
​
tenant_id = 'xxxx'​
client_id = 'xxxxx'​
client_secret = 'xxxxx'​
​
app = Flask(__name__)​
​
app.secret_key = 'xxxxx'​
app.config['SESSION_TYPE'] = 'filesystem'​
​
oauth = OAuth(app)​
​
oauth.register(​
name='azure',​
client_id=client_id,​
client_secret=client_secret,​
access_token_url=f'https://login.chinacloudapi.cn/{tenant_id}/oauth2/v2.0/token',​
authorize_url=f'https://login.chinacloudapi.cn/{tenant_id}/oauth2/v2.0/authorize',​
# client_kwargs={​
# 'scope': 'offline_access https://microsoftgraph.chinacloudapi.cn/Mail.Read'},​
client_kwargs={​
'scope': 'offline_access https://microsoftgraph.chinacloudapi.cn/Channel.ReadBasic.All https://microsoftgraph.chinacloudapi.cn/Mail.Read https://microsoftgraph.chinacloudapi.cn/Mail.ReadBasic https://microsoftgraph.chinacloudapi.cn/Mail.ReadWrite'},​
)​
​
​
@app.route('/')​
def login():​
redirect_uri = url_for('authorize', _external=True)​
​
return oauth.azure.authorize_redirect(redirect_uri)​
​
​
@app.route('/login/authorized')​
def authorize():​
token = oauth.azure.authorize_access_token()​
print(token)​
with open("token.json", "w", encoding="utf8") as f:​
f.write(json.dumps(token)) # token 保存到了 token.json 文件中​
​
return token​
​
# https://learn.microsoft.com/en-us/graph/webhooks?tabs=http#notification-endpoint-validation​
@app.route("/notify", methods=['POST'])​
def onedrive():​
valtoken = request.args.get('validationToken')​
​
resp = app.response_class(response=urllib.parse.unquote(valtoken), status=200, mimetype='plain/text')​
return resp​
​
app.run(host='localhost', port=5000, debug=True)​
1.服务启动后,本地访问,会提示验证登录动作;​
2.这里特别注意的是,国外的 Microsoft Graph API 访问的域名和国内是不一致的(21Vianet 运营的 Office 365 API 端点),会出现 github 上很多正确的示例代码,怎么尝试都是错误的。​
3.这里的过程只会使用一次,提取一次 refresh token 以后,后续,通过 refresh token 反复刷新 token 即可;​
第六步:飞书集成平台创建集成流,监听创建订阅后的消息事件​
2.创建订阅​
​
​
url = "https://microsoftgraph.chinacloudapi.cn/v1.0/subscriptions"​
headers={​
'Authorization': 'Bearer %s' % access_token,​
'Content-type': 'application/json'​
}​
​
data = {​
"changeType": "created",​
"notificationUrl": "https://open.feishu.cn/anycross/xxxx",​
"resource": "me/mailFolders('Inbox')/messages",​
"expirationDateTime":"2023-01-18T18:23:45.9356913Z",​
}​
​
resp = requests.post(url, headers=headers, json=data)​
​
print(resp.status_code, resp.json())​
3.这里的 notificationUrl 是飞书集成平台集成流中对应的监听地址,这里需要将 Microsoft 的请求事件中的 query 部分完整返回(设置资源数据更改的通知)。且需要注意的是,要确保 notificationUrl 有效:​
A status code ofHTTP 200 OK.​
A content type oftext/plain.​
A body that includes the URL decoded validation token. Simply reflect back the same string that was sent in thevalidationTokenquery parameter.​
第七步:接收到 Microsoft Graph API 事件,请求提取完整的邮件信息​
​
250px|700px|reset
​
​
根据 resource 字段值,拼接完整的请求路径,提取完整的邮件体;​
​
​
url = 'https://microsoftgraph.chinacloudapi.cn/v1.0/{resource}'​
​
response = requests.get(url, headers={​
'Authorization': 'Bearer %s' % access_token​
})​
​
print(response.json())​
​
第八步:制定转发规则,将需要提醒的邮件转发到对应的群组或者个人​
飞书集成平台集成流完整闭环​
​
250px|700px|reset
​
​
1.JOSN助手:先将发过来的 webhook 消息体反序列化;​
2.同步回调:立即返回 http status code 200;​
这里主要的原因是,需要应处理收到的每个更改通知。 应用程序必须至少执行以下任务来处理更改通知(设置资源数据更改的通知)​
你的进程应处理它收到的每个更改通知并发送 2xx 类代码。 如果Microsoft Graph在 3 秒内未收到 2xx 类代码,它将尝试在大约 4 小时的时间内多次发布更改通知;之后,更改通知将被删除,并且不会送达。 如果进程在 3 秒内一致未响应,则通知可能会受到限制。​
如果处理预计需要 3 秒以上,则应保留通知,在响应Microsoft Graph时返回202 - Accepted状态代码,然后处理通知。 如果通知未保留,则返回 5xx 类代码以指示错误,以便重试通知。​
如果处理预计花费不到 3 秒,则应处理通知,并在响应Microsoft Graph时返回200 - OK状态代码。 如果通知未正确处理,则返回 5xx 类代码以指示错误,以便重试通知。​
验证clientState属性。 它必须与最初使用订阅创建请求提交的值匹配。​
3.数据源:提取已经存储的 refresh token;​
4.Http client 连接器:根据 refresh token 换取 access token;​
5.动态脚本:根据得到的 access token 和webhook 消息体重的 resource 字段,拼接请求参数;​
​
​
function handler(input) {​
var url_path = input.url_path;​
var token = input.token;​
​
var url = `https://microsoftgraph.chinacloudapi.cn/v1.0/${url_path}`;​
var access_token = `Bearer ${token}`;​
return {​
url: url,​
access_token: access_token,​
};​
}​
6.Http client 连接器:根据参数,发起 Get 请求,得到完整邮件内容;​
7.动态脚本:根据返回值,提取需要的邮件消息体重要字段内容,拼接消息卡片消息体,需要注意的是,其中关于邮件正文的内容,直接根据 js 提取的除去 html string 格式化的内容;​
​
​
var html_content = response.body.content;​
var content = html_content​
.replace(/<[^<>]+>/g, '')​
.replace(/&nbsp;/gi, '')​
.replace(/&gt;/gi, '')​
.replace(/(^\s*)|(\s*$)/g, '');​
8.自定义飞书机器人:根据消息体发出邮件转发的卡片消息。​
​
总结回顾​
1.Microsoft 已经提供了非常完备的消息订阅流程,只要我们想,所有该有的事件都可以实时提取;​
2.创建事件订阅后,需要及时的延长订阅事件的有效期,这里也是 Microsoft 版本更新后可能会让开发者误踩的坑之一;​
3.先用 Python requests 请求将整个链路走通后,在飞书集成平台完整的实现,主要原因是,飞书集成平台的使用体验依然很稳定,我们不需要单独部署服务来实现过程的集成,一方面可以降低我们服务运维的成本,另一方面也是为了方便后续将此类工作解耦,交付其他团队使用;​
4.后续,准备探索将整体 Outlook 邮件转发过程打包成连接器,开源给其他飞书集成平台同学使用;​
预约飞书企业效能顾问 深度诊断企业痛点,定制专属 AI 办公方案

先进团队,先用飞书

欢迎联系我们,飞书效能顾问将为您提供全力支持
分享先进工作方式
输送行业最佳实践
全面协助组织提效
标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题

字节跳动旗下 AI 工作平台

联系我们立即试用