diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6
index 9eeb9f87b35..57c4893fe21 100644
--- a/app/assets/javascripts/discourse/models/user.js.es6
+++ b/app/assets/javascripts/discourse/models/user.js.es6
@@ -158,6 +158,7 @@ const User = RestModel.extend({
'external_links_in_new_tab',
'email_digests',
'email_direct',
+ 'email_in_reply_to',
'email_private_messages',
'email_previous_replies',
'dynamic_favicon',
diff --git a/app/assets/javascripts/discourse/templates/user/preferences.hbs b/app/assets/javascripts/discourse/templates/user/preferences.hbs
index 4c26f028cd4..c0aa984089e 100644
--- a/app/assets/javascripts/discourse/templates/user/preferences.hbs
+++ b/app/assets/javascripts/discourse/templates/user/preferences.hbs
@@ -180,6 +180,7 @@
{{combo-box valueAttribute="value" content=previousRepliesOptions value=model.user_option.email_previous_replies}}
+ {{preference-checkbox labelKey="user.email_in_reply_to" checked=model.user_option.email_in_reply_to}}
{{preference-checkbox labelKey="user.email_private_messages" checked=model.user_option.email_private_messages}}
{{preference-checkbox labelKey="user.email_direct" checked=model.user_option.email_direct}}
{{preference-checkbox labelKey="user.mailing_list_mode" checked=model.user_option.mailing_list_mode}}
diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb
index 018fba10251..9f630c477f1 100644
--- a/app/mailers/user_notifications.rb
+++ b/app/mailers/user_notifications.rb
@@ -193,9 +193,9 @@ class UserNotifications < ActionMailer::Base
include UserNotificationsHelper
end
- def self.get_context_posts(post, topic_user)
- user_option = topic_user.try(:user).try(:user_option)
- if user_option && (user_option.email_previous_replies == UserOption.previous_replies_type[:never])
+ def self.get_context_posts(post, topic_user, user)
+
+ if user.user_option.email_previous_replies == UserOption.previous_replies_type[:never]
return []
end
@@ -210,7 +210,7 @@ class UserNotifications < ActionMailer::Base
.order('created_at desc')
.limit(SiteSetting.email_posts_context)
- if topic_user && topic_user.last_emailed_post_number && user_option.try(:email_previous_replies) == UserOption.previous_replies_type[:unless_emailed]
+ if topic_user && topic_user.last_emailed_post_number && user.user_option.email_previous_replies == UserOption.previous_replies_type[:unless_emailed]
context_posts = context_posts.where("post_number > ?", topic_user.last_emailed_post_number)
end
@@ -280,7 +280,7 @@ class UserNotifications < ActionMailer::Base
context = ""
tu = TopicUser.get(post.topic_id, user)
- context_posts = self.class.get_context_posts(post, tu)
+ context_posts = self.class.get_context_posts(post, tu, user)
# make .present? cheaper
context_posts = context_posts.to_a
@@ -296,11 +296,13 @@ class UserNotifications < ActionMailer::Base
if opts[:use_template_html]
topic_excerpt = post.excerpt.gsub("\n", " ") if post.is_first_post? && post.excerpt
else
+ in_reply_to_post = post.reply_to_post if user.user_option.email_in_reply_to
html = UserNotificationRenderer.new(Rails.configuration.paths["app/views"]).render(
template: 'email/notification',
format: :html,
locals: { context_posts: context_posts,
post: post,
+ in_reply_to_post: in_reply_to_post,
classes: RTL.new(user).css_class
}
)
diff --git a/app/models/user_option.rb b/app/models/user_option.rb
index 53e9bbad790..0e40e9e81ef 100644
--- a/app/models/user_option.rb
+++ b/app/models/user_option.rb
@@ -16,6 +16,7 @@ class UserOption < ActiveRecord::Base
self.automatically_unpin_topics = SiteSetting.default_topics_automatic_unpin
self.email_private_messages = SiteSetting.default_email_private_messages
self.email_previous_replies = SiteSetting.default_email_previous_replies
+ self.email_in_reply_to = SiteSetting.default_email_in_reply_to
self.enable_quoting = SiteSetting.default_other_enable_quoting
self.external_links_in_new_tab = SiteSetting.default_other_external_links_in_new_tab
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
index bf43b41a36f..413ee9c2edd 100644
--- a/app/serializers/user_option_serializer.rb
+++ b/app/serializers/user_option_serializer.rb
@@ -14,7 +14,8 @@ class UserOptionSerializer < ApplicationSerializer
:edit_history_public,
:auto_track_topics_after_msecs,
:new_topic_duration_minutes,
- :email_previous_replies
+ :email_previous_replies,
+ :email_in_reply_to
def include_edit_history_public?
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index 3b24efff08f..0fa1f0b6fe9 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -21,7 +21,8 @@ class UserUpdater
:digest_after_days,
:new_topic_duration_minutes,
:auto_track_topics_after_msecs,
- :email_previous_replies
+ :email_previous_replies,
+ :email_in_reply_to
]
def initialize(actor, user)
@@ -53,10 +54,10 @@ class UserUpdater
save_options = false
- OPTION_ATTR.each do |attribute|
- if attributes[attribute].present?
- save_options = true
+ OPTION_ATTR.each do |attribute|
+ if attributes.key?(attribute)
+ save_options = true
if [true,false].include?(user.user_option.send(attribute))
val = attributes[attribute].to_s == 'true'
diff --git a/app/views/email/_post.html.erb b/app/views/email/_post.html.erb
index c081fb5afda..250d1e6d70d 100644
--- a/app/views/email/_post.html.erb
+++ b/app/views/email/_post.html.erb
@@ -1,4 +1,4 @@
-
+
@@ -23,7 +23,7 @@
|
- <%= format_for_email(post.cooked) %> |
+ <%= format_for_email(use_excerpt ? post.excerpt : post.cooked) %> |
diff --git a/app/views/email/notification.html.erb b/app/views/email/notification.html.erb
index 681dc96afcc..363fa65ca44 100644
--- a/app/views/email/notification.html.erb
+++ b/app/views/email/notification.html.erb
@@ -2,17 +2,22 @@
- <%= render partial: 'email/post', locals: { post: post } %>
+ <%= render partial: 'email/post', locals: { post: post, use_excerpt: false } %>
+
+ <% if in_reply_to_post.present? || context_posts.present? %>
+
+
+ <% end %>
+
+ <% if in_reply_to_post.present? %>
+ <%= t "user_notifications.in_reply_to" %>
+ <%= render partial: 'email/post', locals: { post: in_reply_to_post, use_excerpt: true} %>
+ <% end %>
<% if context_posts.present? %>
-
-
-
-
<%= t "user_notifications.previous_discussion" %>
-
<% context_posts.each do |p| %>
- <%= render partial: 'email/post', locals: { post: p } %>
+ <%= render partial: 'email/post', locals: { post: p, use_excerpt: false } %>
<% end %>
<% end %>
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 8e434f3bd32..d160ed2e518 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -628,7 +628,7 @@ en:
website: "Web Site"
email_settings: "Email"
email_previous_replies:
- title: "Include previous replies"
+ title: "Include previous replies at the bottom of emails"
unless_emailed: "unless previously sent"
always: "always"
never: "never"
@@ -639,6 +639,7 @@ en:
weekly: "weekly"
every_two_weeks: "every two weeks"
+ email_in_reply_to: "Include an excerpt of replied to post in emails"
email_direct: "Send me an email when someone quotes me, replies to my post, mentions my @username, or invites me to a topic"
email_private_messages: "Send me an email when someone messages me"
email_always: "Send me email notifications even when I am active on the site"
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 431b7d7f659..ddda0334662 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -1243,6 +1243,8 @@ en:
default_email_always: "Send an email notification even when the user is active by default."
default_email_previous_replies: "Include previous replies in emails by default."
+ default_email_in_reply_to: "Include excerpt of replied to post in emails by default."
+
default_other_new_topic_duration_minutes: "Global default condition for which a topic is considered new."
default_other_auto_track_topics_after_msecs: "Global default time before a topic is automatically tracked."
default_other_external_links_in_new_tab: "Open external links in a new tab by default."
@@ -1995,6 +1997,7 @@ en:
user_notifications:
previous_discussion: "Previous Replies"
+ in_reply_to: "In Reply To"
unsubscribe:
title: "Unsubscribe"
description: "Not interested in getting these emails? No problem! Click below to unsubscribe instantly:"
diff --git a/config/site_settings.yml b/config/site_settings.yml
index 64990a3e2e6..9657a80997e 100644
--- a/config/site_settings.yml
+++ b/config/site_settings.yml
@@ -1063,7 +1063,9 @@ user_preferences:
default_email_always: false
default_email_previous_replies:
enum: 'PreviousRepliesSiteSetting'
- default: 1
+ default: 2
+ default_email_in_reply_to:
+ default: true
default_other_new_topic_duration_minutes:
enum: 'NewTopicDurationSiteSetting'
diff --git a/db/migrate/20160225095306_add_email_in_reply_to_to_user_options.rb b/db/migrate/20160225095306_add_email_in_reply_to_to_user_options.rb
new file mode 100644
index 00000000000..3f853335809
--- /dev/null
+++ b/db/migrate/20160225095306_add_email_in_reply_to_to_user_options.rb
@@ -0,0 +1,11 @@
+class AddEmailInReplyToToUserOptions < ActiveRecord::Migration
+ def up
+ add_column :user_options, :email_in_reply_to, :boolean, null: false, default: true
+ change_column :user_options, :email_previous_replies, :integer, default: 2, null: false
+ execute 'UPDATE user_options SET email_previous_replies = 2'
+ end
+
+ def down
+ remove_column :user_options, :email_in_reply_to
+ end
+end
diff --git a/spec/mailers/user_notifications_spec.rb b/spec/mailers/user_notifications_spec.rb
index a58c2d16f53..4123b40da14 100644
--- a/spec/mailers/user_notifications_spec.rb
+++ b/spec/mailers/user_notifications_spec.rb
@@ -15,11 +15,16 @@ describe UserNotifications do
_post7 = Fabricate(:post, topic: post1.topic, post_type: Post.types[:whisper])
last = Fabricate(:post, topic: post1.topic)
+ post1.user.user_option.email_previous_replies = UserOption.previous_replies_type[:always]
+
# default is only post #1
- expect(UserNotifications.get_context_posts(last, nil).count).to eq(1)
+ expect(UserNotifications.get_context_posts(last, nil, post1.user).count).to eq(1)
# staff members can also see the whisper
- tu = TopicUser.new(topic: post1.topic, user: build(:moderator))
- expect(UserNotifications.get_context_posts(last, tu).count).to eq(2)
+ moderator = build(:moderator)
+ moderator.user_option = UserOption.new
+ moderator.user_option.email_previous_replies = UserOption.previous_replies_type[:always]
+ tu = TopicUser.new(topic: post1.topic, user: moderator)
+ expect(UserNotifications.get_context_posts(last, tu, tu.user).count).to eq(2)
end
it "allows users to control context" do
@@ -32,13 +37,15 @@ describe UserNotifications do
topic_user = TopicUser.find_by(user_id: user.id, topic_id: post1.topic_id)
# to avoid reloads after update_columns
user = topic_user.user
- expect(UserNotifications.get_context_posts(post3, topic_user).count).to eq(1)
+ user.user_option.update_columns(email_previous_replies: UserOption.previous_replies_type[:unless_emailed])
+
+ expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(1)
user.user_option.update_columns(email_previous_replies: UserOption.previous_replies_type[:never])
- expect(UserNotifications.get_context_posts(post3, topic_user).count).to eq(0)
+ expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(0)
user.user_option.update_columns(email_previous_replies: UserOption.previous_replies_type[:always])
- expect(UserNotifications.get_context_posts(post3, topic_user).count).to eq(2)
+ expect(UserNotifications.get_context_posts(post3, topic_user, user).count).to eq(2)
end
end
@@ -110,12 +117,14 @@ describe UserNotifications do
let(:response_by_user) { Fabricate(:user, name: "John Doe") }
let(:category) { Fabricate(:category, name: 'India') }
let(:topic) { Fabricate(:topic, category: category) }
- let(:post) { Fabricate(:post, topic: topic) }
- let(:response) { Fabricate(:post, topic: post.topic, user: response_by_user)}
+ let(:post) { Fabricate(:post, topic: topic, raw: 'This is My super duper cool topic') }
+ let(:response) { Fabricate(:post, reply_to_post_number: 1, topic: post.topic, user: response_by_user)}
let(:user) { Fabricate(:user) }
let(:notification) { Fabricate(:notification, user: user) }
it 'generates a correct email' do
+
+ # Fabricator is not fabricating this ...
SiteSetting.enable_names = true
SiteSetting.display_name_on_posts = true
mail = UserNotifications.user_replied(response.user,
@@ -123,25 +132,41 @@ describe UserNotifications do
notification_type: notification.notification_type,
notification_data_hash: notification.data_hash
)
-
# from should include full user name
expect(mail[:from].display_names).to eql(['John Doe'])
# subject should include category name
expect(mail.subject).to match(/India/)
+ mail_html = mail.html_part.to_s
+
+ expect(mail_html.scan(/My super duper cool topic/).count).to eq(1)
+ expect(mail_html.scan(/In Reply To/).count).to eq(1)
+
# 2 "visit topic" link
- expect(mail.html_part.to_s.scan(/Visit Topic/).count).to eq(2)
+ expect(mail_html.scan(/Visit Topic/).count).to eq(2)
# 2 respond to links cause we have 1 context post
- expect(mail.html_part.to_s.scan(/to respond/).count).to eq(2)
+ expect(mail_html.scan(/to respond/).count).to eq(2)
# 1 unsubscribe
- expect(mail.html_part.to_s.scan(/To unsubscribe/).count).to eq(1)
+ expect(mail_html.scan(/To unsubscribe/).count).to eq(1)
# side effect, topic user is updated with post number
tu = TopicUser.get(post.topic_id, response.user)
expect(tu.last_emailed_post_number).to eq(response.post_number)
+
+
+ # no In Reply To if user opts out
+ response.user.user_option.email_in_reply_to = false
+ mail = UserNotifications.user_replied(response.user,
+ post: response,
+ notification_type: notification.notification_type,
+ notification_data_hash: notification.data_hash
+ )
+
+
+ expect(mail.html_part.to_s.scan(/In Reply To/).count).to eq(0)
end
end
@@ -169,8 +194,8 @@ describe UserNotifications do
# subject should not include category name
expect(mail.subject).not_to match(/Uncategorized/)
- # 2 respond to links cause we have 1 context post
- expect(mail.html_part.to_s.scan(/to respond/).count).to eq(2)
+ # 1 respond to links as no context by default
+ expect(mail.html_part.to_s.scan(/to respond/).count).to eq(1)
# 1 unsubscribe link
expect(mail.html_part.to_s.scan(/To unsubscribe/).count).to eq(1)
diff --git a/spec/services/user_updater_spec.rb b/spec/services/user_updater_spec.rb
index 7866206bfee..f1ff985dc9e 100644
--- a/spec/services/user_updater_spec.rb
+++ b/spec/services/user_updater_spec.rb
@@ -48,7 +48,8 @@ describe UserUpdater do
mailing_list_mode: true,
digest_after_days: "8",
new_topic_duration_minutes: 100,
- auto_track_topics_after_msecs: 101
+ auto_track_topics_after_msecs: 101,
+ email_in_reply_to: false
)
user.reload
@@ -58,6 +59,7 @@ describe UserUpdater do
expect(user.user_option.digest_after_days).to eq 8
expect(user.user_option.new_topic_duration_minutes).to eq 100
expect(user.user_option.auto_track_topics_after_msecs).to eq 101
+ expect(user.user_option.email_in_reply_to).to eq false
end
context 'when update succeeds' do