
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
Email infrastructure for AI agents: MCP server and CLI for VaEmail. Send email, authenticate domains, track delivery, diagnose deliverability.
MCP server and CLI for VaEmail. Give an agent the ability to send email, authenticate a sending domain, track delivery and diagnose deliverability — without a human reading a dashboard in between.
European infrastructure: servers in Germany, sending through Amazon SES Europe.
# Claude Code
claude mcp add vaemail --env VAEMAIL_API_KEY=swm_your_key -- npx -y vaemail mcp
# Any MCP client
npx -y vaemail mcp
Or as a config block:
{
"mcpServers": {
"vaemail": {
"command": "npx",
"args": ["-y", "vaemail", "mcp"],
"env": { "VAEMAIL_API_KEY": "swm_your_key" }
}
}
}
Check everything is wired up:
npx vaemail init
| Tool | What it does |
|---|---|
vaemail_envoyer_newsletter | Newsletter to a contact list, in French: resolves the list by name, creates, tests, schedules or sends. No "quand" = draft. |
vaemail_ou_en_est_ma_campagne | Where a campaign stands, in plain sentences: scheduled, sending, sent, opens, clicks. |
vaemail_qui_est_abonne | Lists by folder with subscriber counts, or the lists and status of one address. |
vaemail_importer_contacts | Adds contacts to a list (created if missing). Never re-subscribes an unsubscribed address. |
vaemail_capabilities | What the service supports. No API key needed. |
vaemail_send_email | Queue a transactional email, return its id. |
vaemail_validate_email | Dry run: would this send go out, and what would block it. |
vaemail_get_message | Delivery status and every event for one message. |
vaemail_list_messages | Recent messages, filtered by status, tag or recipient. |
vaemail_list_domains | Sending domains with live SPF, DKIM and DMARC state. |
vaemail_create_domain | Declare a domain, return the DNS records to publish. |
vaemail_verify_domain | Re-read the DNS and report what is authenticated. |
vaemail_dns_requirements | The records a declared domain still needs. |
vaemail_diagnose_deliverability | Why mail is landing badly, with the actions that fix it. |
vaemail_list_bounces | Addresses excluded from sending, and why. |
vaemail_get_usage | Quota, daily cap on the key, what is left. |
vaemail_get_audit_log | What this key has done, to report it accurately. |
An agent fails differently from a person. It retries, it does not read a dashboard, and it reports success from a 200. The API is shaped around that:
vaemail_send_email returns 202 and an
id. Only vaemail_get_message says what became of it. The tool descriptions
say so, so an agent does not announce a delivery it cannot know about.idempotency_key and a repeat call replays
the first response for 24 hours instead of sending twice.code, whether it is
retryable, and the corrective action with the endpoint that performs it.publishable: false,
because publishing it would break the domain's authentication.vaemail init # check config, print the MCP snippet
vaemail capabilities # what the service can do (no key needed)
vaemail send --to a@b.fr --subject Hi --html '<p>Hello</p>'
vaemail status 42 # delivery status of a message
vaemail domains:add exemple.fr # declare a domain, print DNS records
vaemail doctor # why is my email not arriving?
vaemail usage # quota and remaining allowance
vaemail mcp # run the MCP server on stdio
Add --json to any command for machine-readable output.
The same client the MCP server and the CLI run on is exported, so an application can call VaEmail directly. No dependencies.
import { VaEmail } from 'vaemail';
const client = new VaEmail({ apiKey: process.env.VAEMAIL_API_KEY });
await client.send(
{
to: 'customer@example.com',
subject: 'Your order is on its way',
html: '<p>Tracking number: 1Z999</p>',
},
'order-4711', // idempotency key: safe to replay for 24 hours
);
Errors carry what to do next, not just a status code:
try {
await client.send({ to: 'customer@example.com' });
} catch (error) {
error.code; // DOMAIN_NOT_VERIFIED
error.retryable; // false
error.pourAgent(); // reason, corrective action, whether to retry
}
Also: capabilities(), health(), validate(), getMessage(),
listMessages(), listDomains(), addDomain(), verifyDomain(),
dnsRecords(), diagnoseDeliverability(), listSuppressions(), usage(),
auditLogs().
A Python SDK with the same surface is available: pip install vaemail
(https://github.com/vaemail/vaemail-python).
| Variable | Meaning |
|---|---|
VAEMAIL_API_KEY | Account API key. Created from the dashboard, under « Clés API ». |
VAEMAIL_BASE_URL | API base URL. Defaults to https://app.vaemail.fr. |
npx skills add vaemail/skills, source https://github.com/vaemail/skillsio.github.vaemail/vaemail (see server.json)None. Node 18+ for the built-in fetch, and nothing else — a package an agent
installs on its own should not pull a dependency tree behind it.
MIT
FAQs
Email infrastructure for AI agents: MCP server and CLI for VaEmail. Send email, authenticate domains, track delivery, diagnose deliverability.
The npm package vaemail receives a total of 26 weekly downloads. As such, vaemail popularity was classified as not popular.
We found that vaemail demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.