Back to Notes
28 August 20268 min read

How I Built an Email-Based User Support System for Festia

I share how I built an email-based user support system for Festia. Users can submit feedback or bug reports directly from the app, while admins can reply and continue each conversation through ticket-based email threads without relying on social media.

How I Built an Email-Based User Support System for Festia

The Email Support Problem for Festia

Festia needs a channel where users can leave feedback or report bugs. At the same time, I also want to be able to reply to them, but I don't want users to have to open a social media app just to message a stranger on the Internet — me.

Choosing Email Instead of Chat Apps for Festia Support

As a user myself, I understand the hesitation of having to open a social media app and connect with a stranger on the Internet. Maybe it's just me, but I don't think every user feels comfortable with that experience.

Building an entire chat system from scratch also feels a bit like over-engineering. Festia's support flow does not need to be real-time. If I built a chat system, I would also have to deal with real-time connections, notifications, online status, and many other things.

So email seemed like a better fit.

UX on Festia

On Festia, I added a feedback button. When a user clicks it, a modal appears where they can fill in the required information just like a normal form.

Users do not need to care where the message is actually sent. They simply fill in the form, click submit, and continue using the application.

The Big Picture

When a user submits feedback:

User → Festia feedback form modal → Backend API → Create a thread/ticket in the database → Resend sends a notification to the admin → Resend sends a confirmation email to the user

Each ticket has its own ID. The email sent to the user can be replied to through an address like:

support+ticket_id@nphuonha.id.vn

The thread and its messages are stored in Supabase. Resend handles both outbound email delivery and inbound email receiving.

When the admin replies

When I want to tell a user that a bug has been fixed or respond to their feedback:

Me → Admin Support View → Backend API adds a message to the thread/ticket → Resend sends an email to the user

The email still uses a subject starting with Re: together with headers such as In-Reply-To and References, which helps Gmail and other mail clients display related emails in the same conversation.

What happens when the user replies?

The email sent to the user includes:

Reply-To: support+ticket_id@nphuonha.id.vn

When the user clicks Reply, the flow becomes:

User → Mail client sends the email to support+ticket_id@nphuonha.id.vn → Resend receives the inbound email → Resend calls a backend webhook → Backend verifies the webhook → Parse ticket_id from the email address → Store the email as a message in the correct thread

Here, the backend does not use In-Reply-To to determine the ticket. Instead, it extracts the ticket_id from the support+ticket_id@... address and maps the incoming email to the corresponding thread.

Why Don't I Use In-Reply-To to Identify the Ticket?

Festia still uses In-Reply-To and References in outbound emails. Their purpose is to help mail clients such as Gmail or Outlook group related emails into the same conversation.

However, the backend does not use these headers as the primary mechanism for identifying a ticket.

If I relied on In-Reply-To, the backend would need to handle several additional cases:

  • A mail client might omit the header.
  • The header may change when an email is forwarded.
  • The system would need to store and match Message-ID values across emails.
  • Different header formats would need to be handled.
  • A fallback mechanism and duplicate-message protection would also be necessary.

Larger support systems such as Zendesk may use In-Reply-To together with Message-ID, ticket IDs in the subject, and several other techniques.

For Festia's current needs, however, I chose plus addressing:

support+ticket_id@nphuonha.id.vn

Advantages

  • Easy to implement.
  • Only requires a regex to extract the ticket ID.
  • Less dependent on whether a mail client provides all expected headers.
  • Easier to debug when something goes wrong.

Disadvantages

  • The system has to define and maintain this convention itself.
  • Direct integration with third-party platforms such as Zendesk may be more difficult.
  • If there are co-authors or additional developers in the future, I will need to clearly explain how the flow works.

Are There Any Weaknesses?

Yes, and there are definitely still many things that could be improved.

This is the first time I have directly built a system involving inbound email, email headers, and email threading. During the process, there were parts I did not fully understand, parts I initially understood incorrectly, and parts where I received help from an AI agent.

However, the system is currently working well enough for Festia's needs, so I am going to leave it as it is for now. Maybe one day, when I understand email flows more deeply, I will come back and make the system more robust and standards-compliant.

Through this article, I wanted to share a small but effective solution that Festia uses to provide a support channel for its users.

Thank you for taking the time to read this article ^^

NP
Phuong Nha NguyenAuthor
Share: