FEATURE: per-topic unsubscribe option in emails
This commit is contained in:
parent
56abd247e1
commit
6669a2d94d
|
@ -24,8 +24,11 @@ export default Ember.Component.extend(StringBuffer, {
|
||||||
}.on('willDestroyElement'),
|
}.on('willDestroyElement'),
|
||||||
|
|
||||||
renderString(buffer) {
|
renderString(buffer) {
|
||||||
|
const title = this.get('title');
|
||||||
|
if (title) {
|
||||||
|
buffer.push("<h4 class='title'>" + title + "</h4>");
|
||||||
|
}
|
||||||
|
|
||||||
buffer.push("<h4 class='title'>" + this.get('title') + "</h4>");
|
|
||||||
buffer.push("<button class='btn standard dropdown-toggle' data-toggle='dropdown'>");
|
buffer.push("<button class='btn standard dropdown-toggle' data-toggle='dropdown'>");
|
||||||
buffer.push(this.get('text'));
|
buffer.push(this.get('text'));
|
||||||
buffer.push("</button>");
|
buffer.push("</button>");
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import ObjectController from "discourse/controllers/object";
|
||||||
|
|
||||||
|
export default ObjectController.extend({
|
||||||
|
|
||||||
|
stopNotificiationsText: function() {
|
||||||
|
return I18n.t("topic.unsubscribe.stop_notifications", { title: this.get("model.fancyTitle") });
|
||||||
|
}.property("model.fancyTitle"),
|
||||||
|
|
||||||
|
})
|
|
@ -10,6 +10,7 @@ export default function() {
|
||||||
this.route('fromParamsNear', { path: '/:nearPost' });
|
this.route('fromParamsNear', { path: '/:nearPost' });
|
||||||
});
|
});
|
||||||
this.resource('topicBySlug', { path: '/t/:slug' });
|
this.resource('topicBySlug', { path: '/t/:slug' });
|
||||||
|
this.route('topicUnsubscribe', { path: '/t/:slug/:id/unsubscribe' });
|
||||||
|
|
||||||
this.resource('discovery', { path: '/' }, function() {
|
this.resource('discovery', { path: '/' }, function() {
|
||||||
// top
|
// top
|
||||||
|
|
|
@ -2,30 +2,30 @@
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
|
|
||||||
// Avoid default model hook
|
// Avoid default model hook
|
||||||
model: function(p) { return p; },
|
model(params) { return params; },
|
||||||
|
|
||||||
setupController: function(controller, params) {
|
setupController(controller, params) {
|
||||||
params = params || {};
|
params = params || {};
|
||||||
params.track_visit = true;
|
params.track_visit = true;
|
||||||
var topic = this.modelFor('topic'),
|
|
||||||
postStream = topic.get('postStream');
|
|
||||||
|
|
||||||
var topicController = this.controllerFor('topic'),
|
const self = this,
|
||||||
|
topic = this.modelFor('topic'),
|
||||||
|
postStream = topic.get('postStream'),
|
||||||
|
topicController = this.controllerFor('topic'),
|
||||||
topicProgressController = this.controllerFor('topic-progress'),
|
topicProgressController = this.controllerFor('topic-progress'),
|
||||||
composerController = this.controllerFor('composer');
|
composerController = this.controllerFor('composer');
|
||||||
|
|
||||||
// I sincerely hope no topic gets this many posts
|
// I sincerely hope no topic gets this many posts
|
||||||
if (params.nearPost === "last") { params.nearPost = 999999999; }
|
if (params.nearPost === "last") { params.nearPost = 999999999; }
|
||||||
|
|
||||||
var self = this;
|
|
||||||
params.forceLoad = true;
|
params.forceLoad = true;
|
||||||
postStream.refresh(params).then(function () {
|
|
||||||
|
|
||||||
|
postStream.refresh(params).then(function () {
|
||||||
// TODO we are seeing errors where closest post is null and this is exploding
|
// TODO we are seeing errors where closest post is null and this is exploding
|
||||||
// we need better handling and logging for this condition.
|
// we need better handling and logging for this condition.
|
||||||
|
|
||||||
// The post we requested might not exist. Let's find the closest post
|
// The post we requested might not exist. Let's find the closest post
|
||||||
var closestPost = postStream.closestPostForPostNumber(params.nearPost || 1),
|
const closestPost = postStream.closestPostForPostNumber(params.nearPost || 1),
|
||||||
closest = closestPost.get('post_number'),
|
closest = closestPost.get('post_number'),
|
||||||
progress = postStream.progressIndexOfPost(closestPost);
|
progress = postStream.progressIndexOfPost(closestPost);
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ export default Discourse.Route.extend({
|
||||||
Ember.run.scheduleOnce('afterRender', function() {
|
Ember.run.scheduleOnce('afterRender', function() {
|
||||||
self.appEvents.trigger('post:highlight', closest);
|
self.appEvents.trigger('post:highlight', closest);
|
||||||
});
|
});
|
||||||
|
|
||||||
Discourse.URL.jumpToPost(closest);
|
Discourse.URL.jumpToPost(closest);
|
||||||
|
|
||||||
if (topic.present('draft')) {
|
if (topic.present('draft')) {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import PostStream from "discourse/models/post-stream";
|
||||||
|
|
||||||
|
export default Discourse.Route.extend({
|
||||||
|
model(params) {
|
||||||
|
const topic = this.store.createRecord("topic", { id: params.id });
|
||||||
|
return PostStream.loadTopicView(params.id).then(json => {
|
||||||
|
topic.updateFromJson(json);
|
||||||
|
return topic;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
afterModel(topic) {
|
||||||
|
// hide the notification reason text
|
||||||
|
topic.set("details.notificationReasonText", null);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
didTransition() {
|
||||||
|
this.controllerFor("application").set("showFooter", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="container">
|
||||||
|
<p>
|
||||||
|
{{{stopNotificiationsText}}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{i18n "topic.unsubscribe.change_notification_state"}} {{topic-notifications-button topic=model}}
|
||||||
|
</p>
|
||||||
|
</div>
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default Discourse.View.extend({
|
||||||
|
classNames: ["topic-unsubscribe"]
|
||||||
|
});
|
|
@ -63,3 +63,15 @@
|
||||||
// Top of bullet aligns with top of line - adjust line height to vertically align bullet.
|
// Top of bullet aligns with top of line - adjust line height to vertically align bullet.
|
||||||
line-height: 0.8;
|
line-height: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topic-unsubscribe {
|
||||||
|
.notification-options {
|
||||||
|
display: inline-block;
|
||||||
|
.dropdown-toggle {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.dropdown-menu {
|
||||||
|
bottom: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,11 +24,12 @@ class TopicsController < ApplicationController
|
||||||
:bulk,
|
:bulk,
|
||||||
:reset_new,
|
:reset_new,
|
||||||
:change_post_owners,
|
:change_post_owners,
|
||||||
:bookmark]
|
:bookmark,
|
||||||
|
:unsubscribe]
|
||||||
|
|
||||||
before_filter :consider_user_for_promotion, only: :show
|
before_filter :consider_user_for_promotion, only: :show
|
||||||
|
|
||||||
skip_before_filter :check_xhr, only: [:show, :feed]
|
skip_before_filter :check_xhr, only: [:show, :unsubscribe, :feed]
|
||||||
|
|
||||||
def id_for_slug
|
def id_for_slug
|
||||||
topic = Topic.find_by(slug: params[:slug].downcase)
|
topic = Topic.find_by(slug: params[:slug].downcase)
|
||||||
|
@ -94,6 +95,26 @@ class TopicsController < ApplicationController
|
||||||
raise ex
|
raise ex
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unsubscribe
|
||||||
|
@topic_view = TopicView.new(params[:topic_id], current_user)
|
||||||
|
|
||||||
|
if slugs_do_not_match || (!request.format.json? && params[:slug].blank?)
|
||||||
|
return redirect_to @topic_view.topic.unsubscribe_url, status: 301
|
||||||
|
end
|
||||||
|
|
||||||
|
tu = TopicUser.find_by(user_id: current_user.id, topic_id: params[:topic_id])
|
||||||
|
|
||||||
|
if tu.notification_level > TopicUser.notification_levels[:regular]
|
||||||
|
tu.notification_level = TopicUser.notification_levels[:regular]
|
||||||
|
else
|
||||||
|
tu.notification_level = TopicUser.notification_levels[:muted]
|
||||||
|
end
|
||||||
|
|
||||||
|
tu.save!
|
||||||
|
|
||||||
|
perform_show_response
|
||||||
|
end
|
||||||
|
|
||||||
def wordpress
|
def wordpress
|
||||||
params.require(:best)
|
params.require(:best)
|
||||||
params.require(:topic_id)
|
params.require(:topic_id)
|
||||||
|
@ -476,6 +497,7 @@ class TopicsController < ApplicationController
|
||||||
format.html do
|
format.html do
|
||||||
@description_meta = @topic_view.topic.excerpt
|
@description_meta = @topic_view.topic.excerpt
|
||||||
store_preloaded("topic_#{@topic_view.topic.id}", MultiJson.dump(topic_view_serializer))
|
store_preloaded("topic_#{@topic_view.topic.id}", MultiJson.dump(topic_view_serializer))
|
||||||
|
render :show
|
||||||
end
|
end
|
||||||
|
|
||||||
format.json do
|
format.json do
|
||||||
|
|
|
@ -292,6 +292,7 @@ class UserNotifications < ActionMailer::Base
|
||||||
context: context,
|
context: context,
|
||||||
username: username,
|
username: username,
|
||||||
add_unsubscribe_link: true,
|
add_unsubscribe_link: true,
|
||||||
|
unsubscribe_url: post.topic.unsubscribe_url,
|
||||||
allow_reply_by_email: allow_reply_by_email,
|
allow_reply_by_email: allow_reply_by_email,
|
||||||
use_site_subject: use_site_subject,
|
use_site_subject: use_site_subject,
|
||||||
add_re_to_subject: add_re_to_subject,
|
add_re_to_subject: add_re_to_subject,
|
||||||
|
@ -306,9 +307,7 @@ class UserNotifications < ActionMailer::Base
|
||||||
}
|
}
|
||||||
|
|
||||||
# If we have a display name, change the from address
|
# If we have a display name, change the from address
|
||||||
if from_alias.present?
|
email_opts[:from_alias] = from_alias if from_alias.present?
|
||||||
email_opts[:from_alias] = from_alias
|
|
||||||
end
|
|
||||||
|
|
||||||
TopicUser.change(user.id, post.topic_id, last_emailed_post_number: post.post_number)
|
TopicUser.change(user.id, post.topic_id, last_emailed_post_number: post.post_number)
|
||||||
|
|
||||||
|
|
|
@ -716,6 +716,10 @@ class Topic < ActiveRecord::Base
|
||||||
url
|
url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unsubscribe_url
|
||||||
|
"#{url}/unsubscribe"
|
||||||
|
end
|
||||||
|
|
||||||
def clear_pin_for(user)
|
def clear_pin_for(user)
|
||||||
return unless user.present?
|
return unless user.present?
|
||||||
TopicUser.change(user.id, id, cleared_pinned_at: Time.now)
|
TopicUser.change(user.id, id, cleared_pinned_at: Time.now)
|
||||||
|
|
|
@ -8,7 +8,8 @@ class TopicUser < ActiveRecord::Base
|
||||||
scope :tracking, lambda { |topic_id|
|
scope :tracking, lambda { |topic_id|
|
||||||
where(topic_id: topic_id)
|
where(topic_id: topic_id)
|
||||||
.where("COALESCE(topic_users.notification_level, :regular) >= :tracking",
|
.where("COALESCE(topic_users.notification_level, :regular) >= :tracking",
|
||||||
regular: TopicUser.notification_levels[:regular], tracking: TopicUser.notification_levels[:tracking])
|
regular: TopicUser.notification_levels[:regular],
|
||||||
|
tracking: TopicUser.notification_levels[:tracking])
|
||||||
}
|
}
|
||||||
|
|
||||||
# Class methods
|
# Class methods
|
||||||
|
@ -58,13 +59,9 @@ class TopicUser < ActiveRecord::Base
|
||||||
|
|
||||||
def create_lookup(topic_users)
|
def create_lookup(topic_users)
|
||||||
topic_users = topic_users.to_a
|
topic_users = topic_users.to_a
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
return result if topic_users.blank?
|
return result if topic_users.blank?
|
||||||
|
topic_users.each { |ftu| result[ftu.topic_id] = ftu }
|
||||||
topic_users.each do |ftu|
|
|
||||||
result[ftu.topic_id] = ftu
|
|
||||||
end
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,11 +110,9 @@ class TopicUser < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
if attrs[:notification_level]
|
if attrs[:notification_level]
|
||||||
MessageBus.publish("/topic/#{topic_id}",
|
MessageBus.publish("/topic/#{topic_id}", { notification_level_change: attrs[:notification_level] }, user_ids: [user_id])
|
||||||
{notification_level_change: attrs[:notification_level]}, user_ids: [user_id])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
rescue ActiveRecord::RecordNotUnique
|
rescue ActiveRecord::RecordNotUnique
|
||||||
# In case of a race condition to insert, do nothing
|
# In case of a race condition to insert, do nothing
|
||||||
end
|
end
|
||||||
|
@ -127,7 +122,7 @@ class TopicUser < ActiveRecord::Base
|
||||||
user_id = user.is_a?(User) ? user.id : topic
|
user_id = user.is_a?(User) ? user.id : topic
|
||||||
|
|
||||||
now = DateTime.now
|
now = DateTime.now
|
||||||
rows = TopicUser.where({topic_id: topic_id, user_id: user_id}).update_all({last_visited_at: now})
|
rows = TopicUser.where(topic_id: topic_id, user_id: user_id).update_all(last_visited_at: now)
|
||||||
if rows == 0
|
if rows == 0
|
||||||
TopicUser.create(topic_id: topic_id, user_id: user_id, last_visited_at: now, first_visited_at: now)
|
TopicUser.create(topic_id: topic_id, user_id: user_id, last_visited_at: now, first_visited_at: now)
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
<div id='main' class=<%= classes %>>
|
<div id='main' class=<%= classes %>>
|
||||||
|
|
||||||
<%= render :partial => 'email/post', :locals => {:post => post} %>
|
<%= render partial: 'email/post', locals: { post: post } %>
|
||||||
|
|
||||||
<% if context_posts.present? %>
|
<% if context_posts.present? %>
|
||||||
<div class='footer'>
|
<div class='footer'>%{respond_instructions}</div>
|
||||||
%{respond_instructions}
|
|
||||||
</div>
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h4 class='.previous-discussion'><%= t "user_notifications.previous_discussion" %></h4>
|
<h4 class='.previous-discussion'><%= t "user_notifications.previous_discussion" %></h4>
|
||||||
|
|
||||||
<% context_posts.each do |p| %>
|
<% context_posts.each do |p| %>
|
||||||
<%= render :partial => 'email/post', :locals => {:post => p} %>
|
<%= render partial: 'email/post', locals: { post: p } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div class='footer'>
|
<div class='footer'>%{respond_instructions}</div>
|
||||||
%{respond_instructions}
|
<div class='footer'>%{unsubscribe_link}</div>
|
||||||
</div>
|
|
||||||
<div class='footer'>
|
|
||||||
%{unsubscribe_link}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div itemscope itemtype="http://schema.org/EmailMessage" style="display:none">
|
<div itemscope itemtype="http://schema.org/EmailMessage" style="display:none">
|
||||||
<div itemprop="action" itemscope itemtype="http://schema.org/ViewAction">
|
<div itemprop="action" itemscope itemtype="http://schema.org/ViewAction">
|
||||||
<link itemprop="url" href="<%= Discourse.base_url %><%= post.url %>" />
|
<link itemprop="url" href="<%= Discourse.base_url %><%= post.url %>" />
|
||||||
|
|
|
@ -981,6 +981,9 @@ en:
|
||||||
search: "There are no more search results."
|
search: "There are no more search results."
|
||||||
|
|
||||||
topic:
|
topic:
|
||||||
|
unsubscribe:
|
||||||
|
stop_notifications: "You will stop receiving notifications for <strong>{{title}}</strong>."
|
||||||
|
change_notification_state: "You can change your notification state"
|
||||||
filter_to: "{{post_count}} posts in topic"
|
filter_to: "{{post_count}} posts in topic"
|
||||||
create: 'New Topic'
|
create: 'New Topic'
|
||||||
create_long: 'Create a new Topic'
|
create_long: 'Create a new Topic'
|
||||||
|
@ -1014,7 +1017,6 @@ en:
|
||||||
new_posts:
|
new_posts:
|
||||||
one: "there is 1 new post in this topic since you last read it"
|
one: "there is 1 new post in this topic since you last read it"
|
||||||
other: "there are {{count}} new posts in this topic since you last read it"
|
other: "there are {{count}} new posts in this topic since you last read it"
|
||||||
|
|
||||||
likes:
|
likes:
|
||||||
one: "there is 1 like in this topic"
|
one: "there is 1 like in this topic"
|
||||||
other: "there are {{count}} likes in this topic"
|
other: "there are {{count}} likes in this topic"
|
||||||
|
|
|
@ -1849,7 +1849,10 @@ en:
|
||||||
subject_template: "Downloading remote images disabled"
|
subject_template: "Downloading remote images disabled"
|
||||||
text_body_template: "The `download_remote_images_to_local` setting was disabled because the disk space limit at `download_remote_images_threshold` was reached."
|
text_body_template: "The `download_remote_images_to_local` setting was disabled because the disk space limit at `download_remote_images_threshold` was reached."
|
||||||
|
|
||||||
unsubscribe_link: "To unsubscribe from these emails, visit your [user preferences](%{user_preferences_url})."
|
unsubscribe_link: |
|
||||||
|
To unsubscribe from these emails, visit your [user preferences](%{user_preferences_url}).
|
||||||
|
|
||||||
|
To stop receiving notifications about this particular topic, [click here](%{unsubscribe_url}).
|
||||||
|
|
||||||
subject_re: "Re: "
|
subject_re: "Re: "
|
||||||
subject_pm: "[PM] "
|
subject_pm: "[PM] "
|
||||||
|
|
|
@ -434,10 +434,12 @@ Discourse::Application.routes.draw do
|
||||||
# Topic routes
|
# Topic routes
|
||||||
get "t/id_for/:slug" => "topics#id_for_slug"
|
get "t/id_for/:slug" => "topics#id_for_slug"
|
||||||
get "t/:slug/:topic_id/wordpress" => "topics#wordpress", constraints: {topic_id: /\d+/}
|
get "t/:slug/:topic_id/wordpress" => "topics#wordpress", constraints: {topic_id: /\d+/}
|
||||||
get "t/:slug/:topic_id/moderator-liked" => "topics#moderator_liked", constraints: {topic_id: /\d+/}
|
|
||||||
get "t/:topic_id/wordpress" => "topics#wordpress", constraints: {topic_id: /\d+/}
|
get "t/:topic_id/wordpress" => "topics#wordpress", constraints: {topic_id: /\d+/}
|
||||||
get "t/:slug/:topic_id/summary" => "topics#show", defaults: {summary: true}, constraints: {topic_id: /\d+/, post_number: /\d+/}
|
get "t/:slug/:topic_id/moderator-liked" => "topics#moderator_liked", constraints: {topic_id: /\d+/}
|
||||||
get "t/:topic_id/summary" => "topics#show", constraints: {topic_id: /\d+/, post_number: /\d+/}
|
get "t/:slug/:topic_id/summary" => "topics#show", defaults: {summary: true}, constraints: {topic_id: /\d+/}
|
||||||
|
get "t/:slug/:topic_id/unsubscribe" => "topics#unsubscribe", constraints: {topic_id: /\d+/}
|
||||||
|
get "t/:topic_id/unsubscribe" => "topics#unsubscribe", constraints: {topic_id: /\d+/}
|
||||||
|
get "t/:topic_id/summary" => "topics#show", constraints: {topic_id: /\d+/}
|
||||||
put "t/:slug/:topic_id" => "topics#update", constraints: {topic_id: /\d+/}
|
put "t/:slug/:topic_id" => "topics#update", constraints: {topic_id: /\d+/}
|
||||||
put "t/:slug/:topic_id/star" => "topics#star", constraints: {topic_id: /\d+/}
|
put "t/:slug/:topic_id/star" => "topics#star", constraints: {topic_id: /\d+/}
|
||||||
put "t/:topic_id/star" => "topics#star", constraints: {topic_id: /\d+/}
|
put "t/:topic_id/star" => "topics#star", constraints: {topic_id: /\d+/}
|
||||||
|
|
|
@ -21,16 +21,17 @@ module Email
|
||||||
@to = to
|
@to = to
|
||||||
@opts = opts || {}
|
@opts = opts || {}
|
||||||
|
|
||||||
@template_args = {site_name: SiteSetting.email_prefix.presence || SiteSetting.title,
|
@template_args = {
|
||||||
|
site_name: SiteSetting.email_prefix.presence || SiteSetting.title,
|
||||||
base_url: Discourse.base_url,
|
base_url: Discourse.base_url,
|
||||||
user_preferences_url: "#{Discourse.base_url}/my/preferences" }.merge!(@opts)
|
user_preferences_url: "#{Discourse.base_url}/my/preferences",
|
||||||
|
}.merge!(@opts)
|
||||||
|
|
||||||
if @template_args[:url].present?
|
if @template_args[:url].present?
|
||||||
if @opts[:include_respond_instructions] == false
|
if @opts[:include_respond_instructions] == false
|
||||||
@template_args[:respond_instructions] = ''
|
@template_args[:respond_instructions] = ''
|
||||||
else
|
else
|
||||||
@template_args[:respond_instructions] =
|
@template_args[:respond_instructions] = if allow_reply_by_email?
|
||||||
if allow_reply_by_email?
|
|
||||||
I18n.t('user_notifications.reply_by_email', @template_args)
|
I18n.t('user_notifications.reply_by_email', @template_args)
|
||||||
else
|
else
|
||||||
I18n.t('user_notifications.visit_link_to_respond', @template_args)
|
I18n.t('user_notifications.visit_link_to_respond', @template_args)
|
||||||
|
@ -56,8 +57,8 @@ module Email
|
||||||
|
|
||||||
def html_part
|
def html_part
|
||||||
return unless html_override = @opts[:html_override]
|
return unless html_override = @opts[:html_override]
|
||||||
if @opts[:add_unsubscribe_link]
|
|
||||||
|
|
||||||
|
if @opts[:add_unsubscribe_link]
|
||||||
if response_instructions = @template_args[:respond_instructions]
|
if response_instructions = @template_args[:respond_instructions]
|
||||||
respond_instructions = PrettyText.cook(response_instructions).html_safe
|
respond_instructions = PrettyText.cook(response_instructions).html_safe
|
||||||
html_override.gsub!("%{respond_instructions}", respond_instructions)
|
html_override.gsub!("%{respond_instructions}", respond_instructions)
|
||||||
|
|
|
@ -168,7 +168,8 @@ describe Email::MessageBuilder do
|
||||||
|
|
||||||
let(:message_with_unsubscribe) { Email::MessageBuilder.new(to_address,
|
let(:message_with_unsubscribe) { Email::MessageBuilder.new(to_address,
|
||||||
body: 'hello world',
|
body: 'hello world',
|
||||||
add_unsubscribe_link: true) }
|
add_unsubscribe_link: true,
|
||||||
|
unsubscribe_url: "/t/1234/unsubscribe") }
|
||||||
|
|
||||||
it "has an List-Unsubscribe header" do
|
it "has an List-Unsubscribe header" do
|
||||||
expect(message_with_unsubscribe.header_args['List-Unsubscribe']).to be_present
|
expect(message_with_unsubscribe.header_args['List-Unsubscribe']).to be_present
|
||||||
|
|
Loading…
Reference in New Issue