Project

General

Profile

Feature #36162 » 0001-Add-notification-reason.patch

Marius BĂLTEANU, 2024-01-17 05:56

View differences:

app/models/issue.rb
1120 1120
    notified = notified.map {|n| n.is_a?(Group) ? n.users : n}.flatten
1121 1121
    notified.uniq!
1122 1122
    notified = notified.select {|u| u.active? && u.notify_about?(self)}
1123
    notified.map {|user| user.notification_reason = UserNotificationReason::INVOLVED}
1123 1124

  
1124 1125
    notified += project.notified_users
1125 1126
    notified += project.users.preload(:preference).select(&:notify_about_high_priority_issues?) if priority.high?
app/models/mailer.rb
78 78
  end
79 79

  
80 80
  # Builds a mail for notifying user about a new issue
81
  def issue_add(user, issue)
81
  def issue_add(user, issue, reason = nil)
82 82
    redmine_headers 'Project' => issue.project.identifier,
83 83
                    'Issue-Tracker' => issue.tracker.name,
84 84
                    'Issue-Id' => issue.id,
85 85
                    'Issue-Author' => issue.author.login,
86 86
                    'Issue-Assignee' => assignee_for_header(issue)
87 87
    redmine_headers 'Issue-Priority' => issue.priority.name if issue.priority
88
    redmine_headers 'Reason' => reason if reason
88 89
    message_id issue
89 90
    references issue
90 91
    @author = issue.author
91 92
    @issue = issue
92 93
    @user = user
94
    @reason = reason
93 95
    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
94 96
    subject = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]"
95 97
    subject += " (#{issue.status.name})" if Setting.show_status_changes_in_mail_subject?
......
103 105
  # Example:
104 106
  #   Mailer.deliver_issue_add(issue)
105 107
  def self.deliver_issue_add(issue)
106
    users = issue.notified_users | issue.notified_watchers | issue.notified_mentions
108
    users = issue.notified_users + issue.notified_watchers + issue.notified_mentions
109
    users = UserNotificationReason.reorder_by_priority(users)
110

  
107 111
    users.each do |user|
108
      issue_add(user, issue).deliver_later
112
      issue_add(user, issue, user.notification_reason).deliver_later
109 113
    end
110 114
  end
111 115

  
112 116
  # Builds a mail for notifying user about an issue update
113
  def issue_edit(user, journal)
117
  def issue_edit(user, journal, reason = nil)
114 118
    issue = journal.journalized
115 119
    redmine_headers 'Project' => issue.project.identifier,
116 120
                    'Issue-Tracker' => issue.tracker.name,
......
118 122
                    'Issue-Author' => issue.author.login,
119 123
                    'Issue-Assignee' => assignee_for_header(issue)
120 124
    redmine_headers 'Issue-Priority' => issue.priority.name if issue.priority
125
    redmine_headers 'Reason' => reason if reason
121 126
    message_id journal
122 127
    references issue
123 128
    @author = journal.user
......
126 131
    s += issue.subject
127 132
    @issue = issue
128 133
    @user = user
134
    @reason = reason
129 135
    @journal = journal
130 136
    @journal_details = journal.visible_details
131 137
    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
......
139 145
  # Example:
140 146
  #   Mailer.deliver_issue_edit(journal)
141 147
  def self.deliver_issue_edit(journal)
142
    users  = journal.notified_users | journal.notified_watchers | journal.notified_mentions | journal.journalized.notified_mentions
148
    users = journal.notified_users + journal.notified_mentions + journal.journalized.notified_mentions + journal.notified_watchers
149
    users = UserNotificationReason.reorder_by_priority(users)
150

  
143 151
    users.select! do |user|
144 152
      journal.notes? || journal.visible_details(user).any?
145 153
    end
146 154
    users.each do |user|
147
      issue_edit(user, journal).deliver_later
155
      issue_edit(user, journal, user.notification_reason).deliver_later
148 156
    end
149 157
  end
