Send email

Your VM can send plain-text emails.

Request

curl -X POST http://169.254.169.254/gateway/email/send \
  -H "Content-Type: application/json" \
  -d '{
    "to": "odysseus@example.com",
    "subject": "Build Complete",
    "body": "Your build finished successfully!"
  }'

Required fields: to, subject, body Optional fields: reply_to, in_reply_to, references, attachments

Sending is rate-limited.

Attachments

Pass an attachments array. Each entry needs a filename and base64-encoded content; content_type is optional.

curl -X POST http://169.254.169.254/gateway/email/send \
  -H "Content-Type: application/json" \
  -d '{
    "to": "odysseus@example.com",
    "subject": "Report",
    "body": "Latest numbers attached.",
    "attachments": [
      {
        "filename": "report.csv",
        "content": "'"$(base64 -w0 report.csv)"'"
      }
    ]
  }'

Attachment count and size are limited.

Allowed recipients

To prevent spam, to must be one of:

  • you
  • a member of your exe.dev team
  • someone that has logged into your private-but-shared VM using exe.dev auth
  • someone who has emailed your VM (see below)

Replying to people who email your VM

If your VM receives email, it may reply to people who email it. By default the permission is scoped to the thread: set in_reply_to (or references) to the Message-ID of a message the sender sent your VM within the last 30 days. Replies sent this way carry a short footer telling the recipient how to widen or revoke the permission (every message your VM sends a correspondent carries at least the unsubscribe instruction):

  • they can email your VM with subject subscribe, after which your VM may email them directly (no in_reply_to needed)
  • they can email your VM with subject unsubscribe, after which your VM cannot email them at all — this outranks every other permission, including your own and your team's, and only another subscribe from that same address lifts it

The subject must be exactly the command word; Re: subscribe does not count, so that hitting Reply can never subscribe someone by accident.

To prevent spoofed or replayed mail from opening this door, the inbound email must carry a valid DKIM signature that is aligned with its From domain and covers a To/Cc header naming your VM (nearly all real mail providers do this). The subject and Message-ID must be signed too, or they are ignored. Mail that can't be verified is still delivered to your VM, but does not make its sender replyable; the send endpoint's error message says why a given address isn't sendable.

Reply permissions are cleared when you run share receive-email <vm> off, when the VM is deleted, and when it changes owner. An unsubscribe outlives the off/on cycle and a change of owner: neither lets your VM mail someone who asked it to stop. Whether your VM may email someone is that person's call, so they are also the only one who can reverse it.

While inbound email is off, your VM cannot email correspondents at all — their unsubscribe reply would have nowhere to land.

You can also restrict who your VM may email at all:

ssh exe.dev share receive-email <vm> --reply-policy=<policy>

where <policy> is all (default: owner, team, share recipients, and correspondents), known (no correspondents), owner, or none.

Response

{"success": true}

or

{"error": "error message"}