From 366cb1314063feceff80c0beb8d0ade441e5397f Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 24 Jul 2013 17:13:15 +1000 Subject: [PATCH] restyle all user notification emails to use a custom html template --- app/helpers/user_notifications_helper.rb | 8 ++++++ app/mailers/user_notifications.rb | 18 ++++++++++-- app/views/email/_post.html.erb | 22 +++++++++++++++ app/views/email/notification.html.erb | 12 ++++++++ config/locales/server.en.yml | 10 +------ lib/email/message_builder.rb | 36 ++++++++++++++++++++---- lib/email/sender.rb | 11 ++++---- 7 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 app/views/email/_post.html.erb create mode 100644 app/views/email/notification.html.erb diff --git a/app/helpers/user_notifications_helper.rb b/app/helpers/user_notifications_helper.rb index 4317fe31f..79a9861d0 100644 --- a/app/helpers/user_notifications_helper.rb +++ b/app/helpers/user_notifications_helper.rb @@ -9,4 +9,12 @@ module UserNotificationsHelper result end + def correct_top_margin(html, desired) + fragment = Nokogiri::HTML.fragment(html) + if para = fragment.css("p:first").first + para["style"] = "margin-top: #{desired};" + end + fragment.to_html.html_safe + end + end diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb index d1fce949c..c0a054118 100644 --- a/app/mailers/user_notifications.rb +++ b/app/mailers/user_notifications.rb @@ -96,12 +96,16 @@ class UserNotifications < ActionMailer::Base def email_post_markdown(post) result = "[email-indent]\n" - result << "#### #{I18n.t('user_notifications.posted_by', username: post.username, post_date: post.created_at.strftime("%m/%d/%Y"))}\n\n" result << "#{post.raw}\n\n" + result << "#{I18n.t('user_notifications.posted_by', username: post.username, post_date: post.created_at.strftime("%m/%d/%Y"))}\n\n" result << "[/email-indent]\n" result end + class UserNotificationRenderer < ActionView::Base + include UserNotificationsHelper + end + def notification_email(user, opts) @notification = opts[:notification] return unless @notification.present? @@ -119,12 +123,19 @@ class UserNotifications < ActionMailer::Base .limit(SiteSetting.email_posts_context) if context_posts.present? - context << "---\n### #{I18n.t('user_notifications.post_history')}\n" + context << "---\n*#{I18n.t('user_notifications.previous_discussion')}*\n" context_posts.each do |cp| context << email_post_markdown(cp) end end + html = UserNotificationRenderer.new(Rails.configuration.paths["app/views"]).render( + template: 'email/notification', + format: :html, + locals: { context_posts: context_posts, post: @post } + ) + + email_opts = { topic_title: @notification.data_hash[:topic_title], message: email_post_markdown(@post), @@ -135,7 +146,8 @@ class UserNotifications < ActionMailer::Base username: username, add_unsubscribe_link: true, allow_reply_by_email: opts[:allow_reply_by_email], - template: "user_notifications.user_#{notification_type}" + template: "user_notifications.user_#{notification_type}", + html_override: html } # If we have a display name, change the from address diff --git a/app/views/email/_post.html.erb b/app/views/email/_post.html.erb new file mode 100644 index 000000000..0bd0ca941 --- /dev/null +++ b/app/views/email/_post.html.erb @@ -0,0 +1,22 @@ + + + + + + + +
+ + + + + + + + + +
+ <%= post.user.username %> + <%= l post.created_at, format: :short_no_year %>
+ <%= correct_top_margin post.cooked.html_safe, "5px" %> +
diff --git a/app/views/email/notification.html.erb b/app/views/email/notification.html.erb new file mode 100644 index 000000000..b69048976 --- /dev/null +++ b/app/views/email/notification.html.erb @@ -0,0 +1,12 @@ +<%= render :partial => 'email/post', :locals => {:post => post} %> + +<% if context_posts.present? %> +
+

<%= t "user_notifications.previous_discussion" %>

+ + <% context_posts.each do |p| %> + <%= render :partial => 'email/post', :locals => {:post => p} %> + <% end %> +<% end %> + +
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 9c40f254b..356e0e71c 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -934,6 +934,7 @@ en: unsubscribe_link: "To unsubscribe from these emails, visit your [user preferences](%{user_preferences_url})." user_notifications: + previous_discussion: "Previous discussion" unsubscribe: title: "Unsubscribe" description: "Not interested in getting these emails? No problem! Click below to unsubscribe instantly:" @@ -941,7 +942,6 @@ en: reply_by_email: "To respond, reply to this email or visit %{base_url}%{url} in your browser." visit_link_to_respond: "To respond, visit %{base_url}%{url} in your browser." - post_history: "Post History" posted_by: "Posted by %{username} on %{post_date}" user_invited_to_private_message: @@ -954,8 +954,6 @@ en: user_replied: subject_template: "[%{site_name}] new reply to your post in '%{topic_title}'" text_body_template: | - %{username} replied to your post in '%{topic_title}' on %{site_name}: - %{message} %{context} @@ -966,8 +964,6 @@ en: user_quoted: subject_template: "[%{site_name}] %{username} quoted you in '%{topic_title}'" text_body_template: | - %{username} quoted you in '%{topic_title}' on %{site_name}: - %{message} %{context} @@ -978,8 +974,6 @@ en: user_mentioned: subject_template: "[%{site_name}] %{username} mentioned you in '%{topic_title}'" text_body_template: | - ### %{username} mentioned you in '%{topic_title}' on %{site_name}: - %{message} %{context} @@ -990,8 +984,6 @@ en: user_posted: subject_template: "[%{site_name}] new post in '%{topic_title}'" text_body_template: | - %{username} posted in '%{topic_title}' on %{site_name}: - %{message} %{context} diff --git a/lib/email/message_builder.rb b/lib/email/message_builder.rb index 1c15e19f4..55278dbbd 100644 --- a/lib/email/message_builder.rb +++ b/lib/email/message_builder.rb @@ -6,7 +6,9 @@ module Email def build_email(*builder_args) builder = Email::MessageBuilder.new(*builder_args) headers(builder.header_args) if builder.header_args.present? - mail(builder.build_args) + mail(builder.build_args).tap { |message| + message.html_part = builder.html_part if message + } end end @@ -22,11 +24,12 @@ module Email user_preferences_url: "#{Discourse.base_url}/user_preferences" }.merge!(@opts) if @template_args[:url].present? - if allow_reply_by_email? - @template_args[:respond_instructions] = I18n.t('user_notifications.reply_by_email', @template_args) - else - @template_args[:respond_instructions] = I18n.t('user_notifications.visit_link_to_respond', @template_args) - end + @template_args[:respond_instructions] = + if allow_reply_by_email? + I18n.t('user_notifications.reply_by_email', @template_args) + else + I18n.t('user_notifications.visit_link_to_respond', @template_args) + end end end @@ -36,6 +39,27 @@ module Email subject end + def html_part + return unless html_override = @opts[:html_override] + if @opts[:add_unsubscribe_link] + html_override << "
".html_safe + + if response_instructions = @template_args[:respond_instructions] + html_override << PrettyText.cook(response_instructions).html_safe + end + + html_override << PrettyText.cook(I18n.t('unsubscribe_link', template_args)).html_safe + end + + styled = Email::Styles.new(html_override) + styled.format_basic + + Mail::Part.new do + content_type 'text/html; charset=UTF-8' + body styled.to_html + end + end + def body body = @opts[:body] body = I18n.t("#{@opts[:template]}.text_body_template", template_args) if @opts[:template] diff --git a/lib/email/sender.rb b/lib/email/sender.rb index f311d3224..65d523712 100644 --- a/lib/email/sender.rb +++ b/lib/email/sender.rb @@ -32,14 +32,15 @@ module Email renderer = Email::Renderer.new(@message, opts) - @message.html_part = Mail::Part.new do - content_type 'text/html; charset=UTF-8' - body renderer.html + unless @message.html_part + @message.html_part = Mail::Part.new do + content_type 'text/html; charset=UTF-8' + body renderer.html + end end @message.parts[0].body = @message.parts[0].body.to_s.gsub!(/\[\/?email-indent\]/, '') - @message.text_part.content_type = 'text/plain; charset=UTF-8' # Set up the email log @@ -107,4 +108,4 @@ module Email end end -end \ No newline at end of file +end