150 158

  
151 159
  # Builds a mail to user about a new document.
152
  def document_added(user, document, author)
160
  def document_added(user, document, author, reason = nil)
153 161
    redmine_headers 'Project' => document.project.identifier
162
    redmine_headers 'Reason' => reason if reason
154 163
    @author = author
155 164
    @document = document
156 165
    @user = user
166
    @reason = reason
157 167
    @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
158 168
    mail :to => user,
159 169
      :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
......
166 176
  def self.deliver_document_added(document, author)
167 177
    users = document.notified_users
168 178
    users.each do |user|
169
      document_added(user, document, author).deliver_later
179
      document_added(user, document, author, user.notification_reason).deliver_later
170 180
    end
171 181
  end
172 182

  
173 183
  # Builds a mail to user about new attachements.
174
  def attachments_added(user, attachments)
184
  def attachments_added(user, attachments, reason = nil)
175 185
    container = attachments.first.container
176 186
    added_to = ''
177 187
    added_to_url = ''
......
188 198
      added_to = "#{l(:label_document)}: #{container.title}"
189 199
    end
190 200
    redmine_headers 'Project' => container.project.identifier
201
    redmine_headers 'Reason' => reason if reason
191 202
    @attachments = attachments
192 203
    @user = user
204
    @reason = reason
193 205
    @added_to = added_to
194 206
    @added_to_url = added_to_url
195 207
    mail :to => user,
......
210 222
    end
211 223

  
212 224
    users.each do |user|
213
      attachments_added(user, attachments).deliver_later
225
      attachments_added(user, attachments, user.notification_reason).deliver_later
214 226
    end
215 227
  end
216 228

  
217 229
  # Builds a mail to user about a new news.
218
  def news_added(user, news)
230
  def news_added(user, news, reason = nil)
219 231
    redmine_headers 'Project' => news.project.identifier
232
    redmine_headers 'Reason' => reason if reason
220 233
    @author = news.author
221 234
    message_id news
222 235
    references news
223 236
    @news = news
224 237
    @user = user
238
    @reason = reason
225 239
    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
226 240
    mail :to => user,
227 241
      :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
......
232 246
  # Example:
233 247
  #   Mailer.deliver_news_added(news)
234 248
  def self.deliver_news_added(news)
235
    users = news.notified_users | news.notified_watchers_for_added_news
249
    users = news.notified_users + news.notified_watchers_for_added_news
250
    users = UserNotificationReason.reorder_by_priority(users)
251

  
236 252
    users.each do |user|
237
      news_added(user, news).deliver_later
253
      news_added(user, news, user.notification_reason).deliver_later
238 254
    end
239 255
  end
240 256

  
241 257
  # Builds a mail to user about a new news comment.
242
  def news_comment_added(user, comment)
258
  def news_comment_added(user, comment, reason = nil)
243 259
    news = comment.commented
244 260
    redmine_headers 'Project' => news.project.identifier
261
    redmine_headers 'Reason' => reason if reason
245 262
    @author = comment.author
246 263
    message_id comment
247 264
    references news
248 265
    @news = news
249 266
    @comment = comment
250 267
    @user = user
268
    @reason = reason
251 269
    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
252 270
    mail :to => user,
253 271
     :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
......
259 277
  #   Mailer.deliver_news_comment_added(comment)
260 278
  def self.deliver_news_comment_added(comment)
261 279
    news = comment.commented
262
    users = news.notified_users | news.notified_watchers
280
    users = news.notified_users + news.notified_watchers
281
    users = UserNotificationReason.reorder_by_priority(users)
282

  
263 283
    users.each do |user|
264
      news_comment_added(user, comment).deliver_later
284
      news_comment_added(user, comment, user.notification_reason).deliver_later
265 285
    end
266 286
  end
267 287

  
268 288
  # Builds a mail to user about a new message.
269
  def message_posted(user, message)
289
  def message_posted(user, message, reason = nil)
270 290
    redmine_headers 'Project' => message.project.identifier,
