You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 `![${altText}](${baseUrl}${url})`;
      });

      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);
    }
    
  }
});

解决方案

核心修改思路

  1. 直接使用YouTrack内置的解析后HTML:评论对象的htmlText属性已经完成Wiki/Markdown到HTML的转换,无需手动处理标记语法
  2. 修正图片绝对路径:将HTML中图片的相对路径替换为YouTrack实例的完整URL,确保邮件客户端能加载图片
  3. 追加附件下载链接:遍历评论附件,为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:14:59