iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0
生成式 AI

打造基於 MCP 協議與 n8n 工作流的會議處理 Agent系列 第 20

Day 20 郵件優化 — 加入直達按鈕與強化迴圈穩定性

  • 分享至 

  • xImage
  •  

昨天我的 M2A Agent 已經成功寄送了任務通知信,但我還希望可以再做一點進化,因此今天的目標就是為通知郵件加入一個直達 Notion 的按鈕,讓夥伴能一鍵查看任務;同時,我也會強化 n8n 的工作流程,確保單一的寄信失敗不會導致整個自動化流程崩潰。

今天的目標與挑戰

  • 在郵件中加入一個前往 Notion 的按鈕。
  • 設定 n8n 的 Gmail 節點,使其在寄信失敗時不會中斷整個流程。
  • 驗證優化後的工作流程,確保功能正常。

Step 1:強化迴圈穩定性

雖然這個步驟是今天最簡單的設定,但也是最重要的一個步驟,因為目前的迴圈機制,就像是一串串起來的鞭炮,只要中間有一顆受潮點不著(像是只要 Email 發生問題),後面的所有鞭炮就都停止了,我要做的,就是讓它們變成獨立的煙火,一顆失敗,不影響下一顆的綻放。

  1. 在 n8n 工作流中,點擊迴圈內的「Gmail」節點,打開設定面板。
  2. 切換到右上方的「Settings」分頁。
  3. 在設定列表中,找到 On Error 這個欄位,並選擇「Continue」。
  4. 完成後關閉設定面板即可。
    Send a message Settings

這個小小的設定,賦予了我們工作流程極大的韌性。現在即使迴圈中有一個人的 Email 無效導致寄信失敗,n8n 也會記錄下這個錯誤,然後繼續處理下一個人的郵件,確保多數人能順利收到通知。


Step 2:加入「查看會議紀錄」按鈕

光有任務列表還不夠,最貼心的助理,會直接幫你把門打開。我們要在郵件的結尾,加上一個醒目的按鈕,讓收到信的夥伴能直接點擊,跳轉到 Notion 的任務看板頁面。

  1. 在 n8n 工作流中,找到並點開「產生郵件 HTML」這個 Code 節點。
  2. 在程式碼編輯區中的 htmlContent 中,加入按鈕的 HTML 語法
const assigneeInfo = $input.item.json;
const meetingInfo = $('提取結構化任務').first().json.meeting_info;
const meetingAttributes = $('提取結構化任務').first().json.meeting_attributes;

const assigneeName = assigneeInfo.name || '夥伴';
const projectName = meetingInfo.project_name || '未指定專案';
const taskCount = assigneeInfo.tasks.length;
const summary = meetingAttributes.summary || '暫無摘要';
const deadlineDate = meetingInfo.deadline_date || '未設定';

let tasksHtml = '';
for (let i = 0; i < assigneeInfo.tasks.length; i++) {
  const task = assigneeInfo.tasks[i];
  const taskNum = i + 1;
  const title = task.title || '未命名任務';
  const desc = task.description || '';
  const timeExpr = task.time_expression || '';
  const priority = task.priority || '';

  const priBg = priority === '高' ? '#e74c3c' : '#f39c12';
  const priBadge = priority ?
    `<span style="background-color: ${priBg}; color: white; font-size: 11px; padding: 3px 8px; border-radius: 10px; margin-left: 5px;">${priority}優先</span>` :
    '';

  tasksHtml += `
    <div style="background-color: #fff; border: 2px solid #e3e8ef; border-left: 5px solid #667eea; padding: 18px; margin-bottom: 15px; border-radius: 6px;">
      <div style="margin-bottom: 10px;">
        <span style="background-color: #667eea; color: white; font-size: 12px; font-weight: bold; padding: 4px 10px; border-radius: 12px;">任務 ${taskNum}</span>
        ${priBadge}
      </div>
      <h4 style="margin: 0 0 12px 0; color: #2c3e50; font-size: 16px; font-weight: bold;">${title}</h4>
      <p style="margin: 8px 0; color: #666; font-size: 13px;">${desc}</p>
      <p style="margin: 12px 0 0 0; color: #555; font-size: 14px;">
        <strong>📅 預計完成期限:</strong> 
        <span style="color: #e74c3c; font-weight: bold;">${deadlineDate}</span>`;
  if (timeExpr) {
    tasksHtml += ` <span style="color: #999; font-size: 13px;">(${timeExpr})</span>`;
  }
  tasksHtml += `
      </p>
    </div>`;
}

// link 替換為要導至的網址
const notionProjectUrl = '<link>';

const htmlContent = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>
<body style="margin: 0; padding: 0; background-color: #f4f4f4; font-family: Arial, sans-serif;">
  <div style="max-width: 600px; margin: 20px auto; background-color: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.15);">
    
    <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 20px; text-align: center;">
      <h1 style="margin: 0; font-size: 24px; font-weight: bold;">M2A Agent 任務指派通知</h1>
      <p style="margin: 10px 0 0 0; font-size: 14px; opacity: 0.9;">您有新的任務等待處理</p>
    </div>

    <div style="padding: 30px 25px;">
      <p style="font-size: 16px; color: #333; margin: 0 0 20px 0;">Hi <strong>${assigneeName}</strong>,</p>
      
      <div style="background-color: #f8f9fa; border-left: 4px solid #667eea; padding: 15px; margin-bottom: 25px; border-radius: 4px;">
        <p style="margin: 0; color: #555; font-size: 14px;">在剛剛的「<strong style="color: #667eea;">${projectName}</strong>」會議中,您被指派了 <strong style="color: #e74c3c;">${taskCount}</strong> 項新任務,請查收:</p>
      </div>
      
      <div style="margin-bottom: 30px;">
        ${tasksHtml}
      </div>
      
      <div style="text-align: center; margin-bottom: 30px;">
        <a href="${notionProjectUrl}" target="_blank" style="background-color: #5a67d8; color: white; padding: 12px 25px; text-decoration: none; border-radius: 8px; font-weight: bold; font-size: 14px; display: inline-block;">
          前往 Notion 查看會議記錄
        </a>
      </div>
      
      <hr style="border: 0; border-top: 1px solid #e0e0e0; margin: 30px 0;">
      
      <div>
        <h3 style="color: #667eea; font-size: 18px; margin: 0 0 15px 0; border-bottom: 2px solid #667eea; padding-bottom: 8px;">相關會議摘要</h3>
        <div style="background-color: #f9f9f9; padding: 15px; border-radius: 6px; border: 1px solid #e8e8e8;">
          <p style="margin: 0; color: #555; font-size: 14px; line-height: 1.6;">${summary}</p>
        </div>
      </div>
    </div>

    <div style="background-color: #f8f9fa; text-align: center; padding: 20px; border-top: 1px solid #e0e0e0;">
      <p style="margin: 0; font-size: 12px; color: #999;">這是一封由 M2A Agent 自動發送的通知郵件</p>
      <p style="margin: 8px 0 0 0; font-size: 11px; color: #bbb;">請勿直接回覆此郵件</p>
    </div>

  </div>
</body>
</html>`;

return {
  email: assigneeInfo.email,
  name: assigneeName,
  projectName: projectName,
  taskCount: taskCount,
  htmlContent: htmlContent
};

Step 3:測試與驗證

修改完成後,進行端到端的測試,確保一切正常運作。

  1. 在 Gradio 前端頁面上船音訊,並輸入指令。
  2. 等待執行完畢後,前往測試信箱收信。
  3. 檢查結果
    打開新的任務通知信,在任務列表下方,出現了一個藍色的「前往 Notion 查看會議記錄」按鈕,點擊按鈕,確認瀏覽器開啟新分頁,並成功帶到指定的 Notion 頁面。
    Gmail

看著信中出現了這個好用的按鈕,代表我們今天的任務順利完成了!


今天的成果總結

完成項目

  • 成功在任務通知信中加入一個美觀且實用的按鈕,大幅提升使用者體驗
  • 透過在On Error 這個欄位,並選擇「Continue」,強化了自動化流程的穩定性與可靠性
  • 完成了從「功能實作」到「細節強化」的開發

心得

今天的工作證明了,有時候最有價值的更新,並不一定是那些驚天動地的大功能,而是在細節處的打磨。

一個小小的按鈕,讓整個使用者體驗又提升了;一個簡單選項,讓系統的可靠性也提升了一個檔次,這正是打造一個成熟作品的必經之路。

🎯 明天計劃

全面強化 Gradio 介面,加入歷史會議列表與進度條,讓使用者能追溯紀錄並掌握即時處理狀態。


上一篇
Day 19 整合 Gmail — 自動化任務指派通知
系列文
打造基於 MCP 協議與 n8n 工作流的會議處理 Agent20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言