- 動作確認日:2026-10-01
- n8nのバージョン:2.41.3(Docker、セルフホスト)
目次
① 結論:このワークフローでできること
Gmailに条件に合うメールが届いたら、その件名と本文の冒頭を、Slackのチャンネルに知らせます。
- 起動には、n8nの「Gmail Trigger」を使います。n8nが1分ごとにGmailを確かめに行くしくみ(ポーリング)なので、n8nを
localhostで動かしていても使えます。 - 条件は、Gmailの検索ボックスと同じ書き方で決めます(今回は件名に
[n8nテスト]を含むメール)。 - 送信者のメールアドレスは、Slackには送りません。
- 使う認証情報(Credentials)は、GmailとSlackの2つです。
② 完成イメージ

ワークフローを有効にしてから、自分あてに、件名に [n8nテスト] を入れたテストメールを1通送りました。
| できごと | 時刻 |
|---|---|
| ワークフローを有効にした | 13:03 |
| テストメールが届いた | 13:04 |
| n8nがメールを見つけて、Slackに送った | 13:05 |
メールが届いてから1分ほどで、Slackのチャンネルに通知が届きました。

送ったメッセージは、次のとおりです(実際の内容です)。
:envelope: 新しいメールが届きました(10/01 13:04)
*[n8nテスト] 請求書の件*
> 来月分の請求書を送ります
実行したときの件数の流れは、次のとおりです。
| ノード | 出てきた件数 |
|---|---|
| Gmail Trigger | 1 |
| Make Message(Code) | 1 |
| Slack | 1 |
動かしてみて気づいた点が2つあります。
- n8nの実行の一覧では、この実行の種類(Mode)が「trigger」になっていました。Webhookで動かしたときとは別の種類として記録されます。
- Gmail Triggerの「Simplify」をオンにすると、出力は
id、snippet、internalDate、Subject、From、Toなどの形になりました。FromとToにはメールアドレスが入るので、今回はSlackに渡していません。
③ 使うノードと必要なもの
必要なもの
- n8n(今回はバージョン2.41.3をDockerで動かしました)
- 認証情報:Gmail OAuth2 API(Google Cloudで作ったOAuthクライアントを使います)
- Slackのワークスペースとチャンネル、Slackアプリの「Bot User OAuth Token」、チャンネルID
- 認証情報:Slack API
Slackアプリの作り方とチャンネルIDの調べ方は、「n8nでブログの新着記事をSlackに通知するワークフロー」の記事で説明しています。
使うノード
| ノード | 役割 | 設定したこと |
|---|---|---|
| Gmail Trigger | 条件に合うメールが届いたら動く | Poll Times:Every Minute、Event:Message Received、Simplify:オン、Search:subject:"[n8nテスト]" |
| Code(Make Message) | Slackに送る文章を作る | 下のコード |
| Slack | メッセージを送る | Send Message To:Channel、Channel:By ID、Message Text:{{ $json.text }}、Include Link to Workflow:オフ |

Gmail Triggerでは、「Poll Times」で、どのくらいの間隔でGmailを確かめに行くかを決めます。今回は「Every Minute」(1分ごと)にしました。「Search」には、Gmailの検索ボックスと同じ書き方で条件を入れます。
| 書き方 | 知らせるメール |
|---|---|
subject:"[n8nテスト]" | 件名に [n8nテスト] を含む |
from:example.com | example.com から届いた |
is:important | 重要マークが付いた |

Make Messageでは、次の処理をしています。
// 届いたメールを、Slackに送る文章にする(送信者のアドレスは入れない)
const esc = s => (s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
return $input.all().map(i => {
const m = i.json;
const at = DateTime.fromMillis(Number(m.internalDate)).setZone('Asia/Tokyo').toFormat('MM/dd HH:mm');
const snippet = (m.snippet || '').slice(0, 80) || '(本文なし)';
return { json: { text: `:envelope: 新しいメールが届きました(${at})\n*${esc(m.Subject)}*\n> ${esc(snippet)}` } };
});
internalDateは、1970年からのミリ秒の数字(文字列)で返ってくるので、日本時間の日時に直しています。- 本文の冒頭(
snippet)は、長すぎないように80文字までにしています。本文がないメールは「(本文なし)」と表示します。 - Slackでは、
*で囲むと太字、行の先頭に>を付けると引用の形で表示されます。 - 件名に
<や&が入っていると表示が崩れるので、先に置き換えています。
④ JSON
n8nの公開API(POST /api/v1/workflows)でこのJSONからワークフローを作成し、有効化してから、上の結果を確認しました。
使うときは、次の箇所を自分の環境に合わせて書き換えてください。
YOUR_GMAIL_CREDENTIAL_ID:n8nに登録したGmailの認証情報のIDYOUR_SLACK_CREDENTIAL_ID:n8nに登録したSlack APIの認証情報のIDYOUR_CHANNEL_ID:送り先のチャンネルID- Gmail TriggerのSearch:知らせたいメールの条件に変えてください。
読み込んだあとに、ノードの画面で認証情報を選び直しても大丈夫です。
{
"name": "test-gmail-slack",
"nodes": [
{ "parameters": {
"pollTimes": { "item": [ { "mode": "everyMinute" } ] },
"simple": true,
"filters": { "q": "subject:\"[n8nテスト]\"" },
"options": {} },
"id": "b6000000-0001-4000-8000-000000000001", "name": "Gmail Trigger", "type": "n8n-nodes-base.gmailTrigger", "typeVersion": 1.2, "position": [0, 0],
"credentials": { "gmailOAuth2": { "id": "YOUR_GMAIL_CREDENTIAL_ID", "name": "Gmail account" } } },
{ "parameters": { "jsCode": "// 届いたメールを、Slackに送る文章にする(送信者のアドレスは入れない)\nconst esc = s => (s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\nreturn $input.all().map(i => {\n const m = i.json;\n const at = DateTime.fromMillis(Number(m.internalDate)).setZone('Asia/Tokyo').toFormat('MM/dd HH:mm');\n const snippet = (m.snippet || '').slice(0, 80) || '(本文なし)';\n return { json: { text: `:envelope: 新しいメールが届きました(${at})\\n*${esc(m.Subject)}*\\n> ${esc(snippet)}` } };\n});" },
"id": "b6000000-0002-4000-8000-000000000002", "name": "Make Message", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [220, 0] },
{ "parameters": {
"select": "channel",
"channelId": { "__rl": true, "value": "YOUR_CHANNEL_ID", "mode": "id" },
"text": "={{ $json.text }}",
"otherOptions": { "includeLinkToWorkflow": false } },
"id": "b6000000-0003-4000-8000-000000000003", "name": "Slack", "type": "n8n-nodes-base.slack", "typeVersion": 2.3, "position": [440, 0],
"webhookId": "b6000000-bbbb-4000-8000-000000000003",
"credentials": { "slackApi": { "id": "YOUR_SLACK_CREDENTIAL_ID", "name": "Slack account" } } }
],
"connections": {
"Gmail Trigger": { "main": [[{ "node": "Make Message", "type": "main", "index": 0 }]] },
"Make Message": { "main": [[{ "node": "Slack", "type": "main", "index": 0 }]] }
},
"settings": { "executionOrder": "v1" }
}
⑤ つまずきポイントと対処
このワークフロー自体は、1回目でエラーなく動きました。ここでは、気をつける点を書きます。
有効にする前に届いたメールは知らせない
- 気をつけること:Gmail Triggerは、ワークフローを有効にしたあとに届いたメールだけを対象にします。条件に合う古いメールが受信トレイにあっても、まとめて知らされることはありませんでした。
- 対処:テストは、ワークフローを有効にしてから、新しくメールを送って確かめました。
「Execute workflow」で試すときとは動きが違う
- 気をつけること:n8nの説明では、エディタの「Execute workflow」で試すと、条件に合うメールを取ってきて動くことになっています(今回は試していません)。本番の動き(新しいメールが届いたときだけ動く)を確かめるには、ワークフローを有効にしてから、メールを送る必要があります。
送信者のアドレスがSlackに出てしまう
- 気をつけること:Gmail Triggerの出力をそのままSlackに送ると、
FromやToのメールアドレスが、チャンネルの全員に見えます。 - 対処:Make Messageで、送る項目(件名、本文の冒頭、受信日時)だけを選んで文章を作っています。
⑥ 応用アイデア
どれも、まだ試していないアイデアです。
- Searchを
from:取引先のドメインにして、取引先からのメールだけを知らせる - 件名に「至急」を含むメールだけ、
@hereを付けて知らせる - 知らせたメールをGoogle Sheetsにも記録して、対応したかどうかを管理する
- 通知先を、DiscordやLINE、Telegramに替える
