Skip to content
Docs
opendesk.shOpen app

Mailboxes

Create, test and connect mailboxes, and post raw inbound email.

Mailboxes are settings: an admin user, or an API key with settings:read and settings:write.

Method Path Description
GET, POST /v1/mailboxes List or create mailboxes
GET, PATCH, DELETE /v1/mailboxes/{id}
POST /v1/mailboxes/{id}/test Test inbound and outbound
POST /v1/mailboxes/oauth/{provider}/start Start a Google or Microsoft connection
GET /v1/mailboxes/oauth/{provider}/callback OAuth redirect target
POST /v1/inbound/email Receive a raw email (forwarding)
type Mailbox = {
id: string;
name: string;
email: string;
display_name: string;
inbound_kind: "forwarding" | "imap" | "google" | "microsoft";
outbound_kind: "smtp" | "google" | "microsoft" | "system";
forwarding_address: string;
config: {
imap_host?: string;
imap_port?: number;
imap_username?: string;
imap_tls?: "tls" | "starttls" | "none";
smtp_host?: string;
smtp_port?: number;
smtp_username?: string;
smtp_tls?: "tls" | "starttls" | "none";
oauth_email?: string;
};
team_id: string | null;
signature_html: string;
auto_reply_enabled: boolean;
auto_reply_subject: string;
auto_reply_html: string;
status: "active" | "error" | "disabled";
last_error: string;
last_synced_at: string | null;
created_at: string;
trusted_form_senders: string[];
};

Passwords and tokens are write-only: they are accepted on create and update, encrypted, and never returned.

Website contact forms usually send From an address of the site with the visitor in Reply-To. List those addresses in trusted_form_senders (an exact address, or @domain for every address at that domain, at most 50) and a form message that passed DMARC is from the visitor: the visitor becomes the contact and replies go to them. Mail from a listed address that did not pass DMARC is handled like any other mail.

Terminal window
curl -X PATCH https://api.opendesk.sh/v1/mailboxes/0192f0c4-... \
-H "Authorization: Bearer od_live_..." \
-H "Content-Type: application/json" \
-d '{ "trusted_form_senders": ["website@example.com"] }'

The list replaces the stored one. A domain of a public email provider (such as @gmail.com) is refused; list the form’s exact address instead.

Terminal window
curl https://api.opendesk.sh/v1/mailboxes \
-H "Authorization: Bearer od_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Support",
"email": "support@example.com",
"display_name": "Example Support",
"inbound_kind": "imap",
"outbound_kind": "smtp",
"config": {
"imap_host": "imap.example.com", "imap_port": 993, "imap_username": "support@example.com", "imap_tls": "tls",
"smtp_host": "smtp.example.com", "smtp_port": 587, "smtp_username": "support@example.com", "smtp_tls": "starttls"
},
"password": "imap-app-password",
"smtp_password": "smtp-app-password"
}'

For forwarding, set "inbound_kind": "forwarding" and read forwarding_address from the response.

Terminal window
curl -X POST https://api.opendesk.sh/v1/mailboxes/0192f0c4-.../test -H "Authorization: Bearer od_live_..."
{ "inbound": { "ok": true, "error": "" }, "outbound": { "ok": false, "error": "535 authentication failed" } }

POST /v1/mailboxes/oauth/{provider}/start with { name, email?, mailbox_id? } returns { url }. Send the user’s browser to that URL. After consent, the provider redirects to the callback, which redirects to APP_URL/settings/mailboxes?connected=<id>. Pass mailbox_id to reconnect an existing mailbox. provider is google or microsoft.

POST /v1/inbound/email?to=<recipient> accepts a raw RFC 822 message as the body and returns 202. It requires the OD-Inbound-Secret header to match the server’s INBOUND_SECRET. This is what the Cloudflare Email Worker calls; self-hosters can call it from their own mail pipeline. See Email setup.

Terminal window
curl "https://desk.example.com/v1/inbound/email?to=acme-x7k2@in.example.com" \
-H "OD-Inbound-Secret: $INBOUND_SECRET" \
-H "Content-Type: message/rfc822" \
--data-binary @message.eml

mailbox.created, mailbox.updated, mailbox.deleted.

Edit this page on GitHub