Tickets by email
Turn inbound support email into tickets, and replies into comments.
Settings → Email intake
Turns inbound support email into tickets, and customers' replies into comments on those tickets. Connect your mailboxes, keep posting from your own script to the intake URL, or both. Routing rules and priority classification apply to every way in.
Choose a way in
- Microsoft 365: sign in with Microsoft. We read new mail every minute and send replies from that mailbox. Best for Outlook / Exchange Online.
- Google Workspace / Gmail: sign in with Google. Same as Microsoft: we read the inbox (or a label) and reply from the mailbox.
- Other provider (IMAP): Zoho, Fastmail, Yahoo, iCloud, your web host's mail. You give us the server, a username and an app password, and replies go out over its SMTP.
- Forwarding address: no sign-in at all. We give you an address, and you forward a copy of your mail to it. Works with any provider, including ones where you can't create an app password.
- Intake URL (script): the original method. Your own script or flow posts each email as JSON. It stays exactly as it was; see the last sections.
Add as many mailboxes as you use (support@, billing@, it-help@), each with its own default project and reporter. Click Add mailbox on this page. If an option is greyed out, your platform admin hasn't switched it on for this deployment yet.
Connect a mailbox
- Add mailbox → Microsoft 365. Pick the default project and the member new tickets are filed by, and choose whether replies go out from this mailbox and whether processed mail is marked as read.
- Click Sign in with Microsoft and sign in as the mailbox you want to connect, e.g. support@yourcompany.com. For a shared mailbox, sign in with an account that has Full Access and Send As on it.
- Approve the permissions. You come back here, and new mail starts arriving within a minute. Mail already in the inbox is not imported.
It reads the Inbox, or a folder you name in Manage (at the top level or directly under Inbox) — so an Outlook rule can file just the help-desk mail there. Replies are sent as replies to the customer's own message, so they thread in their mail client.
What happens to each email
- A reply to an existing ticket (it answers one of our emails, or has the ticket key like
[SUP-12]in the subject) becomes a comment on that ticket, not a new one. This only happens when it comes from that ticket's customer or reporter. Anyone else quoting the key gets a new ticket instead. - Anything else becomes a new ticket. Its project comes from Routing rules, checked in this order: sender email → sender domain → Received at (the address it was sent to) → the mailbox's default project. Its priority comes from the keywords under Priority classification.
- Skipped, never ticketed (mailboxes only): out-of-office and other automatic replies, bounces, bulk and mailing-list mail, and our own outgoing replies. They show as
SKIPPEDwith the reason in Recent activity. - Unverified sender (mailboxes only): mail that failed its domain's DMARC check (the From address may be forged) still becomes a ticket, marked
FLAGGED. It never joins an existing ticket, and nothing is emailed to that address until an agent clicks Mark sender verified on the ticket. Most are genuine customers whose domain is misconfigured. - Quoted history ("On Tue, … wrote:" and the lines below it) is trimmed from replies that come through a mailbox, so comments show only the new answer.
- The same email delivered twice to one mailbox (a retry, a re-sync) is only taken once. An email sent to two of your connected mailboxes is two separate deliveries and makes two tickets. If both addresses land in the same inbox, connect that inbox once and use Received at rules to tell them apart.
Mailbox status
- Connected: checked every minute (forwarding: whenever mail arrives). The row shows the last check and how many emails came in today. Check now in Manage reads it immediately.
- Needs reconnect: the sign-in stopped working (password changed, access removed, Google's 7-day test limit). Everyone who can manage email intake (owners and admins by default) gets a notification. Open Manage → Reconnect (or enter a new app password for IMAP). No mail is lost: it's read from where it left off.
- Error: a temporary problem (server down, timeout). It retries every minute by itself.
- Paused: nothing is read until you resume. Forwarded mail that arrives while paused is dropped.
- Remove deletes the mailbox and its stored sign-in. Tickets it created stay.
Intake URL (script): why one URL?
The URL is a secret webhook endpoint that identifies your org — not a mailbox. It never decides where a ticket goes or how urgent it is; that's decided fresh on every message by Routing rules and Priority classification on this page. Forward every mailbox to the same URL and add more rules underneath it instead of asking for a second URL.
Intake URL (script): payload shape
from and subject are required; body, messageId, and attachments are all optional.
{
"from": "jane@customerco.com",
"subject": "Total outage on prod",
"body": "Everything is down since 10am",
"messageId": "optional-unique-id-for-dedup",
"attachments": [
{ "fileName": "screenshot.png", "mimeType": "image/png", "content": "<base64-encoded-bytes>" }
]
}- attachments — base64-encoded file bytes, not a raw multipart upload (a webhook can't receive one the way a browser form can). A
data:...;base64,prefix is stripped if present. - Up to 10 attachments are stored per message — extras beyond that are silently dropped, not rejected; the ticket is created either way.
- Each attachment is capped at 10 MB decoded — an oversized or malformed one is skipped, logged, and never fails the ticket.
- Attachments land on the created ticket exactly like any other upload — visible in its Attachments list.
Intake URL (script): Gmail / Outlook scripts
Gmail has no native "forward as webhook" feature — use a small Apps Script that polls the inbox on a timer:
- script.google.com → New project, paste the script below.
- Run it once manually to authorize Gmail + URL-fetch access.
- Add a time-driven trigger (Triggers → Add trigger), every 5–10 minutes.
function forwardNewEmailsToIntake() {
var INTAKE_URL = '<your-intake-url>';
var LABEL_NAME = 'IntakeForwarded';
var label = GmailApp.getUserLabelByName(LABEL_NAME) || GmailApp.createLabel(LABEL_NAME);
var threads = GmailApp.search('in:inbox -label:' + LABEL_NAME, 0, 20);
threads.forEach(function (thread) {
thread.getMessages().forEach(function (message) {
var fromHeader = message.getFrom(); // e.g. "Jane Doe <jane@customerco.com>"
var match = fromHeader.match(/<(.+)>/);
var attachments = message.getAttachments().slice(0, 10).map(function (blob) {
return {
fileName: blob.getName(),
mimeType: blob.getContentType(),
content: Utilities.base64Encode(blob.getBytes()),
};
});
var payload = {
from: match ? match[1] : fromHeader,
subject: message.getSubject(),
body: message.getPlainBody(),
messageId: message.getId(),
attachments: attachments,
};
UrlFetchApp.fetch(INTAKE_URL, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true,
});
});
thread.addLabel(label);
});
}Troubleshooting
- Mailbox connected but no tickets: only mail that arrives after connecting is read. Check Recent activity for
SKIPPEDentries (auto-replies, bulk mail), and check the mailbox isn't Paused. For Gmail with a label set, make sure your filter actually applies that label. - Forwarding address gets nothing: send a test from an outside account. Many Microsoft 365 tenants block automatic forwarding to external addresses until an admin allows it, and Gmail needs the confirmation step completed.
- Customers don't get replies from the mailbox: open Manage and check Send replies to customers from this mailbox is on, and that Email replies to customers at the top of this page is on.
- Intake URL: nothing showing up — confirm the forwarding tool ran (check its own execution history) and the URL matches exactly what's shown above.
- Wrong project / priority — check Recent activity: a
ROUTEDentry into the default project with no matched keyword means no Routing/Priority rule matched. - Attachment missing — check the backend logs for a per-attachment warning (wrong base64, empty content, or over 10MB); the ticket itself still gets created.
- 404 from the URL — the token was regenerated (or is wrong) — copy the current URL again.
- Power Automate flow fails on every run — almost always the
fromexpression: it must drill intoemailAddress.address(see the Outlook example above), not reference the trigger's rawfromoutput directly. Check the flow's run history for the exact HTTP action's response — a 400 with an error mentioningfromconfirms this.