openclaw - ✅(Solved) Fix [Bug]: Gmail → Telegram/Discord notifications stopped: gog /gmail-pubsub push endpoint [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#58639Fetched 2026-04-08 01:59:51
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Participants
Timeline (top)
cross-referenced ×1labeled ×1

Here’s a fresh, self‑contained summary you can save or paste.


Root Cause

Here’s a fresh, self‑contained summary you can save or paste.


PR fix notes

PR #60574: fix(hooks): remove hooks token from Tailscale Funnel push endpoint URL

Description (problem / solution / changelog)

Summary

  • Problem: ensureTailscaleEndpoint() in src/hooks/gmail-setup-utils.ts:315 appends the hooks token as ?token= to the Pub/Sub push endpoint URL
  • Why it matters: the token leaks to Tailscale relay logs and Google Pub/Sub subscription metadata. Also, server-http.ts:502 explicitly rejects requests with ?token= in query params (returns 400), which breaks Gmail push delivery
  • What changed: removed the token from the push endpoint URL. The gog serve process already receives the token via --token CLI arg and authenticates against the gateway via Authorization header
  • What did NOT change (scope boundary): no changes to the hooks auth flow, gog serve behavior, or gateway token validation

The rest of the codebase already follows the correct pattern. dashboard.ts:75, onboard-helpers.ts:146, and setup.finalize.ts:314 all use URL fragments (#token=) to avoid server-side log exposure.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related #58639
  • Related #59002
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

  • Root cause: ensureTailscaleEndpoint() was written to include the token in the URL for Pub/Sub push delivery, but the gateway hooks handler was later hardened to reject ?token= in query params (server-http.ts:502-508). The two code paths became inconsistent.
  • Missing detection / guardrail: no test validates that the push endpoint URL does not contain secrets in query parameters
  • Prior context: the ?token= rejection was added in a security hardening pass. The Tailscale endpoint builder was not updated to match.
  • Why this regressed now: the security hardening of server-http.ts created the inconsistency with the existing gmail-setup-utils code

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/hooks/gmail-setup-utils.test.ts
  • Scenario the test should lock in: ensureTailscaleEndpoint with a token param should NOT include ?token= in the returned URL
  • Why this is the smallest reliable guardrail: tests the exact function that constructs the URL
  • If no new test is added, why not: the existing 3 tests in gmail-setup-utils.test.ts pass. A dedicated test for token-not-in-URL could be added by the maintainers if desired. The fix removes the code path entirely rather than changing its behavior.

User-visible / Behavior Changes

Gmail push notifications via Tailscale Funnel may start working for users who had hooks token configured. Previously, Google Pub/Sub would POST to a URL with ?token=, which the gateway rejects with 400.

Diagram (if applicable)

Before:
[Google Pub/Sub] -> POST https://gw.ts.net/hooks/gmail?token=SECRET -> [Tailscale] -> [gog serve] -> [gateway rejects: 400 "query parameters are not allowed"]

After:
[Google Pub/Sub] -> POST https://gw.ts.net/hooks/gmail -> [Tailscale] -> [gog serve --token SECRET] -> [gateway via Authorization header] -> OK

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? Yes
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: the hooks token is no longer placed in the push endpoint URL. This eliminates token exposure in Tailscale relay logs and Google Pub/Sub subscription metadata. The gog serve process already receives the token via --token CLI argument and authenticates via Authorization: Bearer header or X-OpenClaw-Token header. No change in authentication behavior.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 25.2.1
  • Integration/channel: Gmail hooks via Tailscale Funnel

Steps

  1. Configure Gmail hooks with Tailscale Funnel mode and a hooks token
  2. Run openclaw hooks gmail setup
  3. Check the Pub/Sub subscription: gcloud pubsub subscriptions describe <sub> --format="value(pushConfig.pushEndpoint)"

Expected

Push endpoint URL should NOT contain the hooks token

Actual

Before fix: https://gw.ts.net/hooks/gmail?token=SECRET After fix: https://gw.ts.net/hooks/gmail

Evidence

  • Trace/log snippets

ensureTailscaleEndpoint() at gmail-setup-utils.ts:315:

// Before:
return params.token ? `${baseUrl}?token=${params.token}` : baseUrl;
// After:
return baseUrl;

Inconsistency with rest of codebase:

  • dashboard.ts:75 uses #token= (correct)
  • onboard-helpers.ts:146 uses #token= (correct)
  • setup.finalize.ts:314 uses #token= (correct)
  • server-http.ts:502 rejects ?token= with 400 (contradicts the old gmail-setup-utils code)

Human Verification (required)

  • Verified scenarios: existing tests pass (gmail-setup-utils.test.ts, 3/3 green), diff is a single code path removal
  • Edge cases checked: ensureTailscaleEndpoint called without token param still returns baseUrl (no change in behavior for that path)
  • What I did NOT verify: end-to-end Gmail push delivery with live Tailscale Funnel (no Tailscale setup in my environment)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Users who had broken Gmail push notifications due to the ?token= rejection may need to re-run openclaw hooks gmail setup to update the Pub/Sub subscription endpoint.

Risks and Mitigations

  • Risk: users who somehow relied on the ?token= in the Pub/Sub URL for custom middleware
    • Mitigation: this URL shape was rejected by the gateway anyway (400 error), so no working setup depends on it

AI-assisted: yes (analysis and PR preparation with Claude). Fix is a single line change, fully understood and manually verified. Tests run locally with vitest: 3/3 passing.

Changed files

  • src/hooks/gmail-setup-utils.ts (modified, +5/-1)

Code Example

"hooks": {
  "enabled": true,
  "path": "/hooks",
  "token": "8169…f67c",
  "defaultSessionKey": "hook:ingress",
  "allowedAgentIds": ["main"],
  "presets": ["gmail"],
  "mappings": [
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail",
      "sessionKey": "hook:gmail:{{messages[0].id}}",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "telegram",
      "to": "telegram:1888587348"
    },
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail (Discord)",
      "sessionKey": "hook:gmail:{{messages[0].id}}:discord",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "discord",
      "to": "discord:channel:1485211051459870802"
    }
  ],
  "gmail": {
    "account": "[email protected]"
  }
}

---

http://127.0.0.1:18789/hooks/gmail?token=8169…f67c

---

$GogExe = 'C:\Tools\gogcli\gog.exe'
$Account = '[email protected]'
$Port = 8789
$Path = '/gmail-pubsub'
$HookUrl = 'http://127.0.0.1:18789/hooks/gmail'
$HookToken = '8169…f67c'

Start-Process $GogExe -ArgumentList @(
  'gmail', 'watch', 'serve',
  '--account', $Account,
  '--bind', '127.0.0.1',
  '--port', "$Port",
  '--path', $Path,
  '--token', $HookToken,
  '--hook-url', $HookUrl,
  '--hook-token', $HookToken,
  '--include-body',
  '--max-bytes', '20000'
) -WindowStyle Minimized

# Then waits for 127.0.0.1:8789 to listen,
# rebuilds Tailscale serve/funnel, and verifies Funnel readiness.

---

tailscale funnel status

# Funnel on:
# - https://zeusdriver.tail4e3da6.ts.net

https://zeusdriver.tail4e3da6.ts.net (Funnel on)
|-- /gmail-pubsub proxy http://127.0.0.1:8789

---

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub[?token=...]

---

http://127.0.0.1:8789/gmail-pubsub[?token=...]

---

gog.exe gmail watch status --account zeus.lobster@gmail.com

account zeus.lobster@gmail.com
topic projects/zeus-god-is-alive/topics/gog-gmail-watch
labels INBOX
history_id 6038
expiration 2026-04-06T14:46:30-06:00
provider_expiration 2026-04-06T14:46:30-06:00
updated_at 2026-03-30T17:52:18-06:00
last_delivery_status ok
last_delivery_at 2026-03-30T17:52:18-06:00
last_push_message_id 18715057819460205

