在 n8n 2.3.0(自託管)中,透過 SMTP 節點無法傳送電子郵件附件

描述問題/錯誤/問題

嗨,
我試圖在我的自主託管 n8n 2.3.0 設置中從 IMAP 觸發器發送帶附件的電子郵件到 SMTP 節點。
設置:

  • 啟用了「簡單」格式的電子郵件觸發器 (IMAP)
  • N8N_DEFAULT_BINARY_DATA_MODE=default
  • 發送電子郵件節點 (SMTP) 搭配 Plesk 郵件伺服器
    問題所在:
    電子郵件成功發送但附件未包含。當我除錯時,我看到附件存在為二進位資料,但它們沒有出現在接收的電子郵件中。
    我已嘗試:
    :white_check_mark: 將 N8N_DEFAULT_BINARY_DATA_MODE 更改為「memory」和「default」
    :white_check_mark: 用 docker compose down -v 重新啟動
    :white_check_mark: 使用「從檔案提取」節點轉換為 Base64
    :white_check_mark: 將二進位屬性設定為「attachment_0,attachment_1,attachment_2」
    以上都沒有奏效。電子郵件到達但附件總是遺失。
    問題:
  1. 這是 2.3.0 中 SMTP + 二進位資料的已知錯誤嗎?
  2. 除了使用 Gmail API 之外還有其他解決方法嗎?
  3. 我應該降級到 n8n 1.x 嗎?
    任何幫助都將不勝感激!

錯誤訊息是什麼(如果有的話)?

請分享您的工作流程

分享最後一個節點返回的輸出

關於您的 n8n 設置的資訊

  • n8n 版本:2.3.0
  • 資料庫(預設:SQLite):postgres
  • n8n EXECUTIONS_PROCESS 設定(預設:own, main):
  • 運行 n8n 方式(Docker、npm、n8n cloud、桌面應用程式):docker
  • 作業系統:ubuntu

你能否貼上 SMTP 節點的「附件」部分的設定截圖?「Binary Property」欄位需要與屬性名稱完全匹配,以逗號分隔,不含空格。像是 attachment_0,attachment_1 這樣就可以,但如果逗號後面有空格就可能會無聲地中斷。

那個二進制数據模式設定對我來說最突出。當它設置為「default」時,它會將附件保存到磁盤,然後在需要發送電子郵件時再次獲取它。如果你的設置中任何地方涉及多個容器,SMTP節點可能就無法在附加文件時找到該文件,它不會拋出錯誤,而是會靜靜地跳過它。這正好符合你看到的情況。另外,你運行的 docker compose down -v 中的 -v 會擦除卷。如果你的二進制存儲位於其中一個卷中,那個命令可能就在那裡刪除了它。

嗨,感謝您的幫助

Hi @Anthony_P 歡迎!
沒有二進制數據到達 Send email。formatInfoMail 返回一個普通的 json 對象,沒有 binary 鍵,而 Message a model 在它之後再次替換該項目,所以你的 Attachments 表達式命名的屬性在節點運行時已不再存在於該項目上。
在 si humain 和 Send email 之間用代碼節點放回二進制數據:

return [{
  json: $input.first().json,
  binary: $('Email Trigger (IMAP)').first().binary,
}];

然後將 Attachments 設置為 {{ Object.keys($binary).join(',') }}。

降級無法解決此問題,直接指向另一個節點的二進制是一個未解決的問題,最後在 1.115.3 版本報告過:

將 join 改為不添加空格

{{ Object.keys($('Email Trigger (IMAP)').item.binary).join(',') }}

感謝您的解釋!但我需要澄清一點:當我在電子郵件正文中新增此除錯:{{ JSON.stringify($(‘Email Trigger (IMAP)’).item.binary, null, 2) }} 時,我可以看到附件的完整 Base64 內容。這證明二進位資料仍然存在,並且可從「電子郵件觸發器」節點存取。如果二進位資料真的像您提到的那樣遺失,我在除錯輸出中就不會看到任何內容。但我看到了完整的檔案資料(Base64 編碼)。所以問題不是二進位資料消失——它們顯然在那裡。問題似乎是「傳送電子郵件」節點的「二進位屬性」欄位無法直接從「電子郵件觸發器」節點存取它們。

我已經多次測試過了 - 既試過完整的節點路徑表達式,也試過直接放入 attachment_0、attachment_1 - 但都沒有用。奇怪的是:當我通過在郵件正文中添加 {{ JSON.stringify($(‘Email Trigger (IMAP)’).item.binary, null, 2) }} 來調試時,我可以看到二進制對象的完整內容及所有 Base64 數據。這證明附件確實存在且可以訪問。但「發送郵件」節點就是不會附加它們。

我們已經查看過此問題,看起來可能已在最近的版本中修復。請更新並查看您是否仍然遇到同樣的問題。

該除錯輸出是一個表達式,直接讀取 IMAP 節點的資料,可從工作流程中的任何位置運作,不會在項目上放置任何內容。Attachments 不是擷取資料的表達式,而是節點在其自己的輸入項目上查詢的屬性名稱清單,你的螢幕截圖預覽它解析為正確的三個名稱。該節點然後在 si humain 交付的項目上查詢 attachment_0,找不到任何內容,並在沒有它的情況下發送。
你的兩個測試都改變了該字串。在某些東西將二進位檔案放到項目上之前,該欄位中的任何值都無法運作,這正是 Code 節點所做的。升級也不會改變這一點。

感謝,這個有用。不過,我還是不太明白為什麼在寄送電子郵件之前必須重新建立物件。
這幾乎肯定是因為,在我擷取附件的時刻與電子郵件送出的時刻之間,存在中間區塊——而來自第一個區塊的二進位資料不會自動從一個區塊傳遞到下一個區塊。在我看過的線上教學中,附件都是在前一個區塊中定義的。

二進制文件不會被繼承,每個節點都會構建自己的輸出項目,並決定是否將其沿用。formatInfoMail 返回一個普通對象,所以二進制文件在觸發後的一個節點處就消失了,而 Message a model 構建了自己的全新項目。兩個 IF 節點直接傳遞該項目,所以中間的節點數量從來都不是問題所在。
這也是為什麼教程不需要重新構建,附件位於「發送電郵」之前的節點的輸出上。能夠重塑數據並保留數據的節點會在其選項中暴露這個選擇,「編輯欄位」和「分割輸出」都有一個設置來決定二進制文件是否進入其輸出。