Email System
For many users, email is the helpdesk: they write to support@, get an answer and never notice there is a ticket behind it. This page describes what becomes visible in the process, which fundamental decisions shape the behaviour, and how a mail travels in both directions — from polling the mailbox to a confirmed reply. Managing the mailboxes themselves is covered on the Inbound Mailboxes API page.
What users see
| Surface | Behaviour |
|---|---|
| Mail to a mailbox | Within the poll interval a ticket appears with the subject as its title; if configured, the sender receives an acknowledgement with the ticket number in the subject. |
| The customer replies | The reply lands as a message in the existing ticket, not as a new one — even when the customer changed the subject. The ticket moves to "waiting for support". |
| Email thread on the ticket | A separate area shows every incoming and outgoing mail of this record with time, recipients, attachments and state. Error reasons are visible only to staff with internal visibility. |
| Replying from the ticket | The reply goes out through the same mailbox, quotes the last mail, appends the signature and sets the record to "waiting for customer". If the mailbox is not set up for sending, the button is disabled with a reason — rather than producing an error later on. |
| Sending without confirmation | If an attempt breaks off before the mail server answered, the row reads "delivery unconfirmed" — with two menu entries: send again or confirm as sent. The "sending" badge disappears without reloading. |
| A rejected mail | It is moved into a dedicated folder of the mailbox and recorded in the audit trail with a reason — with header data, without content. That keeps it traceable why no record was created. |
| Mailbox list and system status | Every mailbox shows its open mails as a number. If polling stops, a connection fails or a backlog waits too long, the system status reports exactly that — with mailbox name and reason. |
| People in copy | Anybody in CC of a mail becomes a participant of the ticket and stays informed. Bounces and out-of-office replies do not become participants. |
The idea
Four decisions shape the behaviour — they also explain why some things deliberately do NOT happen:
- No mail is silently lost. A discovered mail is first entered into an open set and only then marked as "seen". The other way round, a crash between the two steps would skip exactly those mails nobody has processed yet. Every mail stays open until it is really processed or rejected with a reason.
- Rejecting means moving, not deleting. A mail that does not become a record moves into a dedicated folder and leaves an audit entry with a reason. Deleting processed mails happens only where it is explicitly configured — rejected ones never.
- Unconfirmed is not failed. When a send attempt breaks off without an answer from the mail server, the mail may already be out. The system then claims neither success nor failure but marks "unconfirmed" and repeats nothing by itself — an automatic second attempt could send the same mail twice. A person makes that call.
- Customers see no plumbing. Error reasons, headers, check results and skipped attachments are recorded as an internal trail on the record. Customers see their message and the answer — not what happened on the way.
The path of an incoming mail
Polling
Every mailbox is polled on its own interval (1 to 60 minutes, default 5). Two protocols are available:
| Protocol | How new mails are found |
|---|---|
IMAP | The search starts above the last known message number. If the server changes its numbering, the catch-up search kicks in. |
MS_GRAPH (Microsoft 365) | Microsoft delivers the changes since the last poll, in pages of 100 messages and at most 10 pages per run. If anything is left over, the mailbox becomes due again immediately instead of waiting. Moved mails keep their identifier, so no mail counts as new after a folder change. |
The catch-up search is the same rule for both protocols: everything unread of any age, plus everything from the last 48 hours. It runs on the first poll of a mailbox, after the credentials change and after the remembered position is lost. Read mails older than 48 hours deliberately count as done — otherwise a fresh start would turn years of correspondence into tickets.
If several instances of the email service run, only one of them polls a given mailbox; the others skip it. When errors pile up on a mailbox, its polling pauses briefly instead of hammering a wall on schedule.
Checking
Before processing, every mail passes three checks in this order:
- Size. Mails above 25 MB are rejected for good.
- Mailbox limits. First the mails per minute, then the mails per sender and hour. A throttled mail is not rejected but stays open and gets its turn later — and it consumes no quota.
- Sender checks. Where SPF, DKIM or DMARC are enforced, an explicitly failed result leads to rejection. A missing or inconclusive result never rejects: not every legitimate sender is checked.
Who the mail belongs to
If the sender address is known, the mail belongs to that account. Otherwise the mailbox rule decides: create a contact, attribute everything to a collective account, or reject. An automatically created contact is a pure email contact without password or login; it receives a one-off notice about the storage of its data.
The daily limit for automatically created contacts is deliberately a time lock rather than a refusal: once it is reached, the mail stays open and is processed after midnight (UTC). A mailing list hitting a mailbox therefore costs neither tickets nor mails.
New record or reply to an existing one
Five criteria are checked in this order; the first that matches decides:
| # | Criterion |
|---|---|
| 1 | The mail explicitly answers a mail Eviworx knows |
| 2 | It names such a mail in its history (the last 50 references; the most recent match wins) |
| 3 | It carries the ticket identifier in a dedicated header |
| 4 | It carries the ticket number in a dedicated header |
| 5 | Its subject contains the mailbox tag with the ticket number, for instance [HD-000123] |
A subject match alone is not enough: the sender must be involved in the record — as customer, assigned agent, earlier writer, participant or from an earlier CC. Otherwise somebody could write into a stranger's record with a guessed ticket number in the subject.
If the matched ticket has since been merged into another one, the assignment follows that chain to the record still alive. If no criterion matches, a new ticket is created with the mailbox defaults for category, group and priority.
When a mail hits an existing record, it also affects its status:
- When the customer or a registered person from the CC writes, the record moves to "waiting for support"; when an agent writes, to "waiting for customer".
- On a resolved record a mail does not change the status — it notifies the agent.
- On a closed record the reopening rule applies. If the window has passed, a new follow-up ticket is created and linked to the old one — so the mail is never lost just because the record is too old.
- A reply from an agent by mail satisfies the response target of the service level.
Attachments on the way in
Attachments are fetched only once the mail has really become a record — and then in one go. What is accepted is decided by the attachment settings of tickets: size, count, permitted formats. A file with the same checksum as an existing attachment of the same ticket is not stored twice.
If a file is not accepted, that is no silent loss: an internal trail on the record names every skipped file name with its reason. The mail itself arrives — an oversized attachment does not cost the message.
Post-processing in the mailbox
| Outcome | What happens to the mail in the mailbox |
|---|---|
| processed or recognised as a duplicate | the action configured for the mailbox: mark as read, move to a folder or delete |
| rejected | move to the rejection folder (default "Rejected"); without one, marking as read remains. Never delete. |
| processing still running | no action — otherwise the mail would be out of reach for a second attempt |
Target folders are created by Eviworx when needed, nested ones included. If the post-processing of a single mail fails — because a folder cannot be created, say — the mail stays open and the reason appears as an error code on the mailbox.
Reasons for a rejection
| Code | Meaning |
|---|---|
MESSAGE_TOO_LARGE | Above 25 MB |
SECURITY_POLICY | An enforced sender check explicitly failed |
SENDER_REJECTED | The mailbox accepts no unknown senders |
SENDER_INVALID | The sender is not a deliverable address |
OPEN_TIMEOUT | The mail could not be processed for 24 hours; the audit entry names discovery time and attempts |
PROCESSING_RETRIES_EXHAUSTED | Five processing attempts have failed |
Bounces and out-of-office replies
Eviworx recognises bounces by sender, return path, message type and typical subject lines, and out-of-office or list mails by their headers. Such mails are recorded on the record but trigger no reply, do not make the sender a participant, change no status and satisfy no response target. That prevents the classic endless loop of two automatons answering each other.
The path of an outgoing mail
There are two kinds of outgoing mail: the reply from a record, which goes through its mailbox, and the notification from the system, which uses the global send path. What customers mostly see is the first one.
- Subject and threading. The reply carries tag and ticket number in the subject and references the last incoming mail. Together, both ensure the customer's answer lands in the right record again — even when their mail program rewrites the subject.
- Quoting. What is quoted is the last mail of the thread that really went out. For your own earlier reply the written text is quoted, not the delivery artefact. The quote header appears in the recipient's language.
- Signature. The mailbox signature applies, otherwise the default one; a placeholder in the text decides where it goes. If the signature cannot be resolved, the mail goes out without it — a signature is presentation and must not block an answer. A leftover placeholder never reaches the customer.
- Sender. The name is the mailbox name, otherwise the application name; the address is always the mailbox address, the reply-to is the configured one or again the mailbox address. There is no invented sender: if part of the send settings is missing, no mail goes out.
- Attachments. Only what belongs to the record, is not deleted and passed the virus scan is attached. If a selected file is unavailable, nothing is sent at all rather than half a mail; the same applies when attachments plus signature images exceed the limit for outgoing mails. Both with a clear message before sending.
The three outcomes of an attempt
| Outcome | Meaning and what can be done |
|---|---|
| sent | The mail server accepted the message. Skipped attachments appear as an internal trail. |
| failed | A clear failure with a reason. The agent can send again (at most five times per mail) or dismiss the row. |
| unconfirmed | The attempt broke off before the mail server answered — the mail may have arrived. No automatic second attempt; the agent sends again or confirms it as sent. |
To keep no row stuck in "sending" forever, a sweep runs every 15 minutes ("email deadline sweep"): an outgoing row in delivery for more than 60 minutes becomes unconfirmed; an incoming one in processing for more than 30 minutes is set to failed and thereby released for another attempt. The sweep is deliberately rarely successful — if it finds something regularly, an assumption about the mail path no longer holds.
Limits
| Limit | Value | Effect when reached |
|---|---|---|
| Size of an incoming mail | 25 MB | Rejection with a reason |
| Mails per minute and mailbox | 60 (configurable) | The mail stays open and comes later |
| Mails per sender and hour | 30 (configurable) | The mail stays open and comes later |
| New contacts per mailbox and day | 100 (configurable) | Time lock until midnight (UTC); the mail stays open |
| Processing per poll | 50 | The rest stays open, the mailbox becomes due again immediately |
| Open mail without processing | 24 hours | Rejection with a reason, so an edge case does not run along forever |
| Attachments of an outgoing mail | 25 MB (configurable) | The mail is not queued; the agent finds out right away |
| Resending per mail | 5 | After that only dismissing the row remains |
The three configurable inbound limits live per mailbox in the admin center under "Communication → Email & Mailboxes" in the "Limits" section; the limit for outgoing attachments under "Settings → Files". It should match what your own mail server accepts — in transit a file grows by roughly a third through encoding.
When something is stuck
| System status reason | Meaning |
|---|---|
MAILBOX_STALLED | The mailbox has not been polled for too long — longer than three times its interval, at least 15 minutes. |
MAILBOX_ERRORING | The last poll ended in an error, or three errors in a row occurred. The reason is a code on the mailbox; a failed move of a single mail leads here too. |
MAILBOX_BACKLOG | There are open mails and the oldest waits longer than that same deadline. The reason names count and waiting time. |
A healthy mailbox reports nothing; at most one reason appears per mailbox, in the order of the table. To narrow it down:
- The connection probe on the mailbox uses the same path as production — so it really tests what is stuck and names the reason in plain terms.
- A backlog without errors usually means more is coming in than the interval works off. A shorter interval or a higher per-minute limit helps; processing itself takes 50 mails per poll.
- A deactivated mailbox fetches no mails and does not send — but it reports no error either. Anybody investigating "nothing arrives" checks that first.
- The polling state — how far a mailbox has been read and which mails are open — lives in Redis. Redis should therefore persist to disk; losing that state is not data loss: the next poll fetches everything unread plus the last 48 hours.
- A change to a mailbox takes effect immediately: the email service reloads the settings without waiting for the next poll.
Recommendations
- Choice of protocol: For Microsoft 365, Microsoft Graph is the better path — authentication through an app registration, no mailbox password. For your own mail servers, IMAP and SMTP.
- Unknown senders: Creating contacts suits an open support mailbox, a collective account suits mailboxes that systems report into, and rejecting suits purely internal mailboxes.
- Your own systems replying by mail: They should carry the ticket identifier in a header or explicitly answer the previous mail. That is the most reliable match — the subject is the weakest one.
- Transport encryption: Certificate verification stays on (the default); switching it off is only worth it for a self-issued certificate on your own network.
- Sender checks: For mailboxes handling approvals or access, enforcing SPF, DKIM and DMARC is worthwhile. For an open support mailbox it is risky: legitimate senders sometimes fail because of third-party forwarding.
- Folders: A dedicated folder for processed mails makes visible what Eviworx has seen; deleting as post-processing takes that option away.
Related pages
- Inbound Mailboxes API — creating and maintaining mailboxes: fields, permissions, error codes, access restriction
- Tickets API — email thread, replying by mail, creating a ticket as email
- Notifications — the global send path for notifications and the other channels
- Email Signatures API — signatures, inline images and preview
- Attachments API — the rules by which incoming attachments are accepted
- Integrations — Microsoft Teams, Cisco Webex and outgoing webhooks
- Security — transport encryption, credentials and sender checks in the security context