Email mailboxes
A mailbox connection lets workflows, compositions and agents work in your own inbox: list and search messages, read one with its attachments, mark messages read, watch a folder for new mail, and send from your address once a person has approved the exact message. Each mailbox is its own org-scoped connection, so an organization can connect as many as it needs.
There are two kinds, because the providers sign in differently:
| Connection | Providers | How it signs in | Provider key |
|---|---|---|---|
| Mailbox (IMAP/SMTP) | Gmail and Google Workspace, iCloud Mail, Fastmail, Yahoo Mail, or any other IMAP/SMTP server | An app password you create in the mail account | email |
| Microsoft 365 / Outlook | Microsoft 365 work or school accounts, and personal Outlook.com / Hotmail / Live accounts | Sign in with Microsoft (OAuth, Microsoft Graph). No password is stored | microsoft_mail |
Both kinds run the same email.* workflows. You name the mailbox in every run by its connection_uuid. There is no default mailbox.
Connect an IMAP/SMTP mailbox
In the console, open Connections, go to the Email category and choose Mailbox (IMAP/SMTP). Pick the provider, enter the address and the app password, select Test connection, then Connect.
An app password is a separate password your provider issues for one app. You can revoke it without changing your real password, and revoking it disconnects the mailbox. Never enter your account password.
| Provider | Before you start | Servers (filled in for you) |
|---|---|---|
| Gmail / Google Workspace | Turn on 2-Step Verification, then create an app password at myaccount.google.com/apppasswords. If your Gmail settings still show an IMAP switch, make sure IMAP is on | imap.gmail.com:993, smtp.gmail.com:465 (SSL) |
| iCloud Mail | Two-factor authentication on the Apple Account and an @icloud.com, @me.com or @mac.com address. Create an app-specific password at account.apple.com under Sign-In and Security → App-Specific Passwords | imap.mail.me.com:993, smtp.mail.me.com:587 (STARTTLS) |
| Fastmail | Settings → Privacy & Security → App passwords, with access to Mail (IMAP/POP/SMTP) | imap.fastmail.com:993, smtp.fastmail.com:465 (SSL) |
| Yahoo Mail | Account security → Generate app password (Yahoo may ask you to turn on 2-step verification first) | imap.mail.yahoo.com:993, smtp.mail.yahoo.com:465 (SSL) |
| Other | The IMAP and SMTP settings your provider publishes, and an app password when it offers one | You enter them |
For Other, IMAP must use port 993 (TLS) and SMTP must use 465 (SSL) or 587 (STARTTLS). Hosts must be public mail servers: names that resolve to loopback, private, link-local, multicast or reserved addresses are refused on every connect. Set Login username only when the server does not log in with the email address.
Test connection logs in to IMAP and to SMTP and never sends a message. Connect runs the same test and saves only if it passes.
From an assistant or the API
The same flow is connection.setup with provider_type email:
| Field | Required | Notes |
|---|---|---|
mail_preset | yes | gmail, icloud, fastmail, yahoo or custom |
username | yes | The mailbox login, normally the address |
api_token | yes | The app password. Stored encrypted |
mailbox | no | The mailbox address. Defaults to username |
from_name | no | Display name for the From header |
connection_name | no | Defaults to the mailbox address |
imap_host, imap_port, smtp_host, smtp_port, smtp_security | custom only | Ignored for the named presets. smtp_security is ssl or starttls |
Pass dry_run: true to test without saving. get_workflow_prerequisites("connection.setup", variant="email") returns the full per-provider guide.
Connect a Microsoft 365 or Outlook.com mailbox
Microsoft retired password sign-in for IMAP and SMTP, so Microsoft mailboxes do not work as IMAP/SMTP connections. Use Microsoft 365 / Outlook instead:
- In Connections → Email, choose Microsoft 365 / Outlook and select Sign in with Microsoft.
- Microsoft always shows the account picker, so one person can connect several mailboxes. Pick the account.
- Consent to the permissions below. You return to the console and the connection is saved, named after the mailbox address.
Orkestia asks for these delegated Microsoft Graph permissions, and only these:
| Permission | Why |
|---|---|
openid, email, User.Read | Sign you in and read your profile, which gives the mailbox address the connection is named after |
offline_access | Keep access without asking you to sign in again on every run |
Mail.ReadWrite | Read messages and folders, and mark messages read or unread |
Mail.Send | Send mail as you, only after a person approves the message (see Sending) |
You never paste a client ID, secret or token. Orkestia keeps the access and refresh tokens encrypted on the connection and refreshes them on its own.
Over the API this is connection.oauth-start then connection.oauth-exchange with provider_type microsoft_mail and the redirect URI https://app.orkestia.dev/connections/microsoft_mail/callback. get_workflow_prerequisites("connection.setup", variant="microsoft_mail") returns the guide.
Workflows
Every workflow takes connection_uuid (the mailbox) and refuses any connection that is not a mailbox of your organization. None of the read workflows mark anything read.
| Workflow | What it does | Main inputs |
|---|---|---|
email.mailbox.verify | Re-tests the connection without sending anything. Returns the mailbox address, the inbox message count, and (IMAP/SMTP) whether each side passed | — |
email.folder.list | Lists folders with their id, name, special use and, on Microsoft, total and unread counts | — |
email.message.list | Message summaries of a folder, newest first, with a cursor for the next page | folder (default INBOX), unread_only, since, limit, cursor |
email.message.search | Free-text search over headers and body | query, folder, limit |
email.message.get | One message: headers, text and HTML bodies, attachments, and any meeting invite it carries | message_id, folder, body_max_chars, include_html, storage_connection_uuid + bucket, key_prefix |
email.message.mark-read | Marks messages read, or unread with read: false | message_ids or message_id, read |
email.inbox.poll | The next batch of new messages since a cursor, for a schedule | folder, cursor, limit, since |
email.message.send-with-approval | Prepares a message and asks a person to approve it. Does not send | actor_uuid, to, subject, text or html, and the optional fields below |
email.message.send | Sends the message an approved review holds | approval_envelope_uuid, save_to_sent |
A message summary is {id, internet_message_id, folder, from, to, cc, subject, date, received_at, is_read, has_attachments, size_bytes, snippet, in_reply_to}. Pass its id to get or mark-read; both also accept an RFC Message-ID such as <abc@example.com>. Over IMAP, snippet is empty and folder counts are not reported.
Search takes plain words, not IMAP or Microsoft query syntax. Over IMAP it searches INBOX unless you name a folder; on Microsoft it searches the whole mailbox when folder is omitted.
Attachments go to your bucket
email.message.get never puts attachment bytes in the run. Give it a storage connection and a bucket and it copies each attachment there, returning a storage_object_uuid, bucket and key per file. Without a storage target you get the metadata only (file name, type, size). See object storage for the storage.* side.
When a message contains a meeting invite (a calendar part, an .ics attachment or an Outlook meeting request), get also returns it parsed as invite: title, start and end, time zone, organizer, attendees, location and meeting link.
Watching for new mail
email.inbox.poll is a bounded, read-only batch built to be fired by schedule.*. It returns next_cursor. Store it and pass it back on the next poll. On the first run, with no cursor, it starts from now and returns nothing unless you give since. has_more: true means more new mail is waiting; cursor_reset: true means the stored cursor no longer applied and was re-anchored. message_ids gives you idempotency keys, so a message seen twice can be skipped.
Sending needs a human approval
No workflow sends mail on the say-so of a script or an agent alone. Sending takes two runs:
email.message.send-with-approvalvalidates the message and opens a review in the Staff inbox of the actor you name inactor_uuid. It returnsapproval_envelope_uuidandstatus: review_requested. Nothing is sent yet.- A person reviews the exact message (recipients, subject, body, attachments, mailbox) and approves it.
email.message.sendwith the sameconnection_uuidand thatapproval_envelope_uuidsends exactly the reviewed message. It takes no recipients, subject or body of its own, refuses an envelope approved for a different mailbox, and sends once: calling it again returns the first result withdeduped: true.
Optional fields on the request: cc, bcc, reply_to, from_name, attachment_storage_object_uuids (storage objects of your organization), reply_to_message_id (threads the message as a reply), review_title, review_reason, and connector_uuid to notify an inbox connector.
On IMAP/SMTP mailboxes, save_to_sent (default on) files a copy in the Sent folder. Gmail files its own copy, so Orkestia skips it there.
Limits
| What | Limit |
|---|---|
| Messages per list, search or poll | 25 by default, up to 100 |
| Messages per mark-read call | 100 |
Body returned by get | 100,000 characters per part by default, up to 1,000,000 |
| Whole message read over IMAP | 25 MB. Larger messages are refused |
| Attachments copied per message | 20, each up to 25 MB |
| Recipients per message (to + cc + bcc) | 50 |
| Subject | 998 characters |
| Outgoing attachments | 10 files, 20 MB in total. 3 MB in total on Microsoft mailboxes |
Security and what is stored
- One credential per mailbox, encrypted. An IMAP/SMTP connection stores the address, the provider preset or server settings, and the app password (encrypted). A Microsoft connection stores the address, the account kind (work or personal) and the access and refresh tokens (encrypted). Workflow inputs never carry the credential.
- TLS only. IMAP on 993, SMTP on 465 or 587 with STARTTLS. Server addresses are checked on every connect.
- Orkestia does not copy your mailbox. A run reads what it asked for and returns it as that run's output, within the caps above. Attachments only leave the mailbox when you name a bucket in your own storage.
- Revoke at the source. Revoke the app password in the mail account, or remove Orkestia from the Microsoft account, and the next run fails. Deleting the connection in the console removes it from Orkestia.
Managing a mailbox connection
- Rotate an app password: edit the connection, paste a new app password made in the same mail account, then revoke the old one there.
- Microsoft grant expired or revoked: edit the connection and select Sign in with Microsoft again.
- Check it still works: run
email.mailbox.verify.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| IMAP login failure on Gmail / Workspace | IMAP off, or a Workspace policy blocks app passwords | Turn IMAP on, or ask the Workspace administrator |
| App passwords missing in the Google Account | 2-Step Verification off, security-key-only policy, or Advanced Protection | Turn on 2-Step Verification, or ask the administrator |
| iCloud mailbox stopped working | The Apple Account password changed | Make a new app-specific password and rotate it in |
| Outlook.com or Microsoft 365 address rejected as IMAP/SMTP | Microsoft retired password sign-in | Connect it as Microsoft 365 / Outlook |
| "Need admin approval" at Microsoft sign-in | The tenant blocks user consent | A Microsoft 365 administrator grants consent to the Orkestia app |
| Custom server refused | Port other than 993 / 465 / 587, or the host resolves to a private address | Use the provider's public TLS endpoints |
| Send fails on a Microsoft mailbox with attachments | Over the 3 MB total | Send fewer or smaller files, or share a link instead |
