1

Context

Gems like mail_view, mailcatcher, rails_email_preview, etc. seem to be more developer-oriented (a way to debug a template). But I need something that will be used by the trusted users of my rails app in production.

My app is a project management app, where project managers can update the status of their projects, operations during which emails must be sent to project contractors, developers, clients, etc.

The project manager must be able to tell whether or not he wants to send an email (this is easy), and be able to customize to some extent the message content (not the design, only specific text parts should be enough). They DO want to have some control over the email about to be sent, ie, they need a preview of the email they customized. Why ?

  1. Project Managers are trusted users/programmers, and I let them add HTML as custom parts of the email (We are talking about a small-scale app, and the project managers are all trusted employees). But a closing tag is easily forgotten, so I want to provide them with a mean to check that nothing is wrong. Eg. that the text does not all appear as <h2> just because they forgot a closing </h2>
  2. Some email templates already include some info about what the PM is writing about, and the PM may not be aware of it (understand : may be too drunk to remember it). An email preview is just a way to avoid duplicate sentences (like two times Hello M. President,)
  3. CSS styles are applied to the email. It can be hard to anticipate the effect of tags like <h2>, etc. So I need to render the email with the CSS

REMARKS

Previsualize & Send button

Project managers have access to a form that will feed the content to my Rails app. I am thinking on having both a normal submit button, and a previsualize button. I will probably use some tricks given by this SO question to differentiate the behaviours of the 2 buttons

Letter_opener : a nice gem, but exclusive ?

I am using letter_opener for debug (so different context), but this is typically the preview I'd like to show to the project manager. However, in order to be used, letter_opener requires to modify action_mailer configuration config.action_mailer.delivery_method = :sendmail # (or :letter_opener). So I can only previews emails, or send them for real, not both ? I would accept a solution that would let me choose whether to use letter_opener or send the email for real

Small Editor ?

Instead of blindly trusting my project managers' ability to write basic html without forgetting closing tag, maybe you could recommend a nice WYSIWYG editor that would show the content of my f.text_area() ? This would be a bonus, not an actual answer to my question

Email rendering engine ?

I am now aware that different email clients can render the email client differently. I will ignore this for now. So the way the preview is rendered doesn't matter. I like the rendering of letter_opener however

Current Code

View > Controller > Mailer

my_email_view.html.erb

<%= form_tag some_mailing_list_path %>
  <%= fields_for :email do |f| %>
  <!-- f.text_field(:subject, ....), etc -->
  <% end %>

  <%= submit_tag("Send email") %>
  <%= submit_tag("Preview") %>
<% end %>

my_controller.rb

before_action :prep_email # Strong parameters, define @mail with form contents

# Handles the POST 
def some_action
  check(:to, :from, :subject) # I check the parameters in private functions
  if email_alright? # Above checks will raise a flag if something went wrong
      if Rails.env.production?
        MailingListsMailer.my_action(@mail).deliver_later
      else
        MailingListsMailer.my_action(@mail).deliver_now
      end
      flash.notice = "Email sent"
      redirect_to :back
    else
      redirect_to :back
    end
end

mailing_list_mailer.rb

def my_action(message)
    format_mail_params(message) # Will set more variables
    @etude = etude
    @include_reference = message[:include_reference]
    @include_description = message[:include_description]
    dst = Proc.new { read_emails_file }
    mail(
      to: dst,
      from: message[:from],
      subject: @subject_full)
  end
