本地Azure DevOps服务器Outlook Webhook图标显示异常求助
解决本地Azure DevOps Server到Outlook Group Webhook的图片显示问题
为啥图标会显示成文本?
Outlook Group的Incoming Webhook对Markdown的支持有局限性——它不会解析sections.text字段里的图片语法,只会把这段代码当成纯文本显示。而本地Azure DevOps Server默认的通知模板,刚好把仓库和分支图标放在了这个text字段里,就导致图标没法正常渲染成图片。
解决方案1:直接修改DevOps通知模板(最省心)
本地DevOps Server允许自定义通知模板,咱们直接调整模板结构,把图片移到Outlook支持的字段里就行:
- 登录你的本地DevOps Server,进入项目的「设置」→「通知」,找到你配置的Outlook Webhook通知。
- 点击编辑通知,切换到自定义JSON模式。
- 调整
sections部分的内容:- 把原
text字段里的和删掉,放到images数组里。 - 把
text字段改成纯文本(保留分支和仓库的链接就行)。
- 把原
给你个修改后的JSON片段参考:
"sections": [{ "title": null, "markdown": true, "images": [ { "image": "https://cdn.vsassets.io/content/notifications/teams-pushrepo.png", "title": "Repo Icon" }, { "image": "https://cdn.vsassets.io/content/notifications/teams-branch.png", "title": "Branch Icon" } ], "activityTitle": "[CustomerAddressModule / 20150407.2](https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/71777fbc-1cf2-4bd1-9540-128c1c71f766/_apis/build/Builds/1) (Succeeded)", "activitySubtitle": "Trigger: batchedCI for [Jamal Hartnett](mailto:Jamal.Hartnett@Fabrikamcloud.com)", "text": "Build for [JamalHartnettUserBranch](https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/_git/71777fbc-1cf2-4bd1-9540-128c1c71f766) [master](https://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/_git/71777fbc-1cf2-4bd1-9540-128c1c71f766/#version=GBmaster), finished 04/07/2015 17:24:20 UTC", "activityImage": "https://cdn.vsassets.io/content/notifications/teams-build-succeeded.png", "activityImageType": "article" }]
这样改完,Outlook Group会正确渲染images数组里的图片,其他内容也能正常显示。
解决方案2:加个中间层转换请求(适合改不了模板的情况)
如果因为权限或其他原因没法修改DevOps的模板,那就搭个简单的中间服务,把DevOps发过来的JSON转成Outlook支持的格式再转发:
- 用Node.js、Python或者ASP.NET写个轻量API,监听DevOps的Webhook请求。
- 解析原JSON,把
text字段里的图片链接提取出来,移到sections.images数组,同时清理text里的图片语法。 - 把转换后的JSON转发到Outlook的Webhook地址。
给你一段Python的示例代码(用Flask框架):
from flask import Flask, request, jsonify import requests import re app = Flask(__name__) # 替换成你的Outlook Webhook地址 OUTLOOK_WEBHOOK_URI = "https://outlook.office.com/webhook/<obfuscated>/IncomingWebhook/<obfuscated>/<obfuscated>" @app.route('/devops-proxy', methods=['POST']) def proxy_webhook(): original_payload = request.get_json() if not original_payload or 'sections' not in original_payload: return jsonify({"error": "Invalid payload"}), 400 section = original_payload['sections'][0] # 提取text中的Markdown图片 image_matches = re.findall(r'!\[(.*?)\]\((.*?)\)', section.get('text', '')) # 清理text字段里的图片语法 section['text'] = re.sub(r'!\[(.*?)\]\((.*?)\)', '', section.get('text', '')).strip() # 添加图片到images数组 section['images'] = [{"image": img_url, "title": img_alt} for img_alt, img_url in image_matches] # 转发到Outlook Webhook response = requests.post(OUTLOOK_WEBHOOK_URI, json=original_payload) return jsonify({"status": response.status_code, "message": "Forwarded successfully"}), response.status_code if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
写完后把DevOps的Webhook目标地址改成这个中间服务的地址(比如http://your-server-ip:5000/devops-proxy)就行。
怎么验证?
触发一次构建,去Outlook Group里看通知:
- 仓库和分支图标应该显示成正常的图片,不是
!Repo Icon....这种文本。 - 构建链接、触发人这些信息也得完整显示。
内容的提问来源于stack exchange,提问作者Sk93
相关产品推荐
相关产品推荐

