Haraworks · Engineering case study

A faster inbox.
A bigger audience.
One connected workflow.

Enterprise Mail &
External Email Integration

I built a dedicated mailbox read model, moved large-audience mail processing to Kafka, and designed the external email integration flow from the ground up.

C# / .NETReactMongoDBKafka
My roleFull-stack EngineerBackend-focused
Read performanceMailIndexMailbox views by user & type
Distribution scale10,000+Recipients in a single send
Integration ownershipBuilt from the ground upTwo-way external email flow
Haraworks / Internal MailView the product ↗
Haraworks inbox with mailbox-type filter, sender and subject rows, dates, and pagination
01 / The productA familiar inbox backed by user-specific mailbox data.

The challenge

A simple screen.
A lot happening underneath.

Every row in the mailbox brings together a conversation, its sender and recipients, read information, and a folder classification. Each person has their own view of that same conversation.

At the same time, mail distribution needed to grow from hundreds to more than 10,000 recipients per send. The read path and the send path each needed a different solution.

01 / Read performance

Prepare the mailbox view.
Make each read lighter.

The user wants a list of conversations. The backend needs to assemble who sent them, who received them, how many people read them, and which mailbox type they belong to.

Before / Assemble during list loading
Open a user's inbox
ConversationsSenders & recipientsRead countsMailbox types
Combine data → Build list response

Repeated assembly makes the list-loading path do more work.

After / Maintain a dedicated read model
Message & mailbox changes
MailIndexUser + mailbox typeMessage summary · participants · labels · state
Read prepared view + related counts

Less data assembly when a user opens Inbox, Sent, or Drafts.

What I implemented

A mailbox read model organized by user and type, with repositories and worker updates to keep the list view aligned with conversation and recipient changes.

The trade-off

A dedicated read model reduces list-loading work, but adds synchronization responsibilities. Drafts, unread counts, labels, archive actions, and shared conversations must update the right user's view.

Result

Reduced mailbox list-loading time while preserving a familiar inbox experience.

02 / Distribution at scale

Hundreds of recipients.
Then more than 10,000.

Sending to a larger audience multiplies the work behind one click: sender and recipient records, labels, mailbox views, and notifications all need processing.

Audience per send
Hundreds10,000+

Move audience-wide work out of the API request.

01

Send API

Validate the request.
Persist the message.
Publish processing work.

Request path
02

Kafka

Carry work beyond the lifetime of the initial request.

Message queue
03

Background workers

Sender & recipientsLabel assignmentMailbox updatesNotifications
Asynchronous processing

Conceptual flow of the Kafka-based implementation I worked on.

The key decision

The API response should not depend on processing the entire audience. I moved that work into messages so workers could continue after the initial request.

Keep processing understandable

Sender and recipient state connects background work to the mailbox experience. Processing status, errors, and notifications help users understand what happens after they click Send.

03 / Integration ownership

Outside the company.
Inside the conversation.

I designed and built the two-way external email integration flow from the ground up, connecting the internal mailbox with the platform's email delivery infrastructure.

HaraworksInternal
conversation
Employees · mailbox state
OutgoingCompose → Kafka → Delivery serviceSender identity · HTML · attachment links
Incoming replyReceive → Resolve recipients → Link threadCompany domain · employee prefix · message references
External emailContacts
outside the app
Messages · replies
01

Send with the right identity

Build the outgoing address from company domain settings and the user's email prefix, prepare content, and publish work to the delivery pipeline.

02

Bring replies back into context

Resolve incoming recipients to employees, check domain configuration, and use message references to associate replies with the internal conversation.

03

Carry attachments across systems

Prepare signed attachment links for outgoing email and transfer incoming files into application storage. Adapt editor HTML for email rendering.

04

Expose status and configuration

Reconcile sending logs, report failures, and provide company-specific controls for domains, allowed senders, external sending, and email prefixes.

Queued, delivered, and opened are different events.

I worked on send-log reconciliation and image-based open tracking. An open signal adds visibility, but does not guarantee that a person has read the message.

Full-stack product work

The details that make
the workflow usable.

Alongside the backend work, I developed and refined the React interfaces and API behavior that people use to organize, personalize, and follow up on mail.

A

Mailbox automation

Labels, archive flows, unread counts, and filters based on senders, recipients, or keywords.

Less manual organization
B

Personalized mail

Mail-merge management, recipient validation, permissions, inbox integration, and index synchronization.

Personalized content in one mailbox
C

Recipient reporting

Department and job-title filters, read/error status, and background Excel exports with a notification when ready.

Clearer follow-up for senders

What this project demonstrates

Connect the user workflow
to the system behind it.

My contribution spans how data is read, how work is distributed, and how separate systems exchange messages. Each decision serves the same goal: make enterprise communication practical at a larger scale.

Faster mailbox reads

Prepared views by user and type reduce list-loading work.

10,000+ recipients per send

Kafka separates large-audience processing from API requests.

Two-way external email

A flow built from the ground up connects outside replies to internal conversations.