The email pipeline
How GVenta Help Desk turns inbound mail into tickets, threads replies, assigns companies, survives outages, keeps replies in-thread and alerts your team.
Documented from GVenta Help Desk version 1.8.55.
Email is the front door of GVenta Help Desk. This page describes the machinery that turns mail into tickets, sends replies back out so they land in the customer’s existing thread, and alerts your own team when things happen. None of it needs a human watching.
Inbound: from mailbox to ticket
The sync cycle
A long-running process, the email sync orchestrator, loops continuously with a default 20-second cycle. On each cycle it loads every active email source and syncs them one after another, with per-source error isolation: one broken mailbox cannot stop the others.
Microsoft 365 sources are handled by a worker that talks to Microsoft 365 directly; IMAP sources by an IMAP worker. Both follow the same contract and return processing statistics, which is what feeds the worker status panel described in Background jobs and workers.
What happens to each message
For every new email, in order:
- Deduplication. The message is checked against already-processed records and skipped if it has been seen before.
- Extraction. The sender address and display name, received timestamp, body (HTML or plain text), conversation ID, internet message ID, importance flag and the full CC list are pulled out. The sender is removed from the CC list and every CC address is validated.
- Thread matching, using three strategies in order of reliability:
- Conversation ID: the mail provider’s own thread identifier.
- Internet Message ID: standard RFC message threading.
- Ticket number in the subject:
[TICK-YYYYMMDD-NNNN],#TICK-…or a bare reference. This path additionally checks that the sender’s email matches the ticket’s requester, specifically so one customer cannot reply into another customer’s ticket by quoting its number.
- New ticket or new message. A match appends a message to the existing ticket; no match creates a new ticket.
- Company assignment, in a deliberate order:
- If a contact record already exists for the sender, use that contact’s company. This preserves any manual assignment an administrator has made.
- Otherwise, take the sender’s email domain and look for a customer whose Domain field matches. On a match, the ticket is assigned to that company and a contact is created under it automatically.
- Priority mapping. The email’s importance flag becomes the ticket priority: high → High, low → Low, anything else → Medium.
- CC processing. Each CC address is validated, matched to an existing contact or created as a new one under the appropriate company, and recorded against the message.
- Attachment ingestion. Every attachment is downloaded from the provider and uploaded to your instance’s private object storage.
- Housekeeping. The message is marked read if the source is configured to do so, recorded as processed, and moved to a
Processedfolder in the mailbox (created on demand). This is deliberate belt-and-braces: even if the database were restored from an older backup, or the mailbox re-authorized, mail that has already been handled will not be turned into duplicate tickets. - Notification dispatch. The admin notification side-channel fires
ticket.created, fire-and-forget.
Set a customer’s Domain field once in Customers and contacts and step 5 files every future email from that company automatically.
Built to survive failure
- Per-source failure counting. A source is automatically disabled after 20 consecutive failures, and the application automatically attempts to re-enable it every 5 minutes once conditions improve.
- Authentication outages are treated differently from source failures. If the Microsoft 365 connection itself is rejected (the OAuth broker answers 401), the orchestrator applies exponential backoff between cycles, capped at 30 minutes, rather than disabling sources. Disabling sources cannot fix an authentication outage and would leave the worker permanently idle. Sources stay active and syncing resumes on its own once re-authorization happens.
- Heartbeats. Workers publish regular heartbeats so health monitoring can tell “running” from “running but stuck”.
- Graceful shutdown. When asked to stop, a worker finishes the current source rather than dropping mid-message.
- Auto-reply detection, so out-of-office bounces do not spawn ticket storms.
- Per-source last-sync timestamps, so a restart resumes from where it stopped instead of re-reading the mailbox.
- Automatic worker recovery on restart. A startup routine waits for the database, reads which workers should be running, and restarts them.
Why it matters: Mail keeps flowing through outages, credential expiries and restarts, and when it genuinely can’t, the interface tells you exactly which mailbox and exactly why.
Outbound: replies that stay in the thread
Providers
Two sending providers are supported: Microsoft 365 and SendGrid. When both are configured, SendGrid is preferred and Microsoft 365 is the fallback. Sending is governed by a single active outgoing configuration, deliberately decoupled from the inbound sources, so you can receive on several mailboxes and send from one identity. Configuration lives under Settings → Email Integration → Outgoing Email Configuration; see Settings.
Thread integrity
Outgoing replies set In-Reply-To and References headers from the ticket’s stored message ID, and the subject is prefixed as:
RE: [TICK-YYYYMMDD-NNNN] Original Subject
The RE: prefix and the ticket tag are added only if they are not already present, so subjects never accumulate RE: RE: RE:. The subject format is template-driven and can be customized.
Why it matters: Replies land in the customer’s existing mail thread, in their mail client, looking like a normal conversation, not like a robot opened a new one.
Attachments travel with the email
Files uploaded with a reply are attached to the outgoing email itself. The customer receives real files, not links that require a login.
Delivery is fault-tolerant
When an agent sends a reply, the message is saved to the ticket first and the email is attempted second. If delivery fails, the reply is still on the ticket and the interface reports precisely why, distinguishing sender not configured, not authenticated and incomplete configuration from general failures. Administrators are routed straight to Settings → Email Integration; other users see a message telling them who to contact. The same granular delivery status is returned by the API; see API examples.
Who is notified of what
A separate path sends event notifications, with recipient rules that are careful about who gets what:
| Event | Requester notified | Assigned agent notified |
|---|---|---|
| Status changed | Yes | Yes |
| Resolved | Yes | Yes |
| Closed | Yes | Yes |
| Assigned | No | Yes |
| Reply received | No | Yes |
The person who performed the action is always excluded from their own notification, and the recipient list is de-duplicated. The wording of these emails comes from the templates under Settings → Customize Emails.
Ticket links
Ticket URLs embedded in emails are built from your instance’s configured address and point at the ticket permalink route, https://your-instance.example/tickets/TICK-YYYYMMDD-NNNN, which handles sign-in and access control itself. See Client portal.
Domain authentication for SendGrid
For SendGrid, the application can register or locate your sending domain with the provider, retrieve the DNS records you need to publish, trigger validation, poll its status and store the verification state, all from the settings screen, using the Verify DNS action.
The notification side-channel
Completely separate from customer-facing mail, the side-channel alerts your own team. It has five configurable events, each independently enabled with its own recipient list:
- New Ticket Created
- Ticket Status Changed
- Ticket Assigned
- New Message on Ticket
- Daily Report
Key behaviors:
- Dispatch is fire-and-forget and fully exception-guarded. A notification failure can never affect the API response of the action that triggered it.
- Every dispatch first checks that the event is enabled and has at least one recipient before doing any work.
- The Daily Report is generated by the orchestrator. It reads the configured send time (default 08:00, server time), checks a persisted
daily_report_last_sentmarker stored in the database so that it survives worker restarts, and sends once per day. It gathers live statistics and renders a formatted HTML summary that includes human-readable ticket ages. - Delivery uses the same active outgoing provider as everything else.
- A Send Test action per event lets you verify delivery without waiting for a real trigger.
Recipients and event toggles are managed under Settings → Notifications; see Settings.