n8nメール承認フローを実装して詰まった5つのエラーと解決策【実体験デバッグ記録】

テック・IT

n8nで「記事を自動生成→WordPress下書き保存→承認メール送信→承認したら自動公開」というフローを実装したとき、メール送信まわりで想定外のエラーが連発しました。同じ構成を試みる方のデバッグ参考になるよう、エラーから解決までを時系列で記録します。

実装した構成

  • n8n(セルフホスト版 v2.22.4)
  • WordPress REST API(WP 7.0)
  • Gmail SMTP(アプリパスワード認証)
  • n8n emailSendノード(typeVersion 2)
n8nメール承認フロー全体像
n8n メール承認フロー 全体像(① キーワード取得 → ② 記事生成 → ③ 品質チェック → ④ 画像取得 → ⑤ draft保存 → ⑥ 承認メール送信 → ⑦ 人間レビュー → ⑧ 公開/却下)

エラー① 件名が「object」と表示される

症状

承認メールの件名が記事タイトルではなく object という文字列になる。

原因

WordPress REST APIは投稿タイトルをオブジェクト形式で返す仕様になっている。

// WordPress REST APIのレスポンス
{
  "title": {
    "raw": "記事タイトル",
    "rendered": "記事タイトル"
  }
}

n8nのemailSendノードで $json.title と参照するとオブジェクトが文字列化され [object Object] になる。

解決策

以下変更を加える。

// NG
$json.title

// OK
$json.title.raw

エラー② 本文が空のメールが届く(1回目)

症状

件名は修正されたが、メール本文が完全に空になっていた。messageSize を確認すると 411バイト(ヘッダーのみ)。

原因

n8n emailSendノード(typeVersion 2)のHTMLメール指定パラメータ名が emailType ではなく emailFormat だった。誤ったパラメータ名を設定していたため、デフォルトのtext形式で送信されていた。

// NG
"emailType": "html"

// OK
"emailFormat": "html"

エラー③ 本文が空のメールが届く(2回目)

症状

emailFormat を修正してもまだ本文が空。

原因

n8nの式モード(= プレフィックス)と {{ }} テンプレート記法を混在させていた。式モード下では {{ }} は評価されず空文字になる。

// NG: =プレフィックス(式モード) + {{ }}テンプレート記法の混在
=<html>...{{ $json.title.raw }}...</html>

// OK: 式モードに統一
="<html>..." + $json.title.raw + "...</html>"

エラー④ HTMLのコードがそのまま本文に表示される

症状

メール本文にJavaScriptコードが文字列としてそのまま表示される。

タイトル:" + $json.title.raw + "

" + "
" + ($json.content.raw || "").replace(/<[^>]*>/g, "").substring(0, 300) + "..." + "
" + "

記事プレビューを確認する

" + "
" + "承認して公開する" + "却下する" + "
"

原因

n8n v2 のemailSendノードでバックティックテンプレートリテラルが評価されず、文字列としてそのまま送信された。

解決策

HTML生成をemailSendノードから完全に分離し、専用のFunctionノード(Prepare Email HTML)を追加。FunctionノードはJavaScriptを直接実行するためテンプレートリテラルが確実に動作する。

// Prepare Email HTML(Functionノード)
const item = $input.first().json;
const postId = item.id;
const title = item.title?.raw || '';
const previewUrl = 'https://example.com/?p=' + postId;

const emailHtml = \`<!DOCTYPE html>
<html>
  <body>
    <h2>\${title}</h2>
    <a href="\${previewUrl}">プレビューを確認する</a>
  </body>
</html>\`;

return [{ json: { emailSubject: '【要承認】' + title, emailHtml } }];

// emailSendノード側はシンプルな参照のみ
// subject: ={{ $json.emailSubject }}
// html:    ={{ $json.emailHtml }}

エラー⑤ 承認・却下ボタンのリンクが機能しない

症状

メールに表示されるボタンをクリックすることで投稿の承認を考えていたが、ボタンのhref属性が https://”https://hakamad.com/…” という二重URLになっており、クリックしても正しいURLに飛ばない。

原因

emailSendノードのhtmlフィールド内でURL文字列の引用符が正しく処理されておらず、”https://…”(文字列)をhref属性値としてそのまま埋め込んでいた。

解決策

エラー④の対応(Functionノードへの分離)により解消。FunctionノードでURL文字列を先に組み立て、テンプレートリテラルでHTMLに埋め込むことで引用符の問題が発生しなくなった。

// Functionノード内でURLを先に組み立て
const approveUrl = 'https://example.com/webhook/article-approve?post_id=' + postId + '&action=approve';

// テンプレートリテラルで安全に埋め込み
const emailHtml = \`<a href="\${approveUrl}">承認して公開する</a>\`;

まとめ:n8n emailSendノードのポイント

項目正しい設定
HTMLメールの指定emailFormat: “html”(emailTypeではない)
動的値の参照={{ $json.フィールド名 }}のシンプルな式のみ
HTML本文の組み立てemailSendノード内では行わず、前段のFunctionノードで完結させる
WordPress APIのtitle参照$json.title.raw($json.titleはオブジェクト)

動的なHTMLを含むメール送信はFunctionノードで完結させ、emailSendノードには完成した文字列を渡すだけにするのが最もシンプルで確実な構成です。

コメント

タイトルとURLをコピーしました