Email Integration & Tracking
Email Integration & Tracking
NexusRMS supports bi-directional email integration, allowing external recipients to participate in communication threads directly from their email client. All outbound emails are tracked for delivery, opens, clicks, and bounces.
Enabling Email Integration
Email integration is controlled by the email_integration_enabled communication setting. When enabled, threads with external recipients send email notifications, and replies from those recipients are threaded back into the system. The email_reply_domain setting configures the domain used for inbound reply addresses.
Email Threading
Every discussion thread has an email_thread_id that groups related emails together. Outbound messages include standard email headers:
- Message-ID — stored as email_message_id on the CommunicationMessage model.
- In-Reply-To — stored as email_in_reply_to, referencing the parent message's Message-ID.
These headers ensure that email clients (Gmail, Outlook, Apple Mail) correctly group NexusRMS messages into a single conversation thread.
Email Signature
Each tenant can configure a custom email signature via the email_signature communication setting. Signatures support plain text content with a maximum length of 2,000 characters. The signature is appended to all outbound emails.
Email Digest
Users can choose how frequently they receive email notifications via the digest frequency setting. Available options:
- never — no email notifications.
- daily — a single daily summary of non-urgent notifications.
- weekly — a weekly summary email.
- monthly — a monthly summary email.
Urgent and high-priority notifications are always delivered immediately, regardless of the digest setting.
Email Tracking
The DiscussionEmailTracking model records per-recipient engagement data for every outbound email. Each record is stored in the discussion_email_tracking table.
Tracking Fields
| Field | Description |
|---|---|
| thread_id | Communication thread UUID |
| message_id | Specific message UUID |
| recipient_email | Email address of the recipient |
| recipient_type | One of: client_contact, freelancer, external |
| tracking_pixel_id | Unique ID for the 1x1 tracking pixel embedded in the email |
| sent_at | When the email was dispatched |
| delivered_at | When delivery was confirmed by the mail provider |
| opened_at | Timestamp of first open event |
| open_count | Total number of open events |
| clicked_at | Timestamp of first link click |
| click_count | Total number of link clicks |
| bounced_at | Timestamp when the email bounced |
| bounce_type | One of: hard, soft, complaint |
| bounce_reason | Error message or reason from the mail provider |
| user_agent | Browser or email client user agent string |
| ip_address | IP address from the open/click event |
Tracking Methods
- recordOpen(userAgent, ip) — increments open_count and sets opened_at on first open.
- recordOpenFromRequest(request) — convenience method that extracts user agent and IP from the HTTP request.
- recordClick(userAgent, ip) — increments click_count and sets clicked_at on first click.
- recordDelivery() — sets delivered_at timestamp (only on first delivery event).
- recordBounce(bounceType, reason) — records bounce with type (hard, soft, or complaint) and the reason string.
- findByTrackingPixel(trackingPixelId) — static method to locate a tracking record by its unique pixel identifier.
Tracking Statistics
Aggregate statistics are available at both the thread and message level:
- getStatsForThread(threadId) — returns total, sent, delivered, opened, bounced counts and the open_rate percentage.
- getStatsForMessage(messageId) — same statistics scoped to a single message.
Bounce Handling
Three bounce types are tracked:
- Hard bounce — permanent delivery failure (invalid address). The isHardBounce() method identifies these.
- Soft bounce — temporary failure (mailbox full, server unavailable).
- Complaint — recipient marked the email as spam.
Email Delivery Services
EmailNotificationService renders notification templates via the NotificationTemplate model and sends through Laravel Mail, tracking email_sent_at on each notification. Postmark integration handles transactional email in production; bounce and complaint webhooks feed back into the DiscussionEmailTracking model. SMS delivery via Twilio is restricted to urgent and high priority notifications only to control costs. Each user's delivery respects their configured preferences — immediate for urgent items, batched digest for lower-priority updates.
Was this article helpful?