271 291
                    'Topic-Id' => (message.parent_id || message.id)
292
    redmine_headers 'Reason' => reason if reason
272 293
    @author = message.author
273 294
    message_id message
274 295
    references message.root
275 296
    @message = message
276 297
    @user = user
298
    @reason = reason
277 299
    @message_url = url_for(message.event_url)
278 300
    mail :to => user,
279 301
      :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
......
285 307
  #   Mailer.deliver_message_posted(message)
286 308
  def self.deliver_message_posted(message)
287 309
    users  = message.notified_users
288
    users |= message.root.notified_watchers
289
    users |= message.board.notified_watchers
310
    users += message.root.notified_watchers
311
    users += message.board.notified_watchers
312
    users = UserNotificationReason.reorder_by_priority(users)
290 313

  
291 314
    users.each do |user|
292
      message_posted(user, message).deliver_later
315
      message_posted(user, message, user.notification_reason).deliver_later
293 316
    end
294 317
  end
295 318

  
296 319
  # Builds a mail to user about a new wiki content.
297
  def wiki_content_added(user, wiki_content)
320
  def wiki_content_added(user, wiki_content, reason = nil)
298 321
    redmine_headers 'Project' => wiki_content.project.identifier,
299 322
                    'Wiki-Page-Id' => wiki_content.page.id
323
    redmine_headers 'Reason' => reason if reason
300 324
    @author = wiki_content.author
301 325
    message_id wiki_content
302 326
    @wiki_content = wiki_content
303 327
    @user = user
328
    @reason = reason
304 329
    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
305 330
                                      :project_id => wiki_content.project,
306 331
                                      :id => wiki_content.page.title)
......
316 341
  # Example:
317 342
  #   Mailer.deliver_wiki_content_added(wiki_content)
318 343
  def self.deliver_wiki_content_added(wiki_content)
319
    users = wiki_content.notified_users | wiki_content.page.wiki.notified_watchers | wiki_content.notified_mentions
344
    users = wiki_content.notified_users + wiki_content.page.wiki.notified_watchers + wiki_content.notified_mentions
345
    users = UserNotificationReason.reorder_by_priority(users)
346

  
320 347
    users.each do |user|
321
      wiki_content_added(user, wiki_content).deliver_later
348
      wiki_content_added(user, wiki_content, user.notification_reason).deliver_later
322 349
    end
323 350
  end
324 351

  
325 352
  # Builds a mail to user about an update of the specified wiki content.
326
  def wiki_content_updated(user, wiki_content)
353
  def wiki_content_updated(user, wiki_content, reason = nil)
327 354
    redmine_headers 'Project' => wiki_content.project.identifier,
328 355
                    'Wiki-Page-Id' => wiki_content.page.id
356
    redmine_headers 'Reason' => reason if reason
329 357
    @author = wiki_content.author
330 358
    message_id wiki_content
331 359
    @wiki_content = wiki_content
332 360
    @user = user
361
    @reason = reason
333 362
    @wiki_content_url =
334 363
      url_for(:controller => 'wiki', :action => 'show',
335 364
              :project_id => wiki_content.project,
......
351 380
  #   Mailer.deliver_wiki_content_updated(wiki_content)
352 381
  def self.deliver_wiki_content_updated(wiki_content)
353 382
    users  = wiki_content.notified_users
354
    users |= wiki_content.page.notified_watchers
355
    users |= wiki_content.page.wiki.notified_watchers
356
    users |= wiki_content.notified_mentions
383
    users += wiki_content.page.notified_watchers
384
    users += wiki_content.page.wiki.notified_watchers
385
    users += wiki_content.notified_mentions
386
    users = UserNotificationReason.reorder_by_priority(users)
357 387

  
358 388
    users.each do |user|
359
      wiki_content_updated(user, wiki_content).deliver_later
389
      wiki_content_updated(user, wiki_content, user.notification_reason).deliver_later
360 390
    end
361 391
  end
362 392

  
......
485 515
        field: (options[:field] && l(options[:field])),
486 516
        value: options[:value])
487 517
    @title = options[:title] && l(options[:title])
518
    @reason = UserNotificationReason::ADMIN
488 519
    @remote_ip = options[:remote_ip] || @sender.remote_ip
489 520
    @url = options[:url] && (options[:url].is_a?(Hash) ? url_for(options[:url]) : options[:url])
490 521
    redmine_headers 'Url' => @url
......
521 552
  # Build a mail to user about application settings changes made by sender.
522 553
  def settings_updated(user, sender, changes, options={})
523 554
    @sender = sender
555
    @reason = UserNotificationReason::ADMIN
524 556
    redmine_headers 'Sender' => sender.login
525 557
    @changes = changes
526 558
    @remote_ip = options[:remote_ip] || @sender.remote_ip
app/models/news.rb
56 56
  end
57 57

  
58 58
  def notified_users
59
    project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)}
59
    users = project.users.select {|user| user.notify_about?(self) && user.allowed_to?(:view_news, project)}
60
    users.map {|user| user.notification_reason = UserNotificationReason::SUBSCRIBED}
61
    users
60 62
  end
61 63

  
62 64
  def recipients
app/models/project.rb
626 626

  
627 627
  # Returns the users that should be notified on project events
628 628
  def notified_users
629
    users.where('members.mail_notification = ? OR users.mail_notification = ?', true, 'all')
629
    notified_users = users.where('members.mail_notification = ? OR users.mail_notification = ?', true, 'all')
630
    notified_users.map {|user| user.notification_reason = UserNotificationReason::SUBSCRIBED}
631
    notified_users
630 632
  end
631 633

  
632 634
  # Returns a scope of all custom fields enabled for project issues
app/models/user.rb
102 102
  attr_accessor :password, :password_confirmation, :generate_password
103 103
  attr_accessor :last_before_login_on
104 104
  attr_accessor :remote_ip
105
  attr_accessor :notification_reason
105 106

  
106 107
  LOGIN_LENGTH_LIMIT = 60
107 108
  MAIL_LENGTH_LIMIT = 254
app/models/user_notification_reason.rb
1
# frozen_string_literal: true
2

  
3
# Redmine - project management software
4
# Copyright (C) 2006-2023  Jean-Philippe Lang
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19

  
20
class UserNotificationReason
21
  INVOLVED = 'involved'
22
  MENTIONED = 'mentioned'
23
  WATCHER = 'watcher'
24
  SUBSCRIBED = 'subscribed'
25
  ADMIN = 'admin'
26

  
27
  REASON_PRIORITY = [
28
    INVOLVED,
29
    MENTIONED,
30
    WATCHER,
31
    SUBSCRIBED,
32
    ADMIN
33
  ].freeze
34

  
35
  def self.reorder_by_priority(users)
36
    users = users.sort_by { |r| priority(r.notification_reason) }
37
    users.uniq!
38
    users
39
  end
40

  
41
  def self.priority(reason)
42
    REASON_PRIORITY.index(reason) || REASON_PRIORITY.length + 1
43
  end
44
end
app/views/layouts/mailer.html.erb
75 75
<% end -%>
76 76
<%= yield %>
77 77
<hr />
78
<% if Setting.emails_footer.present? -%>
79
<span class="footer"><%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer).html_safe %></span>
80
<% end -%>
78
<span class="footer">
79
  <% if @reason %>
80
    <span><%= l("text_notification_reason.#{@reason}") %></span> <br />
81
  <% end %>
82
  <span><%= l(:text_notification_settings, link: link_to(nil, url_for(controller: 'my', action: 'account'))).html_safe %></span>
83
  <% if Setting.emails_footer.present? -%>
84
    <%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer).html_safe %>
85
  <% end -%>