---

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub?token=... # token redacted

---

http://127.0.0.1:8789/gmail-pubsub

---

405 Method Not Allowed

---

"hooks": {
  "enabled": true,
  "path": "/hooks",
  "token": "8169…f67c",
  "defaultSessionKey": "hook:ingress",
  "allowedAgentIds": ["main"],
  "presets": ["gmail"],
  "mappings": [
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail",
      "sessionKey": "hook:gmail:{{messages[0].id}}",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "telegram",
      "to": "telegram:1888587348"
    },
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail (Discord)",
      "sessionKey": "hook:gmail:{{messages[0].id}}:discord",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "discord",
      "to": "discord:channel:1485211051459870802"
    }
  ],
  "gmail": {
    "account": "[email protected]"
  }
}

---

http://127.0.0.1:18789/hooks/gmail?token=8169…f67c

---

$GogExe = 'C:\Tools\gogcli\gog.exe'
$Account = '[email protected]'
$Port = 8789
$Path = '/gmail-pubsub'
$HookUrl = 'http://127.0.0.1:18789/hooks/gmail'
$HookToken = '8169…f67c'

Start-Process $GogExe -ArgumentList @(
  'gmail', 'watch', 'serve',
  '--account', $Account,
  '--bind', '127.0.0.1',
  '--port', "$Port",
  '--path', $Path,
  '--token', $HookToken,
  '--hook-url', $HookUrl,
  '--hook-token', $HookToken,
  '--include-body',
  '--max-bytes', '20000'
) -WindowStyle Minimized

# Then waits for 127.0.0.1:8789 to listen,
# rebuilds Tailscale serve/funnel, and verifies Funnel readiness.

---

tailscale funnel status

# Funnel on:
# - https://zeusdriver.tail4e3da6.ts.net

https://zeusdriver.tail4e3da6.ts.net (Funnel on)
|-- /gmail-pubsub proxy http://127.0.0.1:8789

---

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub[?token=...]

---

http://127.0.0.1:8789/gmail-pubsub[?token=...]

---

gog.exe gmail watch status --account zeus.lobster@gmail.com

account zeus.lobster@gmail.com
topic projects/zeus-god-is-alive/topics/gog-gmail-watch
labels INBOX
history_id 6038
expiration 2026-04-06T14:46:30-06:00
provider_expiration 2026-04-06T14:46:30-06:00
updated_at 2026-03-30T17:52:18-06:00
last_delivery_status ok
last_delivery_at 2026-03-30T17:52:18-06:00
last_push_message_id 18715057819460205

---

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub?token=... # token redacted

---

http://127.0.0.1:8789/gmail-pubsub

---

405 Method Not Allowed

---

"hooks": {
  "enabled": true,
  "path": "/hooks",
  "token": "8169…f67c",
  "defaultSessionKey": "hook:ingress",
  "allowedAgentIds": ["main"],
  "presets": ["gmail"],
  "mappings": [
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail",
      "sessionKey": "hook:gmail:{{messages[0].id}}",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "telegram",
      "to": "telegram:1888587348"
    },
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail (Discord)",
      "sessionKey": "hook:gmail:{{messages[0].id}}:discord",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "discord",
      "to": "discord:channel:1485211051459870802"
    }
  ],
  "gmail": {
    "account": "[email protected]"
  }
}

---

http://127.0.0.1:18789/hooks/gmail?token=8169…f67c

---

$GogExe = 'C:\Tools\gogcli\gog.exe'
$Account = '[email protected]'
$Port = 8789
$Path = '/gmail-pubsub'
$HookUrl = 'http://127.0.0.1:18789/hooks/gmail'
$HookToken = '8169…f67c'

Start-Process $GogExe -ArgumentList @(
  'gmail', 'watch', 'serve',
  '--account', $Account,
  '--bind', '127.0.0.1',
  '--port', "$Port",
  '--path', $Path,
  '--token', $HookToken,
  '--hook-url', $HookUrl,
  '--hook-token', $HookToken,
  '--include-body',
  '--max-bytes', '20000'
) -WindowStyle Minimized

# Then waits for 127.0.0.1:8789 to listen,
# rebuilds Tailscale serve/funnel, and verifies Funnel readiness.

---

tailscale funnel status

# Funnel on:
# - https://zeusdriver.tail4e3da6.ts.net

https://zeusdriver.tail4e3da6.ts.net (Funnel on)
|-- /gmail-pubsub proxy http://127.0.0.1:8789

---

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub[?token=...]

---

http://127.0.0.1:8789/gmail-pubsub[?token=...]

---

gog.exe gmail watch status --account zeus.lobster@gmail.com

account zeus.lobster@gmail.com
topic projects/zeus-god-is-alive/topics/gog-gmail-watch
labels INBOX
history_id 6038
expiration 2026-04-06T14:46:30-06:00
provider_expiration 2026-04-06T14:46:30-06:00
updated_at 2026-03-30T17:52:18-06:00
last_delivery_status ok
last_delivery_at 2026-03-30T17:52:18-06:00
last_push_message_id 18715057819460205

---

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub?token=... # token redacted

---

http://127.0.0.1:8789/gmail-pubsub

---

405 Method Not Allowed

---
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

Here’s a fresh, self‑contained summary you can save or paste.


Summary: Gmail → Telegram/Discord notifications stopped

Environment

  • OS: Windows 10 (x64)
  • OpenClaw: 2026.3.31 (213a704) (latest stable)
  • Gateway: local, ws://127.0.0.1:18789 (Scheduled Task, reachable)
  • Tailscale: Funnel ON
  • Gmail account: [email protected]
  • gog CLI: C:\Tools\gogcli\gog.exe
  • Channels:
    • Telegram: ON, OK
    • Discord: ON, OK

Goal

Send all Gmail INBOX notifications to:

  • Telegram DM: telegram:1888587348
  • Discord channel: discord:channel:1485211051459870802

(no longer filtering “important only” – want all INBOX mail surfaced).


OpenClaw hook config

From C:\Users\staeb\.openclaw\openclaw.json:

"hooks": {
  "enabled": true,
  "path": "/hooks",
  "token": "8169…f67c",
  "defaultSessionKey": "hook:ingress",
  "allowedAgentIds": ["main"],
  "presets": ["gmail"],
  "mappings": [
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail",
      "sessionKey": "hook:gmail:{{messages[0].id}}",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "telegram",
      "to": "telegram:1888587348"
    },
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail (Discord)",
      "sessionKey": "hook:gmail:{{messages[0].id}}:discord",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "discord",
      "to": "discord:channel:1485211051459870802"
    }
  ],
  "gmail": {
    "account": "[email protected]"
  }
}

So any successful request to:

http://127.0.0.1:18789/hooks/gmail?token=8169…f67c

should send a formatted email notification to both Telegram and Discord.


Gmail watcher script (gmail-watcher-start.ps1)

Key parts:

$GogExe = 'C:\Tools\gogcli\gog.exe'
$Account = '[email protected]'
$Port = 8789
$Path = '/gmail-pubsub'
$HookUrl = 'http://127.0.0.1:18789/hooks/gmail'
$HookToken = '8169…f67c'

Start-Process $GogExe -ArgumentList @(
  'gmail', 'watch', 'serve',
  '--account', $Account,
  '--bind', '127.0.0.1',
  '--port', "$Port",
  '--path', $Path,
  '--token', $HookToken,
  '--hook-url', $HookUrl,
  '--hook-token', $HookToken,
  '--include-body',
  '--max-bytes', '20000'
) -WindowStyle Minimized

# Then waits for 127.0.0.1:8789 to listen,
# rebuilds Tailscale serve/funnel, and verifies Funnel readiness.

This script is installed as a Scheduled Task (“Zeus Gmail Watcher”) and runs at logon.


Tailscale funnel

tailscale funnel status

# Funnel on:
# - https://zeusdriver.tail4e3da6.ts.net

https://zeusdriver.tail4e3da6.ts.net (Funnel on)
|-- /gmail-pubsub proxy http://127.0.0.1:8789

So Pub/Sub pushes to:

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub[?token=...]

which funnels to:

http://127.0.0.1:8789/gmail-pubsub[?token=...]

Gmail watch status (via gog)

gog.exe gmail watch status --account [email protected]

account [email protected]
topic projects/zeus-god-is-alive/topics/gog-gmail-watch
labels INBOX
history_id 6038
expiration 2026-04-06T14:46:30-06:00
provider_expiration 2026-04-06T14:46:30-06:00
updated_at 2026-03-30T17:52:18-06:00
last_delivery_status ok
last_delivery_at 2026-03-30T17:52:18-06:00
last_push_message_id 18715057819460205

So:

  • Watch is active on INBOX (all inbox mail).
  • It has delivered successfully in the recent past.

Pub/Sub subscription

Topic: projects/zeus-god-is-alive/topics/gog-gmail-watch

Subscription (Push): projects/zeus-god-is-alive/subscriptions/gog-gmail-watch-push

Current push endpoint:

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub?token=... # token redacted

Pub/Sub metrics:

  • url_not_found_404 steadily > 0
  • unreachable_network_error = 0
  • webhook_timeout ≈ 0

This means:

  • Google can reach the URL,
  • but the service behind it is returning 404 (or related).

Local probing

  • gog.exe is running and listening on 127.0.0.1:8789.

  • Invoke-WebRequest to:

    http://127.0.0.1:8789/gmail-pubsub

    returns:

    405 Method Not Allowed

    which implies the path exists and only POST is allowed (as expected for a webhook).

  • Gmail test emails arrive in INBOX.

  • However:

    • openclaw logs --follow shows no POST /hooks/gmail events when test mails arrive.
    • No new notifications appear in Telegram or Discord.

Current understanding

  • The OpenClaw side is correctly configured to deliver any /hooks/gmail POST to Telegram + Discord.
  • The Gmail watch is active on INBOX.
  • The Tailscale funnel is correctly mapping the public URL to http://127.0.0.1:8789/gmail-pubsub.
  • Pub/Sub is calling the funnel URL but is seeing 404‑class errors there.
  • The service on port 8789 (gog) sends 405 for an HTTP GET on /gmail-pubsub, which is normal for a POST‑only handler.

Net effect: Gmail → Pub/Sub → Tailscale → gog is not resulting in processed webhook calls that reach /hooks/gmail, so OpenClaw never emits notifications to Telegram/Discord.


Steps to reproduce

Here’s a fresh, self‑contained summary you can save or paste.


Summary: Gmail → Telegram/Discord notifications stopped

Environment

  • OS: Windows 10 (x64)
  • OpenClaw: 2026.3.31 (213a704) (latest stable)
  • Gateway: local, ws://127.0.0.1:18789 (Scheduled Task, reachable)
  • Tailscale: Funnel ON
  • Gmail account: [email protected]
  • gog CLI: C:\Tools\gogcli\gog.exe
  • Channels:
    • Telegram: ON, OK
    • Discord: ON, OK

Goal

Send all Gmail INBOX notifications to:

  • Telegram DM: telegram:1888587348
  • Discord channel: discord:channel:1485211051459870802

(no longer filtering “important only” – want all INBOX mail surfaced).


OpenClaw hook config

From C:\Users\staeb\.openclaw\openclaw.json:

"hooks": {
  "enabled": true,
  "path": "/hooks",
  "token": "8169…f67c",
  "defaultSessionKey": "hook:ingress",
  "allowedAgentIds": ["main"],
  "presets": ["gmail"],
  "mappings": [
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail",
      "sessionKey": "hook:gmail:{{messages[0].id}}",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "telegram",
      "to": "telegram:1888587348"
    },
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail (Discord)",
      "sessionKey": "hook:gmail:{{messages[0].id}}:discord",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "discord",
      "to": "discord:channel:1485211051459870802"
    }
  ],
  "gmail": {
    "account": "[email protected]"
  }
}

So any successful request to:

http://127.0.0.1:18789/hooks/gmail?token=8169…f67c

should send a formatted email notification to both Telegram and Discord.


Gmail watcher script (gmail-watcher-start.ps1)

Key parts:

$GogExe = 'C:\Tools\gogcli\gog.exe'
$Account = '[email protected]'
$Port = 8789
$Path = '/gmail-pubsub'
$HookUrl = 'http://127.0.0.1:18789/hooks/gmail'
$HookToken = '8169…f67c'

Start-Process $GogExe -ArgumentList @(
  'gmail', 'watch', 'serve',
  '--account', $Account,
  '--bind', '127.0.0.1',
  '--port', "$Port",
  '--path', $Path,
  '--token', $HookToken,
  '--hook-url', $HookUrl,
  '--hook-token', $HookToken,
  '--include-body',
  '--max-bytes', '20000'
) -WindowStyle Minimized

# Then waits for 127.0.0.1:8789 to listen,
# rebuilds Tailscale serve/funnel, and verifies Funnel readiness.

This script is installed as a Scheduled Task (“Zeus Gmail Watcher”) and runs at logon.


Tailscale funnel

tailscale funnel status

# Funnel on:
# - https://zeusdriver.tail4e3da6.ts.net

https://zeusdriver.tail4e3da6.ts.net (Funnel on)
|-- /gmail-pubsub proxy http://127.0.0.1:8789

So Pub/Sub pushes to:

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub[?token=...]

which funnels to:

http://127.0.0.1:8789/gmail-pubsub[?token=...]

Gmail watch status (via gog)

gog.exe gmail watch status --account [email protected]

account [email protected]
topic projects/zeus-god-is-alive/topics/gog-gmail-watch
labels INBOX
history_id 6038
expiration 2026-04-06T14:46:30-06:00
provider_expiration 2026-04-06T14:46:30-06:00
updated_at 2026-03-30T17:52:18-06:00
last_delivery_status ok
last_delivery_at 2026-03-30T17:52:18-06:00
last_push_message_id 18715057819460205

So:

  • Watch is active on INBOX (all inbox mail).
  • It has delivered successfully in the recent past.

Pub/Sub subscription

Topic: projects/zeus-god-is-alive/topics/gog-gmail-watch

Subscription (Push): projects/zeus-god-is-alive/subscriptions/gog-gmail-watch-push

Current push endpoint:

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub?token=... # token redacted

Pub/Sub metrics:

  • url_not_found_404 steadily > 0
  • unreachable_network_error = 0
  • webhook_timeout ≈ 0

This means:

  • Google can reach the URL,
  • but the service behind it is returning 404 (or related).

Local probing

  • gog.exe is running and listening on 127.0.0.1:8789.

  • Invoke-WebRequest to:

    http://127.0.0.1:8789/gmail-pubsub

    returns:

    405 Method Not Allowed

    which implies the path exists and only POST is allowed (as expected for a webhook).

  • Gmail test emails arrive in INBOX.

  • However:

    • openclaw logs --follow shows no POST /hooks/gmail events when test mails arrive.
    • No new notifications appear in Telegram or Discord.

Current understanding

  • The OpenClaw side is correctly configured to deliver any /hooks/gmail POST to Telegram + Discord.
  • The Gmail watch is active on INBOX.
  • The Tailscale funnel is correctly mapping the public URL to http://127.0.0.1:8789/gmail-pubsub.
  • Pub/Sub is calling the funnel URL but is seeing 404‑class errors there.
  • The service on port 8789 (gog) sends 405 for an HTTP GET on /gmail-pubsub, which is normal for a POST‑only handler.

Net effect: Gmail → Pub/Sub → Tailscale → gog is not resulting in processed webhook calls that reach /hooks/gmail, so OpenClaw never emits notifications to Telegram/Discord.


You can paste that summary into Discord/GitHub or save it locally as your “state of the world” for the no‑notifications issue.

Expected behavior

Here’s a fresh, self‑contained summary you can save or paste.


Summary: Gmail → Telegram/Discord notifications stopped

Environment

  • OS: Windows 10 (x64)
  • OpenClaw: 2026.3.31 (213a704) (latest stable)
  • Gateway: local, ws://127.0.0.1:18789 (Scheduled Task, reachable)
  • Tailscale: Funnel ON
  • Gmail account: [email protected]
  • gog CLI: C:\Tools\gogcli\gog.exe
  • Channels:
    • Telegram: ON, OK
    • Discord: ON, OK

Goal

Send all Gmail INBOX notifications to:

  • Telegram DM: telegram:1888587348
  • Discord channel: discord:channel:1485211051459870802

(no longer filtering “important only” – want all INBOX mail surfaced).


OpenClaw hook config

From C:\Users\staeb\.openclaw\openclaw.json:

"hooks": {
  "enabled": true,
  "path": "/hooks",
  "token": "8169…f67c",
  "defaultSessionKey": "hook:ingress",
  "allowedAgentIds": ["main"],
  "presets": ["gmail"],
  "mappings": [
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail",
      "sessionKey": "hook:gmail:{{messages[0].id}}",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "telegram",
      "to": "telegram:1888587348"
    },
    {
      "match": { "path": "gmail" },
      "action": "agent",
      "wakeMode": "now",
      "name": "Gmail (Discord)",
      "sessionKey": "hook:gmail:{{messages[0].id}}:discord",
      "messageTemplate": "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
      "deliver": true,
      "channel": "discord",
      "to": "discord:channel:1485211051459870802"
    }
  ],
  "gmail": {
    "account": "[email protected]"
  }
}

So any successful request to:

http://127.0.0.1:18789/hooks/gmail?token=8169…f67c

should send a formatted email notification to both Telegram and Discord.


Gmail watcher script (gmail-watcher-start.ps1)

Key parts:

$GogExe = 'C:\Tools\gogcli\gog.exe'
$Account = '[email protected]'
$Port = 8789
$Path = '/gmail-pubsub'
$HookUrl = 'http://127.0.0.1:18789/hooks/gmail'
$HookToken = '8169…f67c'

Start-Process $GogExe -ArgumentList @(
  'gmail', 'watch', 'serve',
  '--account', $Account,
  '--bind', '127.0.0.1',
  '--port', "$Port",
  '--path', $Path,
  '--token', $HookToken,
  '--hook-url', $HookUrl,
  '--hook-token', $HookToken,
  '--include-body',
  '--max-bytes', '20000'
) -WindowStyle Minimized

# Then waits for 127.0.0.1:8789 to listen,
# rebuilds Tailscale serve/funnel, and verifies Funnel readiness.

This script is installed as a Scheduled Task (“Zeus Gmail Watcher”) and runs at logon.


Tailscale funnel

tailscale funnel status

# Funnel on:
# - https://zeusdriver.tail4e3da6.ts.net

https://zeusdriver.tail4e3da6.ts.net (Funnel on)
|-- /gmail-pubsub proxy http://127.0.0.1:8789

So Pub/Sub pushes to:

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub[?token=...]

which funnels to:

http://127.0.0.1:8789/gmail-pubsub[?token=...]

Gmail watch status (via gog)

gog.exe gmail watch status --account [email protected]

account [email protected]
topic projects/zeus-god-is-alive/topics/gog-gmail-watch
labels INBOX
history_id 6038
expiration 2026-04-06T14:46:30-06:00
provider_expiration 2026-04-06T14:46:30-06:00
updated_at 2026-03-30T17:52:18-06:00
last_delivery_status ok
last_delivery_at 2026-03-30T17:52:18-06:00
last_push_message_id 18715057819460205

So:

  • Watch is active on INBOX (all inbox mail).
  • It has delivered successfully in the recent past.

Pub/Sub subscription

Topic: projects/zeus-god-is-alive/topics/gog-gmail-watch

Subscription (Push): projects/zeus-god-is-alive/subscriptions/gog-gmail-watch-push

Current push endpoint:

https://zeusdriver.tail4e3da6.ts.net/gmail-pubsub?token=... # token redacted

Pub/Sub metrics:

  • url_not_found_404 steadily > 0
  • unreachable_network_error = 0
  • webhook_timeout ≈ 0

This means:

  • Google can reach the URL,
  • but the service behind it is returning 404 (or related).

Local probing

  • gog.exe is running and listening on 127.0.0.1:8789.

  • Invoke-WebRequest to:

    http://127.0.0.1:8789/gmail-pubsub

    returns:

    405 Method Not Allowed

    which implies the path exists and only POST is allowed (as expected for a webhook).

  • Gmail test emails arrive in INBOX.

  • However:

    • openclaw logs --follow shows no POST /hooks/gmail events when test mails arrive.
    • No new notifications appear in Telegram or Discord.

Current understanding

  • The OpenClaw side is correctly configured to deliver any /hooks/gmail POST to Telegram + Discord.
  • The Gmail watch is active on INBOX.
  • The Tailscale funnel is correctly mapping the public URL to http://127.0.0.1:8789/gmail-pubsub.
  • Pub/Sub is calling the funnel URL but is seeing 404‑class errors there.
  • The service on port 8789 (gog) sends 405 for an HTTP GET on /gmail-pubsub, which is normal for a POST‑only handler.

Net effect: Gmail → Pub/Sub → Tailscale → gog is not resulting in processed webhook calls that reach /hooks/gmail, so OpenClaw never emits notifications to Telegram/Discord.


You can paste that summary into Discord/GitHub or save it locally as your “state of the world” for the no‑notifications issue.

Actual behavior

What happened? Gmail INBOX emails arrive, but no new notifications reach Telegram or Discord. Pub/Sub shows url_not_found_404 on the push endpoint; OpenClaw never sees /hooks/gmail.

OpenClaw version

2026.3.31

Operating system

windows 10

Install method

No response

Model

anthropic/claude-sonnet-4.5)

Provider / routing chain

(openclaw -> cloudflare-ai-gateway -> minimax)

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The issue is likely due to the gog service not properly handling webhook calls from Pub/Sub, resulting in 404-class errors and preventing notifications from being sent to Telegram and Discord.

Guidance

  1. Verify gog configuration: Check the gog configuration to ensure it is correctly set up to handle webhook calls from Pub/Sub.
  2. Check Pub/Sub subscription: Verify that the Pub/Sub subscription is correctly configured and that the push endpoint is correctly set to the Tailscale funnel URL.
  3. Test webhook call: Test a webhook call to the gog service using a tool like curl to ensure it is properly handling POST requests.
  4. Check OpenClaw logs: Check the OpenClaw logs to see if there are any errors or issues that could be preventing notifications from being sent.

Example

To test a webhook call to the gog service, you can use a command like:

curl -X POST \
  http://127.0.0.1:8789/gmail-pubsub \
  -H 'Content-Type: application/json' \
  -d '{"message": "Test message"}'

This should return a successful response if the gog service is properly handling webhook calls.

Notes

The issue seems to be related to the gog service not properly handling webhook calls, but more information is needed to determine the root cause. Checking the gog configuration, Pub/Sub subscription, and testing a webhook call can help identify the issue.

Recommendation

Apply a workaround by testing the gog service with a manual webhook call to ensure it is properly handling POST requests. If the issue persists, further investigation into the gog configuration and Pub/Sub subscription may be necessary.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Here’s a fresh, self‑contained summary you can save or paste.


Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Gmail → Telegram/Discord notifications stopped: gog /gmail-pubsub push endpoint [1 pull requests, 1 participants]