Feature #36162 » 0001-Add-notification-reason.patch
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 |