Skip to content

fix(portal): send the customer an acknowledgement when a ticket is created - #61

Open
YJack0000 wants to merge 3 commits into
developfrom
fix/portal-ticket-acknowledgement-email
Open

YJack0000 wants to merge 3 commits into
developfrom
fix/portal-ticket-acknowledgement-email

Conversation

@YJack0000

Copy link
Copy Markdown
Contributor

Someone who opens a ticket on the help center now gets a first email straight away. It names the ticket number and repeats the subject and description they submitted, and replying to it lands on the same ticket. Until now the portal created the ticket silently: the customer received nothing, and the ticket page told them to "reply to the email we sent you" when no email had been sent. Anything they did write arrived as a brand new conversation.

Why

Portal submission wrote only the customer's own incoming message. Chatwoot delivers mail for outgoing and template messages, so nothing left the system, and the customer's mail client had no Message-ID of ours to reply to.

Ticket creation now adds one outgoing message to the ticket conversation and lets the existing channel machinery deliver it. An email ticket inbox mails it through Email::SendOnEmailService, which stamps the conversation/<uuid>/messages/<id> Message-ID the reply threads onto; the widget fallback picks it up through the continuity mailer. The message carries no sender, the same shape the Captain handoff message uses, so human_response? stays false and first_reply_created_at and waiting_since keep reporting the ticket as unanswered by a human.

Scope

  • Public::Api::V1::Portals::TicketsController#create_acknowledgement_message and #acknowledgement_content, called from #build_ticket.
  • public_portal.tickets.acknowledgement strings in config/locales/en.yml and config/locales/zh_TW.yml.
  • Three existing examples now read the description off messages.incoming.last, since the acknowledgement is the last message.

Tradeoffs

A dedicated mailer would have kept the thread free of an extra bubble, but only a message on the conversation gets the threading headers and shows up for the agent and on the customer's ticket page. The copy stays plain text rather than markdown because the portal ticket page renders message content verbatim.

Blast Radius

Only the portal ticket path. Every other way a conversation starts is untouched. One extra outbound mail per submitted ticket.

How to reproduce

Submit a ticket on a portal whose ticket inbox is an email inbox, then look at the customer's mailbox. Before this change nothing arrives.

Verification

Full local stack (docker compose, MailHog on :8025, portal ticket inbox set to an email inbox). Submitting the form before the change delivered 0 mails; after it, 1 mail to jane@example.com, subject Re: Cannot log in, Message-ID: <conversation/6743ae9f-.../messages/12@support.localhost>, body carrying ticket #2, the subject and the description. Repeated with the portal pointed at the widget inbox: the continuity mailer carries the same acknowledgement.

bundle exec rspec spec/controllers/public/api/v1/portals/tickets_controller_spec.rb reports 42 examples, 0 failures; the two new examples fail on the parent commit. bundle exec rubocop clean on both changed Ruby files.

🤖 Generated with Claude Code

A portal ticket creates only the customer's own incoming message, so nothing
outbound ever leaves and the customer has no mail to reply to. These examples
fail on the current behaviour.

The three existing examples that read the description off `messages.last` now
name `messages.incoming.last`, since the acknowledgement lands after it.
…eated

Submitting a ticket on the help center portal wrote only the customer's own
incoming message. Nothing outbound ever left, so the customer had no mail to
reply to, and the ticket page told them to "reply to the email we sent you"
when no email had been sent. Any mail they wrote instead opened a new
conversation.

Ticket creation now adds an outgoing message that names the ticket number and
quotes the subject and description. It goes out over whichever channel the
portal's ticket inbox uses: the email inbox mails it directly and stamps the
conversation Message-ID their client replies to, the widget fallback sends it
through the continuity mailer. The message carries no sender, so it is not a
human response and leaves first_reply_created_at and waiting_since alone.

@yui0303 yui0303 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

…veries

With SMTP_ADDRESS unset, config/initializers/mailer.rb switches the test
environment to :sendmail, so nothing reaches ActionMailer::Base.deliveries and
the example failed on CI while passing locally. Assert the job enqueued for the
acknowledgement, then render the mail through ConversationReplyMailer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants