Atlas / MCP servers / n24q02m / Better Email

Better EmailCAUTION

mcp/n24q02m/better-email

IMAP/SMTP email for AI agents -- read, send, organize folders, and manage attachments across multiple accounts, with auto-discovery.

Verdict
CAUTION
Grade
C
Trust score
76 /100
Exposed tools
4 3r · 1w · 0d
Transport
stdio · streamable-http
License
Apache-2.0
Stars
33
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

ARCHIVED 2026-09-13 — This repository is no longer maintained. Use IMAP/SMTP or your mail provider's API instead of this MCP server. Existing installations keep working but receive no updates or support.

mcp-name: io.github.n24q02m/better-email-mcp

IMAP/SMTP email for AI agents -- read, send, organize folders, and manage attachments across multiple accounts, with auto-discovery.

[](https://mcp.n24q02m.com/get-started/modes-overview/) [](https://github.com/n24q02m/better-email-mcp/actions/workflows/ci.yml) [](https://codecov.io/gh/n24q02m/better-email-mcp) [](https://www.npmjs.com/package/@n24q02m/better-email-mcp) [](https://hub.docker.com/r/n24q02m/better-email-mcp) [](LICENSE)

[](#) [](#) [](#) [](https://github.com/python-semantic-release/python-semantic-release) [](https://developer.mend.io/)

Read from source at commit 70586e7895a9OBSERVED · 2026-10-08
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (npm)
claude mcp add better-email-mcp --env EMAIL_CREDENTIALS=${EMAIL_CREDENTIALS} --env EMAIL_CREDENTIALS=${EMAIL_CREDENTIALS} -- npx -y @n24q02m/[email protected]
claude-code (oci)
claude mcp add better-email-mcp:latest --env EMAIL_CREDENTIALS=${EMAIL_CREDENTIALS} --env EMAIL_CREDENTIALS=${EMAIL_CREDENTIALS} -- docker run -i --rm docker.io/n24q02m/better-email-mcp:latest:None
03

Exposed tools (4)

3 read · 1 write · 0 destructive.

ToolRiskDescription
config__open_relayreadOpen the relay configuration form for better-email-mcp in the user browser. Returns the relay URL, whether the browser launched, and the current credential state.
foldersreadList mailbox folders or read targeted mailbox status metadata.\n\nActions (required params -> optional):\n- list (-> account): folder names, paths, and flags for one or all accounts\n- status (account, folder): IMAP STATUS messages, unseen, and uid_next for exactly one mailbox
helpreadGet full documentation for a tool. Use when compressed descriptions are insufficient.
messageswriteSearch, read, manage, compose, and send email messages.\n\nActions (required params -> optional):\n- search (-> account, query=
04

Trust audit

CAUTIONgrade C · trust 76/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (2 observation(s))
Network
declared (5 observation(s))
Shell
declared (3 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (25)

MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/cf_full_flow.py:555
print("TOKEN OK len=", len(token), "sub=", _sub_of(token))
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/cf_full_flow.py:631
print("AUTH-ONLY: replaying saved token for sub=", _sub_of(token), "(no re-save)")
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
scripts/cf_full_flow.py:649
print("TOKEN OK len=", len(token), "sub=", _sub_of(token))
LOWInventory / provenance · inv.hidden_file · CWE-1104
.coderabbit.yaml
.coderabbit.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.gitguardian.yaml
.gitguardian.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.infisical.json
.infisical.json
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.mise.toml
.mise.toml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
.pre-commit-config.yaml
.pre-commit-config.yaml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/composite/config.test.ts:2
import { subjectContext } from '../../auth/subject-context.js'
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/composite/config.test.ts:6
vi.mock('../../credential-state.js', () => ({
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/composite/config.test.ts:25
import { getSetupUrl, getState, resetState, resolveCredentialState } from '../../credential-state.js'
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/composite/config.ts:13
import { currentSub } from '../../auth/subject-context.js'
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
src/tools/composite/config.ts:14
import type { CredentialState } from '../../credential-state.js'
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src/tools/composite/config.test.ts:189
mockGetSetupUrl.mockReturnValue('http://127.0.0.1:8080/authorize')
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src/tools/composite/config.test.ts:196
setup_url: 'http://127.0.0.1:8080/authorize'
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src/tools/registry-open-relay.test.ts:8
url: 'http://127.0.0.1:51234/authorize?session=abc',
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
src/transports/http.test.ts:76
expect(resolveSetupBaseUrl(undefined, '127.0.0.1', 3000)).toBe('http://127.0.0.1:3000')
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
tests/e2e.test.ts:148
const HTTP_E2E_URL = `http://127.0.0.1:${HTTP_E2E_PORT}`
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@modelcontextprotocol/sdk, html-to-text, imapflow, mailparser, marked, nodemailer, sanitize-html, @biomejs/biome
Why it matters. 20 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
README.md:81
- **4 composite tools** with 23 actions (plus `help` + `config__open_relay`) -- search, read, send, reply, forward, organize, and credential setup in single calls
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.credential_read · CWE-94, CWE-1427
src/docs/config.md:6
This tool allows you to check the status of your email credentials, return the setup URL, reset your configuration, signal completion of external setup, and manage runtime caches. In HTTP mode the cre
Why it matters. asks the agent to read credentials
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CONTRIBUTING.md:55
export EMAIL_CREDENTIALS="[email protected]:your-app-password"
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:12
[![codecov](https://codecov.io/gh/n24q02m/better-email-mcp/graph/badge.svg?token=O2GWBWCZGF)](https://codecov.io/gh/n24q02m/better-email-mcp)
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:125
| `better-email-mcp` | Start the MCP server over **stdio** (default). Reads credentials from `EMAIL_CREDENTIALS`, or from `EMAIL_USER` + `EMAIL_APP_PASSWORD` |
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:132
EMAIL_CREDENTIALS="[email protected]:app-password" npx @n24q02m/better-email-mcp
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha 70586e7895a9full audit observations/trust-audit/mcp-server/n24q02m__better-email.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-0870586e7895a9CAUTIONC76first audit
06

Questions

What is the Better Email MCP server?

IMAP/SMTP email for AI agents -- read, send, organize folders, and manage attachments across multiple accounts, with auto-discovery.

What tools does Better Email expose?

4 in total: 3 read-only, 1 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.

Is Better Email safe to connect to an agent?

With care. The audit graded it C (76/100) and found 25 things worth knowing before you trust this server, listed below with the exact line each was found on.

What credentials does Better Email need?

It reads CF_EMAIL_CREDENTIALS, CLOUDFLARE_API_TOKEN, CREDENTIAL_SECRET, EMAIL_APP_PASSWORD, EMAIL_CREDENTIALS, MCP_AUTH_DISABLE and MCP_RELAY_PASSWORD from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Better Email run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as @n24q02m/better-email-mcp at 1.41.5.

How current is this page?

The grade is for one exact copy of the source (70586e7895a9), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement