IMAP and SMTP

Connect any IMAP mailbox with a password, find its servers, add CalDAV and CardDAV, and read Google or Microsoft over IMAP.

Any mailbox that speaks IMAP (and SMTP for sending) can be an account. Connect it with an address and password through the API or the hosted IMAP form; Google and Microsoft mailboxes can also use IMAP with their OAuth sign-in.

Connect with a password

POST /v1/imap-accounts takes the address and password. Without servers, Workwae discovers them from the address. The login is checked against the servers before anything is stored, so a created account is one that worked.

curl -X POST "https://api.workwae.com/v1/imap-accounts" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "email": "ada@example.com",
  "password": "app-password",
  "externalRef": "user_42"
}'

To name the servers yourself, pass imap and smtp:

curl -X POST "https://api.workwae.com/v1/imap-accounts" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "email": "ada@example.com",
  "password": "app-password",
  "imap": { "host": "imap.example.com", "port": 993, "security": "tls" },
  "smtp": { "host": "smtp.example.com", "port": 587, "security": "starttls" }
}'
FieldMeaning
imap, smtpOmit both to autodiscover them. Give imap alone to autodiscover only SMTP. "smtp": null makes a receive-only account.
securitytls: implicit TLS (ports 993 and 465). starttls: upgrade after connecting (143 and 587). none: plaintext, which Workwae refuses for logins.
userThe login name, per server. Defaults to the email address.
smtpPasswordWhen SMTP needs a different password than IMAP.
appendSentStore sent mail in Sent. On by default, except for servers known to file it themselves (Gmail, Microsoft).
davCalendar and contacts over CalDAV and CardDAV. See below.
ErrorMeaning
400 login_failedA server (IMAP, SMTP, CalDAV or CardDAV) refused the login; the message names which one.
400 server_not_allowedA server resolves to a private or loopback address.
400 plaintext_not_allowedA server is named with security: "none".
422 autodiscovery_failedNo servers were given and none were found for the address. Ask the user for them.

Calendar and contacts over DAV

Without dav, an IMAP account syncs mail only. With dav, it also syncs calendars and address books.

  • calendarUrl and contactsUrl may be any URL on the server, or left out to discover them from the address. null leaves that half out.
  • dav.password is a DAV password of its own, for when DAV does not log in with the IMAP password. dav.user sets the DAV login name.
  • The halves found switch calendarEnabled and contactsEnabled on, unless the account's settings name them.
  • 400 dav_discovery_failed: neither a CalDAV nor a CardDAV server was found or answered. 400 not_dav_server: a named URL is not a DAV server.

A CalDAV server without scheduling (RFC 6638) tells no attendee about a change, so Workwae mails invitations, updates, cancellations and replies from the account's SMTP server.

  • It does so only for a meeting the account organizes, and only to the attendees it has indexed or the request names.
  • Writing with notify on is refused with 400 provider_unsupported when the account has no SMTP server.
  • A mail that fails after the event was written is logged, and the write stands.

Find the servers

To prefill your own settings form, look the servers up first. 422 autodiscovery_failed means nothing was found: ask the user for the servers.

curl "https://api.workwae.com/v1/autoconfig?email=ada%40example.com" \
  -H "Authorization: Bearer $WORKWAE_API_KEY"
Response
{
  "source": "autoconfig",
  "imap": { "host": "imap.example.com", "port": 993, "security": "tls", "user": "ada@example.com" },
  "smtp": { "host": "smtp.example.com", "port": 465, "security": "tls", "user": "ada@example.com" },
  "oauth": null,
  "dav": {
    "source": "well-known",
    "calendarUrl": "https://dav.example.com/",
    "contactsUrl": "https://dav.example.com/"
  }
}
  • source says where the settings came from: provider, autoconfig, ispdb, srv or mx.
  • oauth names the provider (google or microsoft) whose sign-in reaches this mailbox. Prefer an OAuth connect flow over a password for it.
  • dav holds the CalDAV and CardDAV URLs when a source names them, or null. Pass them on as the account's dav; creating the account resolves them to the user's calendars and address books.

Change servers or password

PATCH /v1/accounts/{accountId}/imap-settings replaces the fields it is given and checks the result like a new account. An account in reauth_required (after a password change, for example) becomes active again.

curl -X PATCH "https://api.workwae.com/v1/accounts/$ACCOUNT_ID/imap-settings" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "password": "new-app-password" }'

A new server needs the password again

A stored password is never sent to a new server or tried for another login. Without the password, the change answers 400 password_required.

  • Changing the IMAP host, port, security or user needs password.
  • Changing the SMTP ones needs smtpPassword, or password when SMTP uses the IMAP password.
  • Switching SMTP from its own password to the IMAP one (smtpPassword: null) needs password.
  • Adding DAV settings, or changing their URLs, user or password source, needs the password DAV logs in with: dav.password, or password when DAV uses the IMAP one.
  • dav: null removes calendar and contacts. A DAV half the account did not have before switches calendarEnabled or contactsEnabled on, unless the account's settings already name it (an earlier opt-out stays).
  • dav fields left out keep their stored values, or are discovered for an account without DAV settings.
  • An account that signs in with OAuth always uses its provider's servers: changing them answers 400 oauth_servers_fixed, and a password answers 400 password_unsupported.

IMAP with OAuth (XOAUTH2)

Google and Microsoft mailboxes can be read over IMAP and SMTP, authenticated with the OAuth grant instead of a password. Pass "mailAccess": "imap" in the options of a hosted session or a headless OAuth start; the sign-in creates an IMAP account.

  • The grant carries mail scopes only: the account has no calendar and no contacts.
  • Google needs your own Google OAuth app (oauthAppId, or oauthAppIds.google on a session). Workwae's app connects Gmail through the Gmail API only, and refuses an IMAP start with google_imap_requires_own_app.
  • Microsoft works with either app.
  • A reconnect of such an account keeps its mail access.
curl -X POST "https://api.workwae.com/v1/oauth-authorizations" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "provider": "google",
  "oauthAppId": "'"$GOOGLE_APP_ID"'",
  "redirectUri": "https://app.example.com/mail/connected",
  "options": { "mailAccess": "imap" }
}'

The hosted IMAP form

Include imap in a hosted session's providers and the connect page offers an IMAP/SMTP form next to the Google and Microsoft buttons. It looks up the servers, checks the login and creates the account, then sends the browser to your redirect URI like the OAuth flows.

curl -X POST "https://api.workwae.com/v1/connect-sessions" \
  -H "Authorization: Bearer $WORKWAE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "redirectUri": "https://app.example.com/mail/connected",
  "providers": ["imap"]
}'
  • The page calls the API with the session token only, never your API key. Each session is rate limited on its own.
  • A session created with the accountId of a password IMAP account shows only the IMAP form, so the user can enter a new password. Its CalDAV and CardDAV login is checked again too; when DAV has a password of its own, the form takes a new one.

On this page