proton-mail-bridge-client 1.11.1 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +340 -254
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +155 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1306 -114
- package/dist/index.js.map +1 -1
- package/dist/is-main.d.ts +10 -0
- package/dist/is-main.d.ts.map +1 -0
- package/dist/is-main.js +32 -0
- package/dist/is-main.js.map +1 -0
- package/dist/lib.d.ts +4 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +7 -0
- package/dist/lib.js.map +1 -0
- package/dist/scripts/bridge-smoke.js +79 -56
- package/dist/scripts/bridge-smoke.js.map +1 -1
- package/dist/services/audit-service.d.ts +3 -0
- package/dist/services/audit-service.d.ts.map +1 -1
- package/dist/services/audit-service.js +30 -11
- package/dist/services/audit-service.js.map +1 -1
- package/dist/services/background-sync-service.d.ts +1 -0
- package/dist/services/background-sync-service.d.ts.map +1 -1
- package/dist/services/background-sync-service.js +28 -2
- package/dist/services/background-sync-service.js.map +1 -1
- package/dist/services/draft-store-service.d.ts +4 -0
- package/dist/services/draft-store-service.d.ts.map +1 -1
- package/dist/services/draft-store-service.js +211 -148
- package/dist/services/draft-store-service.js.map +1 -1
- package/dist/services/local-index-service.d.ts +10 -0
- package/dist/services/local-index-service.d.ts.map +1 -1
- package/dist/services/local-index-service.js +169 -28
- package/dist/services/local-index-service.js.map +1 -1
- package/dist/services/simple-imap-service.d.ts +139 -7
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +1045 -147
- package/dist/services/simple-imap-service.js.map +1 -1
- package/dist/services/smtp-service.d.ts +2 -0
- package/dist/services/smtp-service.d.ts.map +1 -1
- package/dist/services/smtp-service.js +80 -8
- package/dist/services/smtp-service.js.map +1 -1
- package/dist/types/index.d.ts +55 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +10 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +110 -2
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/logger.d.ts +5 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +11 -3
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/runtime-policy.d.ts.map +1 -1
- package/dist/utils/runtime-policy.js +5 -0
- package/dist/utils/runtime-policy.js.map +1 -1
- package/package.json +12 -6
package/README.md
CHANGED
|
@@ -7,104 +7,265 @@
|
|
|
7
7
|
Bridge Client · CLI + Claude Desktop MCP for Proton Mail
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
<div align="center">
|
|
11
11
|
|
|
12
|
-
[](https://www.npmjs.com/package/proton-mail-bridge-client)
|
|
13
|
+
[](https://github.com/googlarz/proton-mail-bridge-client/actions/workflows/ci.yml)
|
|
14
|
+
[](LICENSE)
|
|
15
|
+
[](https://nodejs.org)
|
|
16
|
+
[](https://www.typescriptlang.org)
|
|
17
|
+
[](https://modelcontextprotocol.io)
|
|
18
|
+
[](https://github.com/googlarz/proton-mail-bridge-client)
|
|
19
|
+
[](https://github.com/googlarz/proton-mail-bridge-client/commits/main)
|
|
20
|
+
[](https://github.com/googlarz/proton-mail-bridge-client)
|
|
21
|
+
[](https://glama.ai/mcp/servers/googlarz/proton-mail-bridge-client)
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
</div>
|
|
15
24
|
|
|
16
|
-
|
|
25
|
+
---
|
|
17
26
|
|
|
18
|
-
|
|
27
|
+
Give Claude Desktop (or Cline, or any MCP client) full access to your Proton Mail inbox: read, search, send, draft, triage threads, manage folders, save attachments, and more. The same 40+ capabilities are also available as a full CLI for scripting, cron, and piped automation — no Claude required.
|
|
19
28
|
|
|
20
|
-
|
|
29
|
+
## What you get
|
|
21
30
|
|
|
22
|
-
|
|
31
|
+
- **Claude reads and manages your Proton Mail** — triage, reply, draft, archive, search, move, batch-act on threads, pull attachments
|
|
32
|
+
- **Full CLI** — same 40+ commands, scriptable and pipeable, works in cron and shell scripts
|
|
33
|
+
- **Fast local search** — full-text search across your inbox without hitting IMAP on every query
|
|
34
|
+
- **Safety controls** — read-only mode, send gate, destructive-action confirmation, per-action allowlist
|
|
35
|
+
- **Privacy-native** — no third-party email service involved; your mail stays on your machine
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
---
|
|
25
38
|
|
|
26
|
-
##
|
|
39
|
+
## Privacy model
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
Your emails travel: **Proton Mail → Proton Bridge (local) → this server (local) → your AI client**.
|
|
29
42
|
|
|
30
|
-
|
|
43
|
+
Nothing goes through a third-party email relay. Proton Bridge decrypts your mail locally; this server reads it over a local IMAP connection on `127.0.0.1`. The AI model (Claude Desktop, Cline, etc.) sees the email content you ask it to act on — that's the whole point — but no email leaves your machine except through your own Proton account when you send.
|
|
31
44
|
|
|
32
|
-
|
|
33
|
-
# Morning digest to a file
|
|
34
|
-
proton-mail-bridge-client digest --json > ~/morning-mail.json
|
|
45
|
+
If you use Claude Desktop with the default Anthropic API, conversation content (including email snippets) is sent to Anthropic per their [privacy policy](https://www.anthropic.com/privacy). If you self-host an LLM or use a local-only Claude setup, nothing leaves your machine at all.
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
proton-mail-bridge-client search --from stripe.com --json | jq '.[].subject'
|
|
47
|
+
---
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
## Prerequisites
|
|
50
|
+
|
|
51
|
+
**1. Proton Bridge** — must be installed, signed in, and running.
|
|
52
|
+
Download: [proton.me/mail/bridge](https://proton.me/mail/bridge)
|
|
43
53
|
|
|
44
|
-
**
|
|
54
|
+
> **Bridge password vs Proton password:** Proton Bridge generates a separate local password that is *not* your Proton account password. Find it inside the Bridge app under **Account → Copy password** (or similar — exact label varies by Bridge version). You'll need this for setup.
|
|
55
|
+
|
|
56
|
+
**2. Node.js 18 or later** — `node --version` to check.
|
|
57
|
+
|
|
58
|
+
**3. Your Bridge credentials** — from the Bridge app:
|
|
59
|
+
- IMAP host/port (default: `127.0.0.1:1143`)
|
|
60
|
+
- SMTP host/port (default: `127.0.0.1:1025`)
|
|
61
|
+
- Username (your Proton email address)
|
|
62
|
+
- Bridge password (see note above)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Install
|
|
67
|
+
|
|
68
|
+
**npm (recommended):**
|
|
45
69
|
|
|
46
70
|
```bash
|
|
47
|
-
|
|
48
|
-
0 8 * * 1-5 proton-mail-bridge-client digest >> ~/mail-log.txt
|
|
71
|
+
npm install -g proton-mail-bridge-client
|
|
49
72
|
```
|
|
50
73
|
|
|
51
|
-
**
|
|
74
|
+
**Homebrew:**
|
|
52
75
|
|
|
53
76
|
```bash
|
|
54
|
-
|
|
55
|
-
proton-mail-bridge-client
|
|
56
|
-
|
|
57
|
-
# Count unread in INBOX
|
|
58
|
-
proton-mail-bridge-client emails --folder INBOX --json | jq '[.[] | select(.isRead == false)] | length'
|
|
77
|
+
brew tap googlarz/tap
|
|
78
|
+
brew install proton-mail-bridge-client
|
|
59
79
|
```
|
|
60
80
|
|
|
61
|
-
|
|
81
|
+
<details>
|
|
82
|
+
<summary>Source install (development)</summary>
|
|
62
83
|
|
|
63
|
-
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/googlarz/proton-mail-bridge-client.git
|
|
86
|
+
cd proton-mail-bridge-client
|
|
87
|
+
npm install
|
|
88
|
+
npm run build
|
|
89
|
+
```
|
|
64
90
|
|
|
65
|
-
-
|
|
66
|
-
- [Proton Bridge](https://proton.me/mail/bridge) installed and signed in
|
|
67
|
-
- From Bridge: IMAP host/port, SMTP host/port, username, Bridge password
|
|
91
|
+
The `proton-mail-bridge-client` binary is available inside the repo after build.
|
|
68
92
|
|
|
69
|
-
|
|
93
|
+
</details>
|
|
70
94
|
|
|
71
|
-
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Connect to Claude Desktop
|
|
72
98
|
|
|
73
|
-
|
|
99
|
+
Run the guided setup wizard:
|
|
74
100
|
|
|
75
101
|
```bash
|
|
76
|
-
|
|
102
|
+
proton-mail-bridge-client setup-claude-desktop
|
|
77
103
|
```
|
|
78
104
|
|
|
79
|
-
|
|
105
|
+
The wizard:
|
|
106
|
+
- checks your local Bridge ports
|
|
107
|
+
- asks for your Bridge username and Bridge password
|
|
108
|
+
- writes the Claude Desktop MCP config entry
|
|
80
109
|
|
|
81
|
-
|
|
82
|
-
brew tap googlarz/tap
|
|
83
|
-
brew install proton-mail-bridge-client
|
|
84
|
-
```
|
|
110
|
+
**After setup:** restart Claude Desktop, make sure Proton Bridge is open, then check **`+` → Connectors → proton-mail-bridge**.
|
|
85
111
|
|
|
86
|
-
|
|
112
|
+
### Updating
|
|
87
113
|
|
|
88
114
|
```bash
|
|
115
|
+
npm update -g proton-mail-bridge-client
|
|
89
116
|
proton-mail-bridge-client setup-claude-desktop
|
|
90
117
|
```
|
|
91
118
|
|
|
119
|
+
### Manual config
|
|
120
|
+
|
|
121
|
+
The wizard handles config automatically. If you need to set it up by hand, three credential methods are supported:
|
|
122
|
+
|
|
92
123
|
<details>
|
|
93
|
-
<summary>
|
|
124
|
+
<summary>Option 1 — Environment variables (simplest)</summary>
|
|
94
125
|
|
|
95
|
-
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"mcpServers": {
|
|
129
|
+
"proton-mail-bridge": {
|
|
130
|
+
"command": "proton-mail-bridge-mcp",
|
|
131
|
+
"env": {
|
|
132
|
+
"PROTONMAIL_USERNAME": "you@proton.me",
|
|
133
|
+
"PROTONMAIL_PASSWORD": "your-bridge-password",
|
|
134
|
+
"PROTONMAIL_IMAP_HOST": "127.0.0.1",
|
|
135
|
+
"PROTONMAIL_IMAP_PORT": "1143",
|
|
136
|
+
"PROTONMAIL_IMAP_SECURE": "false",
|
|
137
|
+
"PROTONMAIL_SMTP_HOST": "127.0.0.1",
|
|
138
|
+
"PROTONMAIL_SMTP_PORT": "1025"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
96
144
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
145
|
+
</details>
|
|
146
|
+
|
|
147
|
+
<details>
|
|
148
|
+
<summary>Option 2 — File-based secrets (credentials in files, not config)</summary>
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"mcpServers": {
|
|
153
|
+
"proton-mail-bridge": {
|
|
154
|
+
"command": "proton-mail-bridge-mcp",
|
|
155
|
+
"env": {
|
|
156
|
+
"PROTONMAIL_USERNAME_FILE": "/path/to/username.txt",
|
|
157
|
+
"PROTONMAIL_PASSWORD_FILE": "/path/to/password.txt",
|
|
158
|
+
"PROTONMAIL_IMAP_HOST": "127.0.0.1",
|
|
159
|
+
"PROTONMAIL_IMAP_PORT": "1143",
|
|
160
|
+
"PROTONMAIL_IMAP_SECURE": "false",
|
|
161
|
+
"PROTONMAIL_SMTP_HOST": "127.0.0.1",
|
|
162
|
+
"PROTONMAIL_SMTP_PORT": "1025"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
102
167
|
```
|
|
103
168
|
|
|
104
|
-
|
|
169
|
+
</details>
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary>Option 3 — Command-based secrets (pass, gopass, or any secret manager)</summary>
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"mcpServers": {
|
|
177
|
+
"proton-mail-bridge": {
|
|
178
|
+
"command": "proton-mail-bridge-mcp",
|
|
179
|
+
"env": {
|
|
180
|
+
"PROTONMAIL_USERNAME_COMMAND": "pass proton/username",
|
|
181
|
+
"PROTONMAIL_PASSWORD_COMMAND": "pass proton/password",
|
|
182
|
+
"PROTONMAIL_IMAP_HOST": "127.0.0.1",
|
|
183
|
+
"PROTONMAIL_IMAP_PORT": "1143",
|
|
184
|
+
"PROTONMAIL_IMAP_SECURE": "false",
|
|
185
|
+
"PROTONMAIL_SMTP_HOST": "127.0.0.1",
|
|
186
|
+
"PROTONMAIL_SMTP_PORT": "1025"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
105
192
|
|
|
106
193
|
</details>
|
|
107
194
|
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Connect to Cline (VS Code)
|
|
198
|
+
|
|
199
|
+
Install globally (`npm install -g proton-mail-bridge-client`), then open Cline's MCP settings:
|
|
200
|
+
|
|
201
|
+
- VS Code → Cline extension panel → MCP servers icon → **Edit MCP Settings**
|
|
202
|
+
- Or edit directly: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` (macOS)
|
|
203
|
+
|
|
204
|
+
Add the server:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"mcpServers": {
|
|
209
|
+
"proton-mail-bridge": {
|
|
210
|
+
"command": "proton-mail-bridge-mcp",
|
|
211
|
+
"env": {
|
|
212
|
+
"PROTONMAIL_USERNAME": "you@proton.me",
|
|
213
|
+
"PROTONMAIL_PASSWORD": "your-bridge-password",
|
|
214
|
+
"PROTONMAIL_IMAP_HOST": "127.0.0.1",
|
|
215
|
+
"PROTONMAIL_IMAP_PORT": "1143",
|
|
216
|
+
"PROTONMAIL_IMAP_SECURE": "false",
|
|
217
|
+
"PROTONMAIL_SMTP_HOST": "127.0.0.1",
|
|
218
|
+
"PROTONMAIL_SMTP_PORT": "1025"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
For file-based or command-based credentials, use the same `PROTONMAIL_USERNAME_FILE` / `PROTONMAIL_PASSWORD_COMMAND` pattern from the Claude Desktop manual config above.
|
|
226
|
+
|
|
227
|
+
Reload the Cline extension after saving. Proton Mail tools will appear in Cline's tool list.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Try it: example Claude prompts
|
|
232
|
+
|
|
233
|
+
**Morning triage**
|
|
234
|
+
> "Give me a digest of my inbox. Flag anything that needs a reply today and anything that looks like a bill or invoice."
|
|
235
|
+
|
|
236
|
+
**Inbox zero**
|
|
237
|
+
> "Go through my unread emails from the past 3 days. Archive newsletters, trash anything promotional, and tell me what's left that needs action."
|
|
238
|
+
|
|
239
|
+
**Folder filing**
|
|
240
|
+
> "Find all emails from stripe.com and move them to Folders/Receipts. Create the folder if it doesn't exist."
|
|
241
|
+
|
|
242
|
+
**Meeting prep**
|
|
243
|
+
> "I have a call with alice@example.com in an hour. Pull up our last 5 email threads and summarise the open items."
|
|
244
|
+
|
|
245
|
+
**Draft review**
|
|
246
|
+
> "Show me my drafts, pick the oldest one, and suggest a better subject line and closing paragraph."
|
|
247
|
+
|
|
248
|
+
> **Tip:** When creating folders, use `Folders/Name` (not just `Name`) — that's the Proton Bridge namespace for real folders vs. labels.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Recommended System Prompt
|
|
253
|
+
|
|
254
|
+
Add this to Claude Desktop's system prompt (Settings → Claude Desktop → System Prompt) for safer defaults:
|
|
255
|
+
|
|
256
|
+
```
|
|
257
|
+
You have access to my Proton Mail inbox via the proton-mail-bridge tool.
|
|
258
|
+
|
|
259
|
+
Rules:
|
|
260
|
+
- Always use dryRun: true before any batch operation (batch_email_action, apply_thread_action).
|
|
261
|
+
- Before calling send_email, reply_to_email, or forward_email, summarise what you are about to send and ask me to confirm.
|
|
262
|
+
- Before calling delete_email, confirm with me — deletion is permanent.
|
|
263
|
+
- Prefer create_draft over send_email when composing from scratch.
|
|
264
|
+
- Use get_inbox_digest or get_actionable_threads as your starting point for triage sessions.
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
108
269
|
## CLI
|
|
109
270
|
|
|
110
271
|
```bash
|
|
@@ -203,23 +364,18 @@ proton-mail-bridge-client sync --folder INBOX --limit 150
|
|
|
203
364
|
Run as a background daemon — sends a system notification (macOS / Linux) whenever new mail arrives:
|
|
204
365
|
|
|
205
366
|
```bash
|
|
206
|
-
#
|
|
207
|
-
proton-mail-bridge-client notify
|
|
208
|
-
|
|
209
|
-
# Background (macOS / Linux)
|
|
210
|
-
proton-mail-bridge-client notify &
|
|
211
|
-
|
|
212
|
-
# Custom folder and idle timeout
|
|
213
|
-
proton-mail-bridge-client notify --folder INBOX --timeout 60
|
|
367
|
+
proton-mail-bridge-client notify # foreground (Ctrl+C to stop)
|
|
368
|
+
proton-mail-bridge-client notify & # background
|
|
369
|
+
proton-mail-bridge-client notify --folder INBOX --timeout 60 # custom folder and idle timeout
|
|
214
370
|
```
|
|
215
371
|
|
|
216
|
-
Each
|
|
372
|
+
Each event is also written as a JSON line to stdout:
|
|
217
373
|
|
|
218
374
|
```json
|
|
219
375
|
{"event":"new_mail","folder":"INBOX","count":2,"at":"2026-05-18T14:32:01.000Z"}
|
|
220
376
|
```
|
|
221
377
|
|
|
222
|
-
Uses IMAP IDLE — no polling
|
|
378
|
+
Uses IMAP IDLE — no polling between events. Reconnects automatically on transient errors.
|
|
223
379
|
|
|
224
380
|
### MCP tool passthrough
|
|
225
381
|
|
|
@@ -231,167 +387,86 @@ proton-mail-bridge-client tool get_connection_status --json
|
|
|
231
387
|
proton-mail-bridge-client tool search_indexed_emails --args '{"query":"invoice","limit":3}'
|
|
232
388
|
```
|
|
233
389
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
The CLI and MCP server both read the same environment variables:
|
|
237
|
-
|
|
238
|
-
```bash
|
|
239
|
-
export PROTONMAIL_USERNAME='you@proton.me'
|
|
240
|
-
export PROTONMAIL_PASSWORD='your-bridge-password'
|
|
241
|
-
export PROTONMAIL_IMAP_HOST='127.0.0.1'
|
|
242
|
-
export PROTONMAIL_IMAP_PORT='1143'
|
|
243
|
-
export PROTONMAIL_IMAP_SECURE='false'
|
|
244
|
-
export PROTONMAIL_SMTP_HOST='127.0.0.1'
|
|
245
|
-
export PROTONMAIL_SMTP_PORT='1025'
|
|
246
|
-
export PROTONMAIL_DATA_DIR="$HOME/.proton-mail-bridge-client"
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Optional secrets via file or command (avoids raw credentials in shell):
|
|
390
|
+
### Pipe and script
|
|
250
391
|
|
|
251
392
|
```bash
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
# or
|
|
255
|
-
export PROTONMAIL_USERNAME_COMMAND='pass proton/username'
|
|
256
|
-
export PROTONMAIL_PASSWORD_COMMAND='pass proton/password'
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Full runtime flags:
|
|
393
|
+
# Morning digest to a file
|
|
394
|
+
proton-mail-bridge-client digest --json > ~/morning-mail.json
|
|
260
395
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
export PROTONMAIL_ALLOW_SEND='true'
|
|
264
|
-
export PROTONMAIL_ALLOW_REMOTE_DRAFT_SYNC='true'
|
|
265
|
-
export PROTONMAIL_ALLOWED_ACTIONS='mark_read,mark_unread,star,unstar,archive,trash,restore'
|
|
266
|
-
export PROTONMAIL_CONFIRM_DESTRUCTIVE='false'
|
|
267
|
-
export PROTONMAIL_AUTO_SYNC='true'
|
|
268
|
-
export PROTONMAIL_STARTUP_SYNC='true'
|
|
269
|
-
export PROTONMAIL_SYNC_INTERVAL_MINUTES='5'
|
|
270
|
-
export PROTONMAIL_IDLE_WATCH='true'
|
|
271
|
-
export PROTONMAIL_IDLE_MAX_SECONDS='30'
|
|
272
|
-
```
|
|
396
|
+
# Pull every email from a domain
|
|
397
|
+
proton-mail-bridge-client search --from stripe.com --json | jq '.[].subject'
|
|
273
398
|
|
|
274
|
-
|
|
399
|
+
# Pipe a script's output directly into an email
|
|
400
|
+
echo "Deploy complete on $(hostname) at $(date)" \
|
|
401
|
+
| proton-mail-bridge-client send --to alerts@example.com --subject "Deploy done"
|
|
275
402
|
|
|
276
|
-
|
|
403
|
+
# Scheduled digest every weekday at 8am (cron)
|
|
404
|
+
0 8 * * 1-5 proton-mail-bridge-client digest >> ~/mail-log.txt
|
|
277
405
|
|
|
278
|
-
|
|
279
|
-
|
|
406
|
+
# Count unread in INBOX
|
|
407
|
+
proton-mail-bridge-client emails --folder INBOX --json | jq '[.[] | select(.isRead == false)] | length'
|
|
280
408
|
```
|
|
281
409
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
- check your local Bridge ports
|
|
285
|
-
- ask for your Bridge username and password
|
|
286
|
-
- build the project
|
|
287
|
-
- install a stable machine-wide runtime
|
|
288
|
-
- write the Claude Desktop MCP config entry
|
|
410
|
+
---
|
|
289
411
|
|
|
290
|
-
|
|
412
|
+
## Safety controls
|
|
291
413
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
- macOS: `~/Library/Application Support/Proton Mail Bridge Client`
|
|
295
|
-
- Linux: `~/.local/share/proton-mail-bridge-client`
|
|
296
|
-
- Windows: `%APPDATA%\Proton Mail Bridge Client`
|
|
297
|
-
|
|
298
|
-
### Updating
|
|
414
|
+
All flags work in both the MCP server and CLI:
|
|
299
415
|
|
|
300
416
|
```bash
|
|
301
|
-
|
|
302
|
-
|
|
417
|
+
PROTONMAIL_TOOL_TIER=core # expose 20 core tools instead of all 76 — saves context window
|
|
418
|
+
PROTONMAIL_READ_ONLY=true # disable all write operations
|
|
419
|
+
PROTONMAIL_ALLOW_SEND=false # disable SMTP sends only (other writes still work)
|
|
420
|
+
PROTONMAIL_CONFIRM_DESTRUCTIVE=true # require confirmed:true on send, reply, forward, delete
|
|
421
|
+
PROTONMAIL_ALLOWED_ACTIONS='mark_read,archive,trash' # per-action allowlist
|
|
303
422
|
```
|
|
304
423
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
Three credential methods are supported. Use whichever fits your setup:
|
|
424
|
+
`batch_email_action` and `apply_thread_action` both support `dryRun: true` regardless of the above flags.
|
|
308
425
|
|
|
309
|
-
|
|
426
|
+
---
|
|
310
427
|
|
|
311
|
-
|
|
312
|
-
{
|
|
313
|
-
"mcpServers": {
|
|
314
|
-
"proton-mail-bridge": {
|
|
315
|
-
"command": "node",
|
|
316
|
-
"args": ["/path/to/runtime/dist/index.js"],
|
|
317
|
-
"cwd": "/path/to/runtime",
|
|
318
|
-
"env": {
|
|
319
|
-
"PROTONMAIL_USERNAME": "you@proton.me",
|
|
320
|
-
"PROTONMAIL_PASSWORD": "your-bridge-password",
|
|
321
|
-
"PROTONMAIL_IMAP_HOST": "127.0.0.1",
|
|
322
|
-
"PROTONMAIL_IMAP_PORT": "1143",
|
|
323
|
-
"PROTONMAIL_IMAP_SECURE": "false",
|
|
324
|
-
"PROTONMAIL_SMTP_HOST": "127.0.0.1",
|
|
325
|
-
"PROTONMAIL_SMTP_PORT": "1025"
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
```
|
|
428
|
+
## Environment reference
|
|
331
429
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
"PROTONMAIL_IMAP_HOST": "127.0.0.1",
|
|
368
|
-
"PROTONMAIL_IMAP_PORT": "1143",
|
|
369
|
-
"PROTONMAIL_IMAP_SECURE": "false",
|
|
370
|
-
"PROTONMAIL_SMTP_HOST": "127.0.0.1",
|
|
371
|
-
"PROTONMAIL_SMTP_PORT": "1025"
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
430
|
+
```bash
|
|
431
|
+
# Credentials (required)
|
|
432
|
+
PROTONMAIL_USERNAME='you@proton.me'
|
|
433
|
+
PROTONMAIL_PASSWORD='your-bridge-password' # Bridge password, not Proton account password
|
|
434
|
+
PROTONMAIL_IMAP_HOST='127.0.0.1'
|
|
435
|
+
PROTONMAIL_IMAP_PORT='1143'
|
|
436
|
+
PROTONMAIL_IMAP_SECURE='false'
|
|
437
|
+
PROTONMAIL_SMTP_HOST='127.0.0.1'
|
|
438
|
+
PROTONMAIL_SMTP_PORT='1025'
|
|
439
|
+
|
|
440
|
+
# Secrets via file or command (avoids raw credentials in config)
|
|
441
|
+
PROTONMAIL_USERNAME_FILE='/path/to/user.txt'
|
|
442
|
+
PROTONMAIL_PASSWORD_FILE='/path/to/pass.txt'
|
|
443
|
+
PROTONMAIL_USERNAME_COMMAND='pass proton/username'
|
|
444
|
+
PROTONMAIL_PASSWORD_COMMAND='pass proton/password'
|
|
445
|
+
|
|
446
|
+
# Storage
|
|
447
|
+
PROTONMAIL_DATA_DIR="$HOME/.proton-mail-bridge-client"
|
|
448
|
+
|
|
449
|
+
# Tools
|
|
450
|
+
PROTONMAIL_TOOL_TIER='full' # 'core' exposes 20 essential tools (saves context window); 'full' exposes all 76
|
|
451
|
+
|
|
452
|
+
# Safety
|
|
453
|
+
PROTONMAIL_READ_ONLY='false'
|
|
454
|
+
PROTONMAIL_ALLOW_SEND='true'
|
|
455
|
+
PROTONMAIL_ALLOW_REMOTE_DRAFT_SYNC='true'
|
|
456
|
+
PROTONMAIL_ALLOWED_ACTIONS='mark_read,mark_unread,star,unstar,archive,trash,restore'
|
|
457
|
+
PROTONMAIL_CONFIRM_DESTRUCTIVE='false'
|
|
458
|
+
|
|
459
|
+
# Sync
|
|
460
|
+
PROTONMAIL_AUTO_SYNC='true'
|
|
461
|
+
PROTONMAIL_STARTUP_SYNC='true'
|
|
462
|
+
PROTONMAIL_SYNC_INTERVAL_MINUTES='5'
|
|
463
|
+
PROTONMAIL_IDLE_WATCH='true'
|
|
464
|
+
PROTONMAIL_IDLE_MAX_SECONDS='30'
|
|
376
465
|
```
|
|
377
466
|
|
|
378
|
-
|
|
467
|
+
---
|
|
379
468
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
## Trust & Safety
|
|
383
|
-
|
|
384
|
-
- Runs entirely locally — no hosted relay, no remote URL.
|
|
385
|
-
- Talks to Proton Mail only through Proton Bridge on your own machine.
|
|
386
|
-
- `PROTONMAIL_READ_ONLY=true` disables all write operations.
|
|
387
|
-
- `PROTONMAIL_ALLOW_SEND=false` disables SMTP sends without affecting other writes.
|
|
388
|
-
- `PROTONMAIL_ALLOWED_ACTIONS` controls which mailbox mutations are permitted.
|
|
389
|
-
- `PROTONMAIL_CONFIRM_DESTRUCTIVE=true` requires `confirmed: true` on `send_email`, `reply_to_email`, `forward_email`, `send_draft`, and `delete_email` — Claude will pause and ask before executing irreversible operations.
|
|
390
|
-
- `batch_email_action` and `apply_thread_action` both support `dryRun: true`.
|
|
391
|
-
- Supports `*_FILE` and `*_COMMAND` secrets so raw credentials never appear in config or shell history.
|
|
392
|
-
- System folders (INBOX, Sent, Trash, Spam, Archive, All Mail) are guarded against accidental deletion.
|
|
393
|
-
|
|
394
|
-
## Compared With Claude's Native Gmail Connector
|
|
469
|
+
## Compared with Claude's native Gmail connector
|
|
395
470
|
|
|
396
471
|
| Capability | Gmail connector | Proton Mail Bridge Client |
|
|
397
472
|
|---|---|---|
|
|
@@ -399,88 +474,99 @@ On macOS, `better-sqlite3` must be a native binary built for the current machine
|
|
|
399
474
|
| Search and read | Native Claude UX | IMAP + local index |
|
|
400
475
|
| Send email | No | Yes |
|
|
401
476
|
| Draft workflows | Better first-party UX | Full control incl. remote draft sync |
|
|
402
|
-
| Attachment content | Limited | Fetch and save |
|
|
477
|
+
| Attachment content | Limited | Fetch and save to disk |
|
|
403
478
|
| Mailbox actions | Limited | Full (star, move, archive, trash, restore, delete, batch) |
|
|
404
479
|
| Folder management | No | Yes (create, rename, delete) |
|
|
405
480
|
| CLI access | No | Full parity with MCP |
|
|
406
|
-
|
|
|
407
|
-
| Native threads/labels | Gmail-native | Reconstructed from IMAP |
|
|
481
|
+
| Privacy | Google-hosted | Proton E2E encryption, local Bridge |
|
|
408
482
|
|
|
409
|
-
|
|
483
|
+
---
|
|
410
484
|
|
|
411
|
-
|
|
485
|
+
## Tool surface
|
|
412
486
|
|
|
413
|
-
|
|
414
|
-
|
|
487
|
+
### Send
|
|
488
|
+
`send_email` · `send_test_email` · `reply_to_email` · `reply_all_email` · `forward_email`
|
|
415
489
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
- Use get_inbox_digest or get_actionable_threads as your starting point for triage sessions.
|
|
422
|
-
```
|
|
490
|
+
### Drafts
|
|
491
|
+
`create_draft` · `create_reply_draft` · `create_forward_draft` · `create_thread_reply_draft` · `list_drafts` · `list_remote_drafts` · `get_draft` · `update_draft` · `sync_draft_to_remote` · `send_draft` · `delete_draft`
|
|
492
|
+
|
|
493
|
+
### Read
|
|
494
|
+
`get_emails` · `get_email_by_id` · `count_messages` · `search_emails` · `search_indexed_emails` · `list_attachments` · `get_attachment_content` · `save_attachment` · `save_attachments`
|
|
423
495
|
|
|
424
|
-
|
|
496
|
+
### Triage
|
|
497
|
+
`get_folders` · `sync_folders` · `get_labels` · `get_threads` · `get_thread_by_id` · `get_thread_brief` · `get_actionable_threads` · `get_inbox_digest` · `get_follow_up_candidates` · `find_document_threads` · `prepare_meeting_context` · `delete_thread` · `flag_thread` · `move_thread`
|
|
425
498
|
|
|
426
|
-
|
|
499
|
+
### Actions
|
|
500
|
+
`mark_email_read` · `star_email` · `move_email` · `archive_email` · `trash_email` · `restore_email` · `delete_email` · `batch_email_action` · `apply_thread_action` · `empty_folder` · `bulk_delete` · `bulk_move` · `bulk_update_flags` · `bulk_update_labels` · `update_message_flags` · `update_message_labels`
|
|
427
501
|
|
|
428
|
-
|
|
429
|
-
|
|
502
|
+
### Folder management
|
|
503
|
+
`create_folder` · `rename_folder` · `delete_folder` · `create_label`
|
|
430
504
|
|
|
431
|
-
|
|
432
|
-
|
|
505
|
+
### Analytics
|
|
506
|
+
`get_email_stats` · `get_email_analytics` · `get_contacts` · `get_volume_trends` · `folder_stats` · `top_senders`
|
|
433
507
|
|
|
434
|
-
|
|
435
|
-
|
|
508
|
+
### Diagnostics
|
|
509
|
+
`get_connection_status` · `get_runtime_status` · `run_doctor` · `get_audit_logs` · `run_background_sync` · `wait_for_mailbox_changes` · `sync_emails` · `get_index_status` · `clear_cache` · `clear_index` · `get_logs`
|
|
436
510
|
|
|
437
|
-
|
|
438
|
-
> "I have a call with alice@example.com in an hour. Pull up our last 5 email threads and summarise the open items."
|
|
511
|
+
---
|
|
439
512
|
|
|
440
|
-
|
|
441
|
-
> "Show me my drafts, pick the oldest one, and suggest a better subject line and closing paragraph."
|
|
513
|
+
## Using it as a library
|
|
442
514
|
|
|
443
|
-
|
|
515
|
+
Beyond the CLI and MCP server, the underlying service classes are importable directly:
|
|
444
516
|
|
|
445
|
-
|
|
517
|
+
```ts
|
|
518
|
+
import { SimpleIMAPService, SMTPService } from "proton-mail-bridge-client/services";
|
|
446
519
|
|
|
447
|
-
|
|
448
|
-
|
|
520
|
+
const imapService = new SimpleIMAPService(config, logger);
|
|
521
|
+
const smtpService = new SMTPService(config);
|
|
522
|
+
```
|
|
449
523
|
|
|
450
|
-
|
|
451
|
-
|
|
524
|
+
`proton-mail-bridge-client/services` has no side effects on import — unlike the package's
|
|
525
|
+
main entry point, which also self-starts the MCP server when run directly. Also exported:
|
|
526
|
+
all shared types (`ProtonMailConfig`, `EmailSummary`, `EmailDetail`, …), `planFolderSync`,
|
|
527
|
+
`isLikelyAuthenticationError`, and `sanitizeHeader`.
|
|
452
528
|
|
|
453
|
-
|
|
454
|
-
`get_emails` · `get_email_by_id` · `search_emails` · `list_attachments` · `get_attachment_content` · `save_attachments` · `save_attachment`
|
|
529
|
+
---
|
|
455
530
|
|
|
456
|
-
|
|
457
|
-
`get_folders` · `sync_folders` · `get_labels` · `get_threads` · `get_thread_by_id` · `get_thread_brief` · `get_actionable_threads` · `get_inbox_digest` · `get_follow_up_candidates` · `find_document_threads` · `prepare_meeting_context`
|
|
531
|
+
## Operational notes
|
|
458
532
|
|
|
459
|
-
|
|
460
|
-
|
|
533
|
+
- `get_emails` and `search_emails` return a composite `emailId` — use it for all subsequent reads and actions.
|
|
534
|
+
- `search_indexed_emails` supports `from:`, `to:`, `subject:`, `label:`, `domain:` shortcuts.
|
|
535
|
+
- The local index lives at `PROTONMAIL_DATA_DIR/mail-index.sqlite`. Background sync and IMAP IDLE keep it warm.
|
|
536
|
+
- Audit logs live at `PROTONMAIL_DATA_DIR/audit.log`.
|
|
537
|
+
- Draft sync is best-effort — the local draft is always preserved even if remote sync fails.
|
|
538
|
+
- System folders (INBOX, Sent, Trash, Spam, Archive, All Mail) are guarded against accidental deletion.
|
|
461
539
|
|
|
462
|
-
|
|
463
|
-
`create_folder` · `rename_folder` · `delete_folder`
|
|
540
|
+
---
|
|
464
541
|
|
|
465
|
-
|
|
466
|
-
`get_email_stats` · `get_email_analytics` · `get_contacts` · `get_volume_trends`
|
|
542
|
+
## Troubleshooting
|
|
467
543
|
|
|
468
|
-
|
|
469
|
-
|
|
544
|
+
**"Wrong password" or connection refused**
|
|
545
|
+
Make sure you're using the **Bridge password**, not your Proton account password. Find it in the Bridge app under Account → Copy password. Bridge must be running before the MCP server or CLI can connect.
|
|
470
546
|
|
|
471
|
-
|
|
547
|
+
**macOS native module crash after update**
|
|
548
|
+
`better-sqlite3` is a native binary built for your machine. After a major Node.js upgrade or environment change, rebuild it:
|
|
549
|
+
```bash
|
|
550
|
+
proton-mail-bridge-client setup-claude-desktop
|
|
551
|
+
```
|
|
552
|
+
This reinstalls the runtime and rebuilds native modules in place.
|
|
472
553
|
|
|
473
|
-
|
|
474
|
-
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
554
|
+
**Claude can't see the connector**
|
|
555
|
+
After changing the MCP config, restart Claude Desktop fully (not just reload). Then check **`+` → Connectors → proton-mail-bridge**. If it's not there, run `proton-mail-bridge-client doctor` to validate the connection.
|
|
556
|
+
|
|
557
|
+
**Folder not found when moving email**
|
|
558
|
+
Use `Folders/Name` for real folders (e.g., `Folders/Receipts`), not just `Name`. Labels and folders share the same namespace in Proton Bridge but are structurally different.
|
|
559
|
+
|
|
560
|
+
---
|
|
479
561
|
|
|
480
562
|
## Changelog
|
|
481
563
|
|
|
482
564
|
See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
483
565
|
|
|
566
|
+
## Contributing
|
|
567
|
+
|
|
568
|
+
Bug reports and pull requests welcome: [github.com/googlarz/proton-mail-bridge-client/issues](https://github.com/googlarz/proton-mail-bridge-client/issues)
|
|
569
|
+
|
|
484
570
|
## License
|
|
485
571
|
|
|
486
572
|
MIT
|