YouTrack工单邮件评论附件(图片/ZIP)显示异常求助
问题描述
我们在YouTrack Helpdesk中开发了一款工单评论邮件通知工作流,其余功能正常,但邮件里的图片、ZIP等附件仅显示Markdown标记语法,无法正确渲染。需要将评论的Wiki标记解析为带内联图片和附件链接的HTML,实现内容正常显示。
原工作流代码如下:
var entities = require('@jetbrains/youtrack-scripting-api/entities'); var notification = require('@jetbrains/youtrack-scripting-api/notifications'); const resolveLinks = function (text) { var baseUrl = 'https://test.com/images/'; var updatedText = text.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, function(match, altText, url) { // Check if the URL is already absolute if (url.startsWith('http://') || url.startsWith('https://')) { return match; } // Replace with absolute URL return ``; }); if (text !== updatedText) { text = updatedText; } return text; }; exports.rule = entities.Issue.onChange({ title: 'Send Email Notification', guard: function(ctx) { return true; }, action: function(ctx) { var issue = ctx.issue; if (issue.comments.added.isNotEmpty()) { var authorName = issue.comments.added.first().author.fullName; var emailReporter = issue.reporter.email; var emailWorker = issue.fields.Bearbeiter.email; var emailObserver = ""; issue.fields.Beobachten.forEach(function(user) { emailObserver = emailObserver + user.email + ","; }); if(emailObserver.endsWith(",")) { emailObserver = emailObserver.substring(0,emailObserver.length-1); } var message = { fromName: authorName, to: [emailReporter], cc: [emailWorker], bcc: [emailObserver], subject: 'New comment in ' + issue.id, headers: { 'X-Custom-Header': 'Important value' }, body: [ '<div style="font-family: sans-serif">', ' <div style="padding: 10px 10px; font-size: 13px; border-bottom: 1px solid #D4D5D6;">', ' New comment was added in issue <a href=https://service-desk.dhge.de/tickets/'+issue.id+'>'+issue.id+'</a> by ' + authorName + ': ', ' <br> <br>' + resolveLinks (issue.comments.last().text) , ' </div>', '<\div>' ].join('\n') }; console.log("Send mail from "+authorName+" to: "+emailReporter); console.log("Send mail from "+authorName+" to: "+emailWorker); console.log("Send mail from "+authorName+" to: "+emailObserver); console.log("Send mail text "+issue.comments.last().text); notification.sendEmail(message, issue); } } });
解决方案
核心修改思路
- 直接使用YouTrack内置的解析后HTML:评论对象的
htmlText属性已经完成Wiki/Markdown到HTML的转换,无需手动处理标记语法 - 修正图片绝对路径:将HTML中图片的相对路径替换为YouTrack实例的完整URL,确保邮件客户端能加载图片
- 追加附件下载链接:遍历评论附件,为ZIP等非图片附件生成可点击的下载链接
修改后的完整代码
var entities = require('@jetbrains/youtrack-scripting-api/entities'); var notification = require('@jetbrains/youtrack-scripting-api/notifications'); // 处理HTML中的图片相对路径,转为YouTrack绝对URL const resolveImageUrls = function(htmlText, youTrackBaseUrl) { return htmlText.replace(/<img[^>]+src="([^"]+)"[^>]*>/g, function(match, src) { if (src.startsWith('http://') || src.startsWith('https://')) { return match; } return match.replace(src, `${youTrackBaseUrl}${src}`); }); }; // 生成附件下载链接的HTML片段 const generateAttachmentLinks = function(attachments, youTrackBaseUrl) { if (attachments.isEmpty()) { return ''; } let linksHtml = '<br><br><h4>附件:</h4><ul>'; attachments.forEach(attachment => { const downloadUrl = `${youTrackBaseUrl}${attachment.url}`; linksHtml += `<li><a href="${downloadUrl}" target="_blank">${attachment.name}</a> (${attachment.sizeFormatted})</li>`; }); linksHtml += '</ul>'; return linksHtml; }; exports.rule = entities.Issue.onChange({ title: 'Send Email Notification', guard: function(ctx) { return true; }, action: function(ctx) { var issue = ctx.issue; if (issue.comments.added.isNotEmpty()) { const addedComment = issue.comments.added.first(); var authorName = addedComment.author.fullName; var emailReporter = issue.reporter.email; var emailWorker = issue.fields.Bearbeiter?.email || ''; var emailObserver = issue.fields.Beobachten.map(user => user.email).join(','); // 替换为你的YouTrack实例基础URL const youTrackBaseUrl = 'https://service-desk.dhge.de'; // 获取解析后的评论HTML并修正图片路径 var commentHtml = resolveImageUrls(addedComment.htmlText, youTrackBaseUrl); // 生成附件链接HTML var attachmentsHtml = generateAttachmentLinks(addedComment.attachments, youTrackBaseUrl); var message = { fromName: authorName, to: emailReporter ? [emailReporter] : [], cc: emailWorker ? [emailWorker] : [], bcc: emailObserver ? [emailObserver] : [], subject: `New comment in ${issue.id}`, headers: { 'X-Custom-Header': 'Important value' }, body: [ '<div style="font-family: sans-serif">', ' <div style="padding: 10px 10px; font-size: 13px; border-bottom: 1px solid #D4D5D6;">', ` New comment was added in issue <a href="${youTrackBaseUrl}/tickets/${issue.id}">${issue.id}</a> by ${authorName}:`, ' <br><br>' + commentHtml, attachmentsHtml, ' </div>', '</div>' ].join('\n') }; console.log(`Send mail from ${authorName} to: ${emailReporter}`); console.log(`Send mail from ${authorName} to: ${emailWorker}`); console.log(`Send mail from ${authorName} to: ${emailObserver}`); notification.sendEmail(message, issue); } } });
代码说明
resolveImageUrls:匹配HTML中的<img>标签,将相对路径的src替换为YouTrack实例的绝对URL,解决图片无法加载的问题generateAttachmentLinks:遍历评论附件,生成包含文件名、大小和下载链接的列表,让ZIP等附件可以直接点击下载addedComment.htmlText:直接使用YouTrack已解析完成的HTML内容,彻底避免Markdown标记显示的问题- 优化收件人处理:用
map+join简化观察者邮箱拼接,添加空值判断避免无效收件人报错
内容的提问来源于stack exchange,提问作者Matthias Jakob
相关产品推荐
相关产品推荐