Community
  • 1
  • 1
Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164
  • What email client are you targeting? An email viewed in Outlook may look very different from when it is rendered by Gmail or Hotmail or Thunderbird. –  Feb 20 '15 at 21:04
  • There is really a difference between email clients ? Well when I said "how it really looks like", I meant after the rails application inserted database-related content. I do have some HTML/CSS styles in some emails, but I guess it's ok if they do not look exactly the same between email clients. – Cyril Duchon-Doris Feb 20 '15 at 21:11
  • 1
    A brief description of the [current state of html email](http://en.wikipedia.org/wiki/HTML_email#Compatibility). –  Feb 20 '15 at 21:28
  • Thanks for the info. That's definitely something I'll keep in mind. Let's say for this question that I'm looking for a way to produce an output similar to the `letter_opener` gem, or even just loading the email .erb template after processing by rails would be enough – Cyril Duchon-Doris Feb 20 '15 at 21:43

2 Answers2

1

Question update: based on your pseudocode, this is a simple case of creating a status update model and emailing the update to a mailing list.

There are several ways you can go about it, but I'd suggest that you keep things simple and avoid using gems.

<%= link_to "New update", new_status_update_path, class: 'button' %>

Model

class StatusUpdate
  belongs_to :sender, class_name: 'User'
  belongs_to :mailing_list
end

Controller

class StatusUpdateController
   def new
      @status_update = StatusUpdate.new
   end

   def create
      @status_update = StatusUpdate.create(status_update_params)
      @status_update.mailing_list = MailingList.where(whichever_mailing_list)
      if @status_update.save
        redirect_to :action => "preview", :status_update => @status_update
      end
   end

   def preview
     @status_update = StatusUpdate.where(id: params[:id]).first
     @mailing_list = MailingList.where(id: @status_update.mailing_list_id)
   end

   def send
      @status_update = StatusUpdate.where(id:params[:status_update_id]).first
      Mailer.status_update_email(@status_update).deliver
   end
end

status_updates/new.html.erb

<%= simple_form_for(@status_update) do |f| %>    
    <%= f.input :title %> 
    <%= f.input :content, as: :text %>
    <%= f.button :submit, 'Post update' %>
<% end %>

status_updates/preview.html.erb

<h1>Preview</h1>
<%= simple_form_for(@status_update, :url => url_for(:controller => 'StatusUpdateController, :action => 'send') do |f| %>

    <%= f.input :subject %>

    <div class="email-render-container">
      <%= @status_update.content %>
    </div>

    <p>Make changes</p>
    <%= f.input :content, as: :text %>

    <%= f.button :submit, 'Approve and send emails' %>
<% end %>

If I were you, I'd do away with the preview feature. If you're loading content from a template and all you're worried about are potential duplicate content, just do this:

Controller

class StatusUpdateController
  def new
      @status_update = StatusUpdate.new
      template = UpdateTemplate.where(however_you_assign_the_template)
      @status_update.content = template.content
  end

  def create
      @status_update = StatusUpdate.create(status_update_params)
      @status_update.mailing_list = MailingList.where(whichever_mailing_list)
      if @status_update.save
        Mailer.status_update_email(@status_update).deliver
      end
   end
end

and style the new status update form with css to simulate writing on the actual email template. You'll save your users and yourself a lot of time.


wysiwyg editor

Never trust the end user with the ability to write html. Depending on your needs, I find https://www.froala.com/wysiwyg-editor easy to deploy.

differentiating buttons

Just use a preview icon with a label on your button and/or a subtitle under your button to differentiate your buttons. You don't need much command logic in your view.

Alternatively, if you think that the preview is important to your end users, just use the "preview" button as the next logical step instead of presenting your users with too many unnecessary choices.

Suggestions

Adopting a front end framework like Angularjs makes this sort of use case almost trivially easy, but it may be overkill and comes with steep learning curve if you're not familiar with it.

Ryan.lay
  • 1,741
  • 2
  • 17
  • 30
  • Hmm wait, you suggest that I use an `email` model ? So I should have one email model per type of email I'm sending ? So far I never considered saving emails to the DB, but that can actually be a good idea... – Cyril Duchon-Doris Jul 22 '15 at 11:17
  • @CyrilDD Its just a placeholder for whichever model you're tracking, as you didn't expand on how you're tracking the project updates. It could be the notifications model or the status_update model or any model you prefer. I'll edit the answer to make this clearer. – Ryan.lay Jul 22 '15 at 12:33
  • @CyrilDD If you need anything more specific, it would help if you posted up some code detailing how you're implementing this feature. – Ryan.lay Jul 22 '15 at 12:52
  • Yes you're right, I'll add details of my current implementation. I'm not really tracking a model actually. – Cyril Duchon-Doris Jul 22 '15 at 13:19
  • 1
    Hmm yes I like this flow of `new > save_preview > validate_preview > send`. I will have to work on it a bit more, for my email templates were generated using a tool, which produced horrible code (I'm not sure I can reproduce the style of the email inside the ` – Cyril Duchon-Doris Jul 22 '15 at 16:21
  • @CyrilDD Your email templates are not horrible code, they're inline styles, which are needed for html emails. If it makes sense for your app, you can approximate the look of the email with css, if it's just an internal app and you only need the content of the email, then don't waste your time with the css and just validate the content. – Ryan.lay Jul 22 '15 at 23:51
0

Take a look at letter_opener gem. It was created by Ryan Bates, the Railscasts guy.

Eric Remer
  • 11
  • 3
  • Thanks, it's interesting, but then previsualisation is just an optional step, the project manager should still be able to send the email for real afterwards ! – Cyril Duchon-Doris Feb 20 '15 at 14:29