86
</span>
81 87
</body>
82 88
</html>
app/views/layouts/mailer.text.erb
2 2
<%= Setting.emails_header %>
3 3
<% end -%>
4 4
<%= yield %>
5
<% if Setting.emails_footer.present? -%>
6 5
-- 
6
<% if @reason %>
7
<%= l("text_notification_reason.#{@reason}") %>
8
<% end %>
9
<%= l(:text_notification_settings, link: url_for(controller: 'my', action: 'account')) %>
10
<% if Setting.emails_footer.present? -%>
7 11
<%= Setting.emails_footer %>
8 12
<% end -%>
config/locales/en.yml
1414 1414
  text_user_destroy_confirmation: "Are you sure you want to delete this user and remove all references to them? This cannot be undone. Often, locking a user instead of deleting them is the better solution. To confirm, please enter their login (%{login}) below."
1415 1415
  text_project_destroy_enter_identifier: "To confirm, please enter the project's identifier (%{identifier}) below."
1416 1416
  field_name_or_email_or_login: Name, email or login
1417
  text_notification_reason:
1418
    admin: You have received this security notification because you are an administrator.
1419
    subscribed: You have received this notification because you have subscribed to it.
1420
    involved: You have received this notification because you are involved in.
1421
    watcher: You have received this notification because you are watching it.
1422
    mentioned: You have received this notification because you have been mentioned in.
1423
  text_notification_settings: "To change your notification preferences, please click here: %{link}."
config/settings.yml
298 298
ui_theme:
299 299
  default: ''
300 300
emails_footer:
301
  default: |-
302
    You have received this notification because you have either subscribed to it, or are involved in it.
303
    To change your notification preferences, please click here: http://hostname/my/account
301
  default: ''
304 302
gravatar_enabled:
305 303
  default: 0
306 304
gravatar_default:
lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
118 118
          if respond_to?(:visible?)
119 119
            notified.reject! {|user| !visible?(user)}
120 120
          end
121
          notified.map {|user| user.notification_reason = UserNotificationReason::WATCHER}
121 122
          notified
122 123
        end
123 124

  
lib/redmine/acts/mentionable.rb
48 48
          if respond_to?(:visible?)
49 49
            notified.select! {|user| visible?(user)}
50 50
          end
51
          notified.map {|user| user.notification_reason = UserNotificationReason::MENTIONED}
51 52
          notified
52 53
        end
53 54

  
test/test_helper.rb
285 285
    (mail.multipart? ? mail.parts.first : mail).body.encoded
286 286
  end
287 287

  
288
  # Verifies mail notification deliveries match the expected deliveries and the reasons
289
  def assert_mail_deliveries_reasons(expected, deliveries)
290
    # First assert that number of deliveries match the number of expected deliveries
291
    assert_equal expected.size, deliveries.size
292

  
293
    deliveries.each do |mail|
294
      assert_not_nil mail
295

  
296
      # Assert that the email is sent to only one recipient
297
      assert_equal 1, mail.to.size
298

  
299
      recipient = mail.to.first
300

  
301
      # Assert that the actual recipient is part of the expected recipients
302
      assert expected[recipient]
303

  
304
      # Get expected notification reason
305
      reason = expected[recipient]
306
      # Remove recipient from the expected hash
307
      expected.delete(recipient)
308

  
309
      mail_html_part = mail.parts.detect {|part| part.content_type.include?('text/html')}
310
      mail_text_part = mail.parts.detect {|part| part.content_type.include?('text/html')}
311

  
312
      # Assert mail body contains the expected notification reason for both parts (html / text)
313
      assert_include l("text_notification_reason.#{reason}"), mail_html_part.body.encoded
314
      assert_include l("text_notification_reason.#{reason}"), mail_text_part.body.encoded
315

  
316
      # Assert reason header
317
      assert_equal reason, mail.header['X-Redmine-Reason'].to_s
318
    end
319

  
320
    # Assert that we iterate through all the expected recipients
321
    assert_equal 0, expected.size
322
  end
323

  
288 324
  # Returns the lft value for a new root issue
289 325
  def new_issue_lft
290 326
    1
test/unit/comment_test.rb
20 20
require_relative '../test_helper'
21 21

  
22 22
class CommentTest < ActiveSupport::TestCase
23
  include Redmine::I18n
23 24
  fixtures :users, :email_addresses, :news, :comments, :projects, :enabled_modules,
24 25
           :user_preferences, :roles, :members, :member_roles
25 26

  
......
44 45
        Comment.create!(:commented => @news, :author => @jsmith, :comments => "my comment")
45 46
      end
46 47
    end
48

  
49
    recipients = {
50
      "jsmith@somenet.foo" => "watcher",
51
      "dlopper@somenet.foo" => "subscribed",
52
    }
53

  
54
    assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries)
47 55
  end
48 56

  
49 57
  def test_validate
test/unit/mailer_test.rb
486 486
    # @jsmith and @dlopper are members of the project
487 487
    # admin is mentioned
488 488
    # @dlopper won't receive duplicated notifications
489
    assert_equal 3, ActionMailer::Base.deliveries.size
490
    assert_include User.find(1).mail, recipients
491 489
  end
492 490

  
493 491
  def test_issue_add_should_include_enabled_fields
......
543 541
    end
544 542
  end
545 543

  
544
  def test_issue_add_should_contain_notification_reason
545
    issue = Issue.find(1)
546
    assert Mailer.deliver_issue_add(issue)
547

  
548
    recipients = {
549
      "jsmith@somenet.foo" => "involved",
550
      "dlopper@somenet.foo" => "subscribed",
551
    }
552
    assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries)
553
  end
554

  
546 555
  def test_issue_edit_subject_should_include_status_changes_if_setting_is_enabled
547 556
    with_settings :show_status_changes_in_mail_subject => 1 do
548 557
      issue = Issue.find(2)
......
645 654
    ActionMailer::Base.deliveries.clear
646 655
    Mailer.deliver_issue_edit(journal)
647 656

  
648
    # @jsmith and @dlopper are members of the project
649
    # admin is mentioned in the updated description
650
    # @dlopper won't receive duplicated notifications
651
    assert_equal 3, ActionMailer::Base.deliveries.size
652
    assert_include User.find(1).mail, recipients
657
    recipients = {
658
      "jsmith@somenet.foo" => "involved",
659
      "dlopper@somenet.foo" => "involved",
660
      "admin@somenet.foo" => "mentioned",
661
    }
662
    assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries)
653 663
  end
654 664

  
655 665
  def test_issue_edit_should_notify_mentioned_users_in_notes
......
665 675
    # @dlopper won't receive duplicated notifications
666 676
    assert_equal 3, ActionMailer::Base.deliveries.size
667 677
    assert_include User.find(1).mail, recipients
678

  
679
    recipients = {
680
      "jsmith@somenet.foo" => "involved",
681
      "dlopper@somenet.foo" => "involved",
682
      "admin@somenet.foo" => "mentioned",
683
    }
684
    assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries)
685
  end
686

  
687
  def test_issue_edit_should_contain_notification_reason
688
    journal = Journal.generate!(journalized: Issue.find(2), user: User.find(1), notes: 'Hello')
689

  
690
    ActionMailer::Base.deliveries.clear
691
    Mailer.deliver_issue_edit(journal)
692

  
693
    # assert notification reason
694
    assert_include "You have received this notification because you are watching it.", text_part.body.encoded
695
    assert_include "You have received this notification because you are watching it.", html_part.body.encoded
696

  
697
    # Assert notification reason
698
    assert_equal 'watcher', last_email.header['X-Redmine-Reason'].to_s
668 699
  end
669 700

  
670 701
  def test_issue_should_send_email_notification_with_suppress_empty_fields
......
714 745
    assert last_email.to.any?
715 746
    assert_select_email do
716 747
      assert_select "a[href=?]", "http://localhost:3000/projects/ecookbook/files"
748
      assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it."
717 749
    end
750
    assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded
751

  
752
    # Assert notification reason header
753
    assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s
718 754
  end
719 755

  
720 756
  def test_project_file_added
......
724 760
    assert last_email.to.any?
725 761
    assert_select_email do
726 762
      assert_select "a[href=?]", "http://localhost:3000/projects/ecookbook/files"
763
      assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it."
727 764
    end
765
    assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded
766

  
767
    # Assert notification reason header
768
    assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s
769
  end
770

  
771
  def test_document_file_added
772
    attachements = [Attachment.find_by_container_type('Document')]
773

  
774
    assert Mailer.deliver_attachments_added(attachements)
775
    assert_not_nil last_email.to
776
    assert last_email.to.any?
777
    assert_select_email do
778
      assert_select "a[href=?]", "http://localhost:3000/documents/1"
779
      assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it."
780
    end
781
    assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded
782

  
783
    # Assert notification reason header
784
    assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s
785
  end
786

  
787
  def test_document_added
788
    project = Project.find(1)
789
    doc = Document.new(:project => project, :title => 'New document', :category => Enumeration.find_by_name('User documentation'))
790
    doc.save
791

  
792
    assert Mailer.deliver_document_added(doc, User.find_by_id(3))
793
    assert_not_nil last_email.to
794
    assert last_email.to.any?
795
    assert_select_email do
796
      assert_select "a[href=?]", "http://localhost:3000/documents/#{doc.id}"
797
      assert_select "span[class=?] span", "footer", text: "You have received this notification because you have subscribed to it."
798
    end
799
    assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded
800

  
801
    # Assert headers
802
    assert_equal project.identifier, last_email.header['X-Redmine-Project'].to_s
803
    assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s
728 804
  end
729 805

  
730 806
  def test_news_added_should_notify_project_news_watchers
......
759 835
        assert_select 'a[href=?]',
760 836
                      'http://localhost:3000/projects/ecookbook/wiki/CookBook_documentation',
761 837
                      :text => 'CookBook documentation'
838
        assert_select "span[class=?] span", 'footer', text: "You have received this notification because you have subscribed to it."
762 839
      end
840

  
841
      assert_include "You have received this notification because you have subscribed to it.", text_part.body.encoded
842

  
843
      # Assert headers
844
      assert_equal 'subscribed', last_email.header['X-Redmine-Reason'].to_s
763 845
    end
764 846
  end
765 847

  
......
785 867
                    'http://localhost:3000/projects/ecookbook/wiki/CookBook_documentation',
786 868
                    :text => 'CookBook documentation'
787 869
    end
870

  
871
    recipients = {
872
      "admin@somenet.foo" => "watcher",
873
      "jsmith@somenet.foo" => "subscribed",
874
      "dlopper@somenet.foo" => "subscribed",
875
    }
876

  
877
    assert_mail_deliveries_reasons(recipients, ActionMailer::Base.deliveries)
788 878
  end
789 879

  
790 880
  def test_wiki_content_updated_should_notify_mentioned_users_in_updated_content
......
981 1071

  
982 1072
  def test_security_notification
983 1073
    set_language_if_valid User.find(1).language
984
    with_settings :emails_footer => "footer without link" do
1074
    with_settings :emails_footer => "footer without extra link" do
985 1075
      sender = User.find(2)
986 1076
      sender.remote_ip = '192.168.1.1'
987 1077
      assert(
......
996 1086
      assert_mail_body_match '192.168.1.1', mail
997 1087
      assert_mail_body_match I18n.t(:notice_account_password_updated), mail
998 1088
      assert_select_email do
999
        assert_select "h1", false
1000
        assert_select "a", false
1089
        assert_select 'span[class=?]', 'footer' do
1090
          assert_select 'span', text: 'You have received this security notification because you are an administrator.'
1091
          assert_select 'a', true
1092
          assert_select 'p', text: "footer without extra link"
1093
        end
1001 1094
      end
1002 1095
    end
1003 1096
  end
......
1031 1124
        )
1032 1125
      )
1033 1126
      assert_select_email do
1034
        assert_select "a", false
1127
        assert_select "a", true
1035 1128
        assert_select "h1", :text => I18n.t(:label_my_account)
1036 1129
      end
1037 1130
    end
......
1117 1210
      with_settings :plain_text_mail => 0 do
1118 1211
        assert Mailer.test_email(User.find(1)).deliver_now
1119 1212
        assert_select_email do
1120
          assert_select ".footer" do
1213
          assert_select "span[class=?]", "footer" do
1121 1214
            assert_select "strong", :text => "Footer content"
1122 1215
          end
1123 1216
        end
......
1126 1219
        assert Mailer.test_email(User.find(1)).deliver_now
1127 1220
        mail = last_email
1128 1221
        assert_include "\n-- \n", mail.body.decoded
1222
        assert_include "To change your notification preferences, please click here: http://localhost:3000/my/account.", mail.body.decoded
1129 1223
        assert_include "*Footer content*", mail.body.decoded
1130 1224
      end
1131 1225
    end
......
1136 1230
      with_settings :plain_text_mail => 0 do
1137 1231
        assert Mailer.test_email(User.find(1)).deliver_now
1138 1232
        assert_select_email do
1139
          assert_select ".footer", false
1233
          assert_select 'span[class=?]', 'footer' do
1234
            assert_select 'p', false
1235
          end
1140 1236
        end
1141 1237
      end
1142 1238
      with_settings :plain_text_mail => 1 do
1143 1239
        assert Mailer.test_email(User.find(1)).deliver_now
1144
        mail = last_email
1145
        assert_not_include "\n-- \n", mail.body.decoded
1240
        assert_equal "This is a test email sent by Redmine.\nRedmine URL: http://localhost:3000/\n\n-- \nTo change your notification preferences, please click here: http://localhost:3000/my/account.\n",
1241
last_email.body.decoded
1146 1242
      end
1147 1243
    end
1148 1244
  end
test/unit/message_test.rb
20 20
require_relative '../test_helper'
21 21

  
22 22
class MessageTest < ActiveSupport::TestCase
23
  include Redmine::I18n
23 24
  fixtures :projects, :roles, :members, :member_roles, :boards, :messages,
24 25
           :users, :watchers, :enabled_modules
25 26

  
......
36 37
    message = Message.new(:board => @board, :subject => 'Test message',
37 38
                          :content => 'Test message content',
38 39
                          :author => @user)
39
    assert message.save
40

  
41
    with_settings :notified_events => %w(message_posted) do
42
      assert message.save
43
    end
44

  
40 45
    @board.reload
41 46
    # topics count incremented
42 47
    assert_equal topics_count + 1, @board[:topics_count]
......
45 50
    assert_equal message, @board.last_message
46 51
    # author should be watching the message
47 52
    assert message.watched_by?(@user)
53

  
54
    expected = {
55
      "admin@somenet.foo" => "watcher",
56
      "jsmith@somenet.foo" => "subscribed",
57
      "dlopper@somenet.foo" => "subscribed"
58
    }
59

  
60
    assert_mail_deliveries_reasons(expected, ActionMailer::Base.deliveries)
48 61
  end
49 62

  
50 63
  def test_reply
test/unit/news_test.rb
20 20
require_relative '../test_helper'
21 21

  
22 22
class NewsTest < ActiveSupport::TestCase
23
  include Redmine::I18n
23 24
  fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles, :enabled_modules, :news
24 25

  
25 26
  def valid_news
......
38 39
      assert news.save
39 40
    end
40 41
    assert_equal 2, ActionMailer::Base.deliveries.size
42

  
43
    expected = {
44
      "jsmith@somenet.foo" => "subscribed",
45
      "dlopper@somenet.foo" => "subscribed"
46
    }
47
    assert_mail_deliveries_reasons(expected, ActionMailer::Base.deliveries)
41 48
  end
42 49

  
43 50
  def test_should_include_news_for_projects_with_news_enabled
(3-3/6)