Home Simple e-mail service with Rails - Part 6: Sending Replies
Post
Cancel

Simple e-mail service with Rails - Part 6: Sending Replies

Now that we can see Topics, there’s one last thing that’s missing. We can track replies, but there’s no way to send a reply. Technically, sending a reply should be opposite process as receiving one, so let’s get started!

TLDR: You can find the code in this GitHub repository. Every part has a corresponding commit.

We can start with a button this time. I personally added option to reply to each Message in a Topic. For that, we add link to a new Message, but this time, we also pass message_id so we know to which Message we want to reply to.

1
    <%= link_to 'Reply', new_message_path(reply_to_id: message.id), class: "rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>

Replying to an email is simply reversing from and to. It’s also common to prepend Re: to the original subject.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  # ...

  def new
    @message = Message.new

    if params[:reply_to_id].present?
      reply_to = Message.find(params[:reply_to_id])
      @message.reply_to = reply_to # we also have to save reference to original Message
      @message.subject = "Re: #{reply_to.subject}"
      @message.to = reply_to.from
      @message.from = reply_to.to
      @message.cc = reply_to.cc
    end
  end

  # ...

This change prefill new Message object with all reply related data. We also set reference to Message this new one is a reply to. As we need the reply_to value to be part to the HTML form, incidentally being passed in form data to the create method, we have to do few minor changes.

1
2
<%= form_with(model: message, class: "contents") do |form| %>
  <%= form.hidden_field :reply_to_id %>

We have to add new hidden field to the form which will include id of a Message we are replying to. We also have to allow reply_to_id as a valid param for a Message. This we can do by updating existing message_params method in the MessagesController.

1
2
3
4
5
6
7
8
9
class MessagesController < ApplicationController
    # ...

    def message_params
      params.require(:message).permit(:subject, :from, :to, :cc, :bcc, :content, :reply_to_id, attachments: [])
    end

    # ...
end

Right now, if you try to send a new reply, email will be delivered and new Message record will also include reply_to association to another Message. That could be enough, but if you remember from reply tracking part, we tracked replies by reading a message_id from the Mail object. It’d be a good idea to also pass message_id of a Message we are trying to send a reply to, so we make tracking of replies possible for receiver of the reply too.

1
2
3
4
5
6
7
8
9
class MessageMailer < ApplicationMailer
  def send_message(message_id)
    # ...

    if @message.reply_to.present?
      headers['In-Reply-To'] = @message.reply_to.message_id
    end

    mail subject: ...

And that’s it. This simple change ensures we are including correct header to mark email as a reply to another email.

This part was fairly short and simple, but our app currently looks like a mess unless you did some styling on your own. I won’t include changes in the text, but I’ll add one extra commit with few UX changes and my attempt to styling.

This post is licensed under CC BY 4.0 by the author.
Trending Tags

Simple e-mail service with Rails - Part 5: Grouping to Topics

Simple e-mail service with Rails - Part 7: Reactivity with Turbo Streams

Comments powered by Disqus.

Trending Tags