##// END OF EJS Templates
Merged r14081 (#19323)....
Jean-Philippe Lang -
r13711:bcd35e4c44ac
parent child
Show More
@@ -1,529 +1,538
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Mailer < ActionMailer::Base
19 19 layout 'mailer'
20 20 helper :application
21 21 helper :issues
22 22 helper :custom_fields
23 23
24 24 include Redmine::I18n
25 25
26 26 def self.default_url_options
27 { :host => Setting.host_name, :protocol => Setting.protocol }
27 options = {:protocol => Setting.protocol}
28 if Setting.host_name.to_s =~ /\A(https?\:\/\/)?(.+?)(\:(\d+))?(\/.+)?\z/i
29 host, port, prefix = $2, $4, $5
30 options.merge!({
31 :host => host, :port => port, :script_name => prefix
32 })
33 else
34 options[:host] = Setting.host_name
35 end
36 options
28 37 end
29 38
30 39 # Builds a mail for notifying to_users and cc_users about a new issue
31 40 def issue_add(issue, to_users, cc_users)
32 41 redmine_headers 'Project' => issue.project.identifier,
33 42 'Issue-Id' => issue.id,
34 43 'Issue-Author' => issue.author.login
35 44 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
36 45 message_id issue
37 46 references issue
38 47 @author = issue.author
39 48 @issue = issue
40 49 @users = to_users + cc_users
41 50 @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
42 51 mail :to => to_users,
43 52 :cc => cc_users,
44 53 :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
45 54 end
46 55
47 56 # Notifies users about a new issue
48 57 def self.deliver_issue_add(issue)
49 58 to = issue.notified_users
50 59 cc = issue.notified_watchers - to
51 60 issue.each_notification(to + cc) do |users|
52 61 Mailer.issue_add(issue, to & users, cc & users).deliver
53 62 end
54 63 end
55 64
56 65 # Builds a mail for notifying to_users and cc_users about an issue update
57 66 def issue_edit(journal, to_users, cc_users)
58 67 issue = journal.journalized
59 68 redmine_headers 'Project' => issue.project.identifier,
60 69 'Issue-Id' => issue.id,
61 70 'Issue-Author' => issue.author.login
62 71 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
63 72 message_id journal
64 73 references issue
65 74 @author = journal.user
66 75 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
67 76 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
68 77 s << issue.subject
69 78 @issue = issue
70 79 @users = to_users + cc_users
71 80 @journal = journal
72 81 @journal_details = journal.visible_details(@users.first)
73 82 @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
74 83 mail :to => to_users,
75 84 :cc => cc_users,
76 85 :subject => s
77 86 end
78 87
79 88 # Notifies users about an issue update
80 89 def self.deliver_issue_edit(journal)
81 90 issue = journal.journalized.reload
82 91 to = journal.notified_users
83 92 cc = journal.notified_watchers - to
84 93 journal.each_notification(to + cc) do |users|
85 94 issue.each_notification(users) do |users2|
86 95 Mailer.issue_edit(journal, to & users2, cc & users2).deliver
87 96 end
88 97 end
89 98 end
90 99
91 100 def reminder(user, issues, days)
92 101 set_language_if_valid user.language
93 102 @issues = issues
94 103 @days = days
95 104 @issues_url = url_for(:controller => 'issues', :action => 'index',
96 105 :set_filter => 1, :assigned_to_id => user.id,
97 106 :sort => 'due_date:asc')
98 107 mail :to => user,
99 108 :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
100 109 end
101 110
102 111 # Builds a Mail::Message object used to email users belonging to the added document's project.
103 112 #
104 113 # Example:
105 114 # document_added(document) => Mail::Message object
106 115 # Mailer.document_added(document).deliver => sends an email to the document's project recipients
107 116 def document_added(document)
108 117 redmine_headers 'Project' => document.project.identifier
109 118 @author = User.current
110 119 @document = document
111 120 @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
112 121 mail :to => document.notified_users,
113 122 :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
114 123 end
115 124
116 125 # Builds a Mail::Message object used to email recipients of a project when an attachements are added.
117 126 #
118 127 # Example:
119 128 # attachments_added(attachments) => Mail::Message object
120 129 # Mailer.attachments_added(attachments).deliver => sends an email to the project's recipients
121 130 def attachments_added(attachments)
122 131 container = attachments.first.container
123 132 added_to = ''
124 133 added_to_url = ''
125 134 @author = attachments.first.author
126 135 case container.class.name
127 136 when 'Project'
128 137 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
129 138 added_to = "#{l(:label_project)}: #{container}"
130 139 recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
131 140 when 'Version'
132 141 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
133 142 added_to = "#{l(:label_version)}: #{container.name}"
134 143 recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
135 144 when 'Document'
136 145 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
137 146 added_to = "#{l(:label_document)}: #{container.title}"
138 147 recipients = container.notified_users
139 148 end
140 149 redmine_headers 'Project' => container.project.identifier
141 150 @attachments = attachments
142 151 @added_to = added_to
143 152 @added_to_url = added_to_url
144 153 mail :to => recipients,
145 154 :subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
146 155 end
147 156
148 157 # Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
149 158 #
150 159 # Example:
151 160 # news_added(news) => Mail::Message object
152 161 # Mailer.news_added(news).deliver => sends an email to the news' project recipients
153 162 def news_added(news)
154 163 redmine_headers 'Project' => news.project.identifier
155 164 @author = news.author
156 165 message_id news
157 166 references news
158 167 @news = news
159 168 @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
160 169 mail :to => news.notified_users,
161 170 :cc => news.notified_watchers_for_added_news,
162 171 :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
163 172 end
164 173
165 174 # Builds a Mail::Message object used to email recipients of a news' project when a news comment is added.
166 175 #
167 176 # Example:
168 177 # news_comment_added(comment) => Mail::Message object
169 178 # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
170 179 def news_comment_added(comment)
171 180 news = comment.commented
172 181 redmine_headers 'Project' => news.project.identifier
173 182 @author = comment.author
174 183 message_id comment
175 184 references news
176 185 @news = news
177 186 @comment = comment
178 187 @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
179 188 mail :to => news.notified_users,
180 189 :cc => news.notified_watchers,
181 190 :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
182 191 end
183 192
184 193 # Builds a Mail::Message object used to email the recipients of the specified message that was posted.
185 194 #
186 195 # Example:
187 196 # message_posted(message) => Mail::Message object
188 197 # Mailer.message_posted(message).deliver => sends an email to the recipients
189 198 def message_posted(message)
190 199 redmine_headers 'Project' => message.project.identifier,
191 200 'Topic-Id' => (message.parent_id || message.id)
192 201 @author = message.author
193 202 message_id message
194 203 references message.root
195 204 recipients = message.notified_users
196 205 cc = ((message.root.notified_watchers + message.board.notified_watchers).uniq - recipients)
197 206 @message = message
198 207 @message_url = url_for(message.event_url)
199 208 mail :to => recipients,
200 209 :cc => cc,
201 210 :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
202 211 end
203 212
204 213 # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
205 214 #
206 215 # Example:
207 216 # wiki_content_added(wiki_content) => Mail::Message object
208 217 # Mailer.wiki_content_added(wiki_content).deliver => sends an email to the project's recipients
209 218 def wiki_content_added(wiki_content)
210 219 redmine_headers 'Project' => wiki_content.project.identifier,
211 220 'Wiki-Page-Id' => wiki_content.page.id
212 221 @author = wiki_content.author
213 222 message_id wiki_content
214 223 recipients = wiki_content.notified_users
215 224 cc = wiki_content.page.wiki.notified_watchers - recipients
216 225 @wiki_content = wiki_content
217 226 @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
218 227 :project_id => wiki_content.project,
219 228 :id => wiki_content.page.title)
220 229 mail :to => recipients,
221 230 :cc => cc,
222 231 :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
223 232 end
224 233
225 234 # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was updated.
226 235 #
227 236 # Example:
228 237 # wiki_content_updated(wiki_content) => Mail::Message object
229 238 # Mailer.wiki_content_updated(wiki_content).deliver => sends an email to the project's recipients
230 239 def wiki_content_updated(wiki_content)
231 240 redmine_headers 'Project' => wiki_content.project.identifier,
232 241 'Wiki-Page-Id' => wiki_content.page.id
233 242 @author = wiki_content.author
234 243 message_id wiki_content
235 244 recipients = wiki_content.notified_users
236 245 cc = wiki_content.page.wiki.notified_watchers + wiki_content.page.notified_watchers - recipients
237 246 @wiki_content = wiki_content
238 247 @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
239 248 :project_id => wiki_content.project,
240 249 :id => wiki_content.page.title)
241 250 @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
242 251 :project_id => wiki_content.project, :id => wiki_content.page.title,
243 252 :version => wiki_content.version)
244 253 mail :to => recipients,
245 254 :cc => cc,
246 255 :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
247 256 end
248 257
249 258 # Builds a Mail::Message object used to email the specified user their account information.
250 259 #
251 260 # Example:
252 261 # account_information(user, password) => Mail::Message object
253 262 # Mailer.account_information(user, password).deliver => sends account information to the user
254 263 def account_information(user, password)
255 264 set_language_if_valid user.language
256 265 @user = user
257 266 @password = password
258 267 @login_url = url_for(:controller => 'account', :action => 'login')
259 268 mail :to => user.mail,
260 269 :subject => l(:mail_subject_register, Setting.app_title)
261 270 end
262 271
263 272 # Builds a Mail::Message object used to email all active administrators of an account activation request.
264 273 #
265 274 # Example:
266 275 # account_activation_request(user) => Mail::Message object
267 276 # Mailer.account_activation_request(user).deliver => sends an email to all active administrators
268 277 def account_activation_request(user)
269 278 # Send the email to all active administrators
270 279 recipients = User.active.where(:admin => true)
271 280 @user = user
272 281 @url = url_for(:controller => 'users', :action => 'index',
273 282 :status => User::STATUS_REGISTERED,
274 283 :sort_key => 'created_on', :sort_order => 'desc')
275 284 mail :to => recipients,
276 285 :subject => l(:mail_subject_account_activation_request, Setting.app_title)
277 286 end
278 287
279 288 # Builds a Mail::Message object used to email the specified user that their account was activated by an administrator.
280 289 #
281 290 # Example:
282 291 # account_activated(user) => Mail::Message object
283 292 # Mailer.account_activated(user).deliver => sends an email to the registered user
284 293 def account_activated(user)
285 294 set_language_if_valid user.language
286 295 @user = user
287 296 @login_url = url_for(:controller => 'account', :action => 'login')
288 297 mail :to => user.mail,
289 298 :subject => l(:mail_subject_register, Setting.app_title)
290 299 end
291 300
292 301 def lost_password(token, recipient=nil)
293 302 set_language_if_valid(token.user.language)
294 303 recipient ||= token.user.mail
295 304 @token = token
296 305 @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
297 306 mail :to => recipient,
298 307 :subject => l(:mail_subject_lost_password, Setting.app_title)
299 308 end
300 309
301 310 def register(token)
302 311 set_language_if_valid(token.user.language)
303 312 @token = token
304 313 @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
305 314 mail :to => token.user.mail,
306 315 :subject => l(:mail_subject_register, Setting.app_title)
307 316 end
308 317
309 318 def test_email(user)
310 319 set_language_if_valid(user.language)
311 320 @url = url_for(:controller => 'welcome')
312 321 mail :to => user.mail,
313 322 :subject => 'Redmine test'
314 323 end
315 324
316 325 # Sends reminders to issue assignees
317 326 # Available options:
318 327 # * :days => how many days in the future to remind about (defaults to 7)
319 328 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
320 329 # * :project => id or identifier of project to process (defaults to all projects)
321 330 # * :users => array of user/group ids who should be reminded
322 331 # * :version => name of target version for filtering issues (defaults to none)
323 332 def self.reminders(options={})
324 333 days = options[:days] || 7
325 334 project = options[:project] ? Project.find(options[:project]) : nil
326 335 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
327 336 target_version_id = options[:version] ? Version.named(options[:version]).pluck(:id) : nil
328 337 if options[:version] && target_version_id.blank?
329 338 raise ActiveRecord::RecordNotFound.new("Couldn't find Version with named #{options[:version]}")
330 339 end
331 340 user_ids = options[:users]
332 341
333 342 scope = Issue.open.where("#{Issue.table_name}.assigned_to_id IS NOT NULL" +
334 343 " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
335 344 " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date
336 345 )
337 346 scope = scope.where(:assigned_to_id => user_ids) if user_ids.present?
338 347 scope = scope.where(:project_id => project.id) if project
339 348 scope = scope.where(:fixed_version_id => target_version_id) if target_version_id.present?
340 349 scope = scope.where(:tracker_id => tracker.id) if tracker
341 350 issues_by_assignee = scope.includes(:status, :assigned_to, :project, :tracker).
342 351 group_by(&:assigned_to)
343 352 issues_by_assignee.keys.each do |assignee|
344 353 if assignee.is_a?(Group)
345 354 assignee.users.each do |user|
346 355 issues_by_assignee[user] ||= []
347 356 issues_by_assignee[user] += issues_by_assignee[assignee]
348 357 end
349 358 end
350 359 end
351 360
352 361 issues_by_assignee.each do |assignee, issues|
353 362 reminder(assignee, issues, days).deliver if assignee.is_a?(User) && assignee.active?
354 363 end
355 364 end
356 365
357 366 # Activates/desactivates email deliveries during +block+
358 367 def self.with_deliveries(enabled = true, &block)
359 368 was_enabled = ActionMailer::Base.perform_deliveries
360 369 ActionMailer::Base.perform_deliveries = !!enabled
361 370 yield
362 371 ensure
363 372 ActionMailer::Base.perform_deliveries = was_enabled
364 373 end
365 374
366 375 # Sends emails synchronously in the given block
367 376 def self.with_synched_deliveries(&block)
368 377 saved_method = ActionMailer::Base.delivery_method
369 378 if m = saved_method.to_s.match(%r{^async_(.+)$})
370 379 synched_method = m[1]
371 380 ActionMailer::Base.delivery_method = synched_method.to_sym
372 381 ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
373 382 end
374 383 yield
375 384 ensure
376 385 ActionMailer::Base.delivery_method = saved_method
377 386 end
378 387
379 388 def mail(headers={}, &block)
380 389 headers.reverse_merge! 'X-Mailer' => 'Redmine',
381 390 'X-Redmine-Host' => Setting.host_name,
382 391 'X-Redmine-Site' => Setting.app_title,
383 392 'X-Auto-Response-Suppress' => 'OOF',
384 393 'Auto-Submitted' => 'auto-generated',
385 394 'From' => Setting.mail_from,
386 395 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
387 396
388 397 # Replaces users with their email addresses
389 398 [:to, :cc, :bcc].each do |key|
390 399 if headers[key].present?
391 400 headers[key] = self.class.email_addresses(headers[key])
392 401 end
393 402 end
394 403
395 404 # Removes the author from the recipients and cc
396 405 # if the author does not want to receive notifications
397 406 # about what the author do
398 407 if @author && @author.logged? && @author.pref.no_self_notified
399 408 addresses = @author.mails
400 409 headers[:to] -= addresses if headers[:to].is_a?(Array)
401 410 headers[:cc] -= addresses if headers[:cc].is_a?(Array)
402 411 end
403 412
404 413 if @author && @author.logged?
405 414 redmine_headers 'Sender' => @author.login
406 415 end
407 416
408 417 # Blind carbon copy recipients
409 418 if Setting.bcc_recipients?
410 419 headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
411 420 headers[:to] = nil
412 421 headers[:cc] = nil
413 422 end
414 423
415 424 if @message_id_object
416 425 headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
417 426 end
418 427 if @references_objects
419 428 headers[:references] = @references_objects.collect {|o| "<#{self.class.references_for(o)}>"}.join(' ')
420 429 end
421 430
422 431 m = if block_given?
423 432 super headers, &block
424 433 else
425 434 super headers do |format|
426 435 format.text
427 436 format.html unless Setting.plain_text_mail?
428 437 end
429 438 end
430 439 set_language_if_valid @initial_language
431 440
432 441 m
433 442 end
434 443
435 444 def initialize(*args)
436 445 @initial_language = current_language
437 446 set_language_if_valid Setting.default_language
438 447 super
439 448 end
440 449
441 450 def self.deliver_mail(mail)
442 451 return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
443 452 begin
444 453 # Log errors when raise_delivery_errors is set to false, Rails does not
445 454 mail.raise_delivery_errors = true
446 455 super
447 456 rescue Exception => e
448 457 if ActionMailer::Base.raise_delivery_errors
449 458 raise e
450 459 else
451 460 Rails.logger.error "Email delivery error: #{e.message}"
452 461 end
453 462 end
454 463 end
455 464
456 465 def self.method_missing(method, *args, &block)
457 466 if m = method.to_s.match(%r{^deliver_(.+)$})
458 467 ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
459 468 send(m[1], *args).deliver
460 469 else
461 470 super
462 471 end
463 472 end
464 473
465 474 # Returns an array of email addresses to notify by
466 475 # replacing users in arg with their notified email addresses
467 476 #
468 477 # Example:
469 478 # Mailer.email_addresses(users)
470 479 # => ["foo@example.net", "bar@example.net"]
471 480 def self.email_addresses(arg)
472 481 arr = Array.wrap(arg)
473 482 mails = arr.reject {|a| a.is_a? Principal}
474 483 users = arr - mails
475 484 if users.any?
476 485 mails += EmailAddress.
477 486 where(:user_id => users.map(&:id)).
478 487 where("is_default = ? OR notify = ?", true, true).
479 488 pluck(:address)
480 489 end
481 490 mails
482 491 end
483 492
484 493 private
485 494
486 495 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
487 496 def redmine_headers(h)
488 497 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
489 498 end
490 499
491 500 def self.token_for(object, rand=true)
492 501 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
493 502 hash = [
494 503 "redmine",
495 504 "#{object.class.name.demodulize.underscore}-#{object.id}",
496 505 timestamp.strftime("%Y%m%d%H%M%S")
497 506 ]
498 507 if rand
499 508 hash << Redmine::Utils.random_hex(8)
500 509 end
501 510 host = Setting.mail_from.to_s.strip.gsub(%r{^.*@|>}, '')
502 511 host = "#{::Socket.gethostname}.redmine" if host.empty?
503 512 "#{hash.join('.')}@#{host}"
504 513 end
505 514
506 515 # Returns a Message-Id for the given object
507 516 def self.message_id_for(object)
508 517 token_for(object, true)
509 518 end
510 519
511 520 # Returns a uniq token for a given object referenced by all notifications
512 521 # related to this object
513 522 def self.references_for(object)
514 523 token_for(object, false)
515 524 end
516 525
517 526 def message_id(object)
518 527 @message_id_object = object
519 528 end
520 529
521 530 def references(object)
522 531 @references_objects ||= []
523 532 @references_objects << object
524 533 end
525 534
526 535 def mylogger
527 536 Rails.logger
528 537 end
529 538 end
@@ -1,835 +1,853
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class MailerTest < ActiveSupport::TestCase
21 21 include Redmine::I18n
22 22 include Rails::Dom::Testing::Assertions
23 23 fixtures :projects, :enabled_modules, :issues, :users, :email_addresses, :members,
24 24 :member_roles, :roles, :documents, :attachments, :news,
25 25 :tokens, :journals, :journal_details, :changesets,
26 26 :trackers, :projects_trackers,
27 27 :issue_statuses, :enumerations, :messages, :boards, :repositories,
28 28 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
29 29 :versions,
30 30 :comments
31 31
32 32 def setup
33 33 ActionMailer::Base.deliveries.clear
34 34 Setting.host_name = 'mydomain.foo'
35 35 Setting.protocol = 'http'
36 36 Setting.plain_text_mail = '0'
37 37 Setting.default_language = 'en'
38 38 User.current = nil
39 39 end
40 40
41 41 def test_generated_links_in_emails
42 42 Setting.host_name = 'mydomain.foo'
43 43 Setting.protocol = 'https'
44 44
45 45 journal = Journal.find(3)
46 46 assert Mailer.deliver_issue_edit(journal)
47 47
48 48 mail = last_email
49 49 assert_not_nil mail
50 50
51 51 assert_select_email do
52 52 # link to the main ticket
53 53 assert_select 'a[href=?]',
54 54 'https://mydomain.foo/issues/2#change-3',
55 55 :text => 'Feature request #2: Add ingredients categories'
56 56 # link to a referenced ticket
57 57 assert_select 'a[href=?][title=?]',
58 58 'https://mydomain.foo/issues/1',
59 59 "Cannot print recipes (New)",
60 60 :text => '#1'
61 61 # link to a changeset
62 62 assert_select 'a[href=?][title=?]',
63 63 'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
64 64 'This commit fixes #1, #2 and references #1 & #3',
65 65 :text => 'r2'
66 66 # link to a description diff
67 67 assert_select 'a[href^=?][title=?]',
68 68 # should be https://mydomain.foo/journals/diff/3?detail_id=4
69 69 # but the Rails 4.2 DOM assertion doesn't handle the ? in the
70 70 # attribute value
71 71 'https://mydomain.foo/journals/diff/3',
72 72 'View differences',
73 73 :text => 'diff'
74 74 # link to an attachment
75 75 assert_select 'a[href=?]',
76 76 'https://mydomain.foo/attachments/download/4/source.rb',
77 77 :text => 'source.rb'
78 78 end
79 79 end
80 80
81 81 def test_generated_links_with_prefix
82 82 relative_url_root = Redmine::Utils.relative_url_root
83 83 Setting.host_name = 'mydomain.foo/rdm'
84 84 Setting.protocol = 'http'
85 85
86 86 journal = Journal.find(3)
87 87 assert Mailer.deliver_issue_edit(journal)
88 88
89 89 mail = last_email
90 90 assert_not_nil mail
91 91
92 92 assert_select_email do
93 93 # link to the main ticket
94 94 assert_select 'a[href=?]',
95 95 'http://mydomain.foo/rdm/issues/2#change-3',
96 96 :text => 'Feature request #2: Add ingredients categories'
97 97 # link to a referenced ticket
98 98 assert_select 'a[href=?][title=?]',
99 99 'http://mydomain.foo/rdm/issues/1',
100 100 "Cannot print recipes (New)",
101 101 :text => '#1'
102 102 # link to a changeset
103 103 assert_select 'a[href=?][title=?]',
104 104 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
105 105 'This commit fixes #1, #2 and references #1 & #3',
106 106 :text => 'r2'
107 107 # link to a description diff
108 108 assert_select 'a[href^=?][title=?]',
109 109 # should be http://mydomain.foo/rdm/journals/diff/3?detail_id=4
110 110 # but the Rails 4.2 DOM assertion doesn't handle the ? in the
111 111 # attribute value
112 112 'http://mydomain.foo/rdm/journals/diff/3',
113 113 'View differences',
114 114 :text => 'diff'
115 115 # link to an attachment
116 116 assert_select 'a[href=?]',
117 117 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
118 118 :text => 'source.rb'
119 119 end
120 120 end
121 121
122 def test_generated_links_with_port_and_prefix
123 with_settings :host_name => '10.0.0.1:81/redmine', :protocol => 'http' do
124 Mailer.test_email(User.find(1)).deliver
125 mail = last_email
126 assert_not_nil mail
127 assert_include 'http://10.0.0.1:81/redmine', mail_body(mail)
128 end
129 end
130
131 def test_generated_links_with_port
132 with_settings :host_name => '10.0.0.1:81', :protocol => 'http' do
133 Mailer.test_email(User.find(1)).deliver
134 mail = last_email
135 assert_not_nil mail
136 assert_include 'http://10.0.0.1:81', mail_body(mail)
137 end
138 end
139
122 140 def test_issue_edit_should_generate_url_with_hostname_for_relations
123 141 journal = Journal.new(:journalized => Issue.find(1), :user => User.find(1), :created_on => Time.now)
124 142 journal.details << JournalDetail.new(:property => 'relation', :prop_key => 'label_relates_to', :value => 2)
125 143 Mailer.deliver_issue_edit(journal)
126 144 assert_not_nil last_email
127 145 assert_select_email do
128 146 assert_select 'a[href=?]', 'http://mydomain.foo/issues/2', :text => 'Feature request #2'
129 147 end
130 148 end
131 149
132 150 def test_generated_links_with_prefix_and_no_relative_url_root
133 151 relative_url_root = Redmine::Utils.relative_url_root
134 152 Setting.host_name = 'mydomain.foo/rdm'
135 153 Setting.protocol = 'http'
136 154 Redmine::Utils.relative_url_root = nil
137 155
138 156 journal = Journal.find(3)
139 157 assert Mailer.deliver_issue_edit(journal)
140 158
141 159 mail = last_email
142 160 assert_not_nil mail
143 161
144 162 assert_select_email do
145 163 # link to the main ticket
146 164 assert_select 'a[href=?]',
147 165 'http://mydomain.foo/rdm/issues/2#change-3',
148 166 :text => 'Feature request #2: Add ingredients categories'
149 167 # link to a referenced ticket
150 168 assert_select 'a[href=?][title=?]',
151 169 'http://mydomain.foo/rdm/issues/1',
152 170 "Cannot print recipes (New)",
153 171 :text => '#1'
154 172 # link to a changeset
155 173 assert_select 'a[href=?][title=?]',
156 174 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
157 175 'This commit fixes #1, #2 and references #1 & #3',
158 176 :text => 'r2'
159 177 # link to a description diff
160 178 assert_select 'a[href^=?][title=?]',
161 179 # should be http://mydomain.foo/rdm/journals/diff/3?detail_id=4
162 180 # but the Rails 4.2 DOM assertion doesn't handle the ? in the
163 181 # attribute value
164 182 'http://mydomain.foo/rdm/journals/diff/3',
165 183 'View differences',
166 184 :text => 'diff'
167 185 # link to an attachment
168 186 assert_select 'a[href=?]',
169 187 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
170 188 :text => 'source.rb'
171 189 end
172 190 ensure
173 191 # restore it
174 192 Redmine::Utils.relative_url_root = relative_url_root
175 193 end
176 194
177 195 def test_email_headers
178 196 issue = Issue.find(1)
179 197 Mailer.deliver_issue_add(issue)
180 198 mail = last_email
181 199 assert_not_nil mail
182 200 assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
183 201 assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
184 202 assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s
185 203 end
186 204
187 205 def test_email_headers_should_include_sender
188 206 issue = Issue.find(1)
189 207 Mailer.deliver_issue_add(issue)
190 208 mail = last_email
191 209 assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
192 210 end
193 211
194 212 def test_plain_text_mail
195 213 Setting.plain_text_mail = 1
196 214 journal = Journal.find(2)
197 215 Mailer.deliver_issue_edit(journal)
198 216 mail = last_email
199 217 assert_equal "text/plain; charset=UTF-8", mail.content_type
200 218 assert_equal 0, mail.parts.size
201 219 assert !mail.encoded.include?('href')
202 220 end
203 221
204 222 def test_html_mail
205 223 Setting.plain_text_mail = 0
206 224 journal = Journal.find(2)
207 225 Mailer.deliver_issue_edit(journal)
208 226 mail = last_email
209 227 assert_equal 2, mail.parts.size
210 228 assert mail.encoded.include?('href')
211 229 end
212 230
213 231 def test_from_header
214 232 with_settings :mail_from => 'redmine@example.net' do
215 233 Mailer.test_email(User.find(1)).deliver
216 234 end
217 235 mail = last_email
218 236 assert_equal 'redmine@example.net', mail.from_addrs.first
219 237 end
220 238
221 239 def test_from_header_with_phrase
222 240 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
223 241 Mailer.test_email(User.find(1)).deliver
224 242 end
225 243 mail = last_email
226 244 assert_equal 'redmine@example.net', mail.from_addrs.first
227 245 assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
228 246 end
229 247
230 248 def test_should_not_send_email_without_recipient
231 249 news = News.first
232 250 user = news.author
233 251 # Remove members except news author
234 252 news.project.memberships.each {|m| m.destroy unless m.user == user}
235 253
236 254 user.pref.no_self_notified = false
237 255 user.pref.save
238 256 User.current = user
239 257 Mailer.news_added(news.reload).deliver
240 258 assert_equal 1, last_email.bcc.size
241 259
242 260 # nobody to notify
243 261 user.pref.no_self_notified = true
244 262 user.pref.save
245 263 User.current = user
246 264 ActionMailer::Base.deliveries.clear
247 265 Mailer.news_added(news.reload).deliver
248 266 assert ActionMailer::Base.deliveries.empty?
249 267 end
250 268
251 269 def test_issue_add_message_id
252 270 issue = Issue.find(2)
253 271 Mailer.deliver_issue_add(issue)
254 272 mail = last_email
255 273 assert_match /^redmine\.issue-2\.20060719190421\.[a-f0-9]+@example\.net/, mail.message_id
256 274 assert_include "redmine.issue-2.20060719190421@example.net", mail.references
257 275 end
258 276
259 277 def test_issue_edit_message_id
260 278 journal = Journal.find(3)
261 279 journal.issue = Issue.find(2)
262 280
263 281 Mailer.deliver_issue_edit(journal)
264 282 mail = last_email
265 283 assert_match /^redmine\.journal-3\.\d+\.[a-f0-9]+@example\.net/, mail.message_id
266 284 assert_include "redmine.issue-2.20060719190421@example.net", mail.references
267 285 assert_select_email do
268 286 # link to the update
269 287 assert_select "a[href=?]",
270 288 "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
271 289 end
272 290 end
273 291
274 292 def test_message_posted_message_id
275 293 message = Message.find(1)
276 294 Mailer.message_posted(message).deliver
277 295 mail = last_email
278 296 assert_match /^redmine\.message-1\.\d+\.[a-f0-9]+@example\.net/, mail.message_id
279 297 assert_include "redmine.message-1.20070512151532@example.net", mail.references
280 298 assert_select_email do
281 299 # link to the message
282 300 assert_select "a[href=?]",
283 301 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
284 302 :text => message.subject
285 303 end
286 304 end
287 305
288 306 def test_reply_posted_message_id
289 307 message = Message.find(3)
290 308 Mailer.message_posted(message).deliver
291 309 mail = last_email
292 310 assert_match /^redmine\.message-3\.\d+\.[a-f0-9]+@example\.net/, mail.message_id
293 311 assert_include "redmine.message-1.20070512151532@example.net", mail.references
294 312 assert_select_email do
295 313 # link to the reply
296 314 assert_select "a[href=?]",
297 315 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
298 316 :text => message.subject
299 317 end
300 318 end
301 319
302 320 test "#issue_add should notify project members" do
303 321 issue = Issue.find(1)
304 322 assert Mailer.deliver_issue_add(issue)
305 323 assert last_email.bcc.include?('dlopper@somenet.foo')
306 324 end
307 325
308 326 def test_issue_add_should_send_mail_to_all_user_email_address
309 327 EmailAddress.create!(:user_id => 3, :address => 'otheremail@somenet.foo')
310 328 issue = Issue.find(1)
311 329 assert Mailer.deliver_issue_add(issue)
312 330 assert last_email.bcc.include?('dlopper@somenet.foo')
313 331 assert last_email.bcc.include?('otheremail@somenet.foo')
314 332 end
315 333
316 334 test "#issue_add should not notify project members that are not allow to view the issue" do
317 335 issue = Issue.find(1)
318 336 Role.find(2).remove_permission!(:view_issues)
319 337 assert Mailer.deliver_issue_add(issue)
320 338 assert !last_email.bcc.include?('dlopper@somenet.foo')
321 339 end
322 340
323 341 test "#issue_add should notify issue watchers" do
324 342 issue = Issue.find(1)
325 343 user = User.find(9)
326 344 # minimal email notification options
327 345 user.pref.no_self_notified = '1'
328 346 user.pref.save
329 347 user.mail_notification = false
330 348 user.save
331 349
332 350 Watcher.create!(:watchable => issue, :user => user)
333 351 assert Mailer.deliver_issue_add(issue)
334 352 assert last_email.bcc.include?(user.mail)
335 353 end
336 354
337 355 test "#issue_add should not notify watchers not allowed to view the issue" do
338 356 issue = Issue.find(1)
339 357 user = User.find(9)
340 358 Watcher.create!(:watchable => issue, :user => user)
341 359 Role.non_member.remove_permission!(:view_issues)
342 360 assert Mailer.deliver_issue_add(issue)
343 361 assert !last_email.bcc.include?(user.mail)
344 362 end
345 363
346 364 def test_issue_add_should_include_enabled_fields
347 365 issue = Issue.find(2)
348 366 assert Mailer.deliver_issue_add(issue)
349 367 assert_mail_body_match '* Target version: 1.0', last_email
350 368 assert_select_email do
351 369 assert_select 'li', :text => 'Target version: 1.0'
352 370 end
353 371 end
354 372
355 373 def test_issue_add_should_not_include_disabled_fields
356 374 issue = Issue.find(2)
357 375 tracker = issue.tracker
358 376 tracker.core_fields -= ['fixed_version_id']
359 377 tracker.save!
360 378 assert Mailer.deliver_issue_add(issue)
361 379 assert_mail_body_no_match 'Target version', last_email
362 380 assert_select_email do
363 381 assert_select 'li', :text => /Target version/, :count => 0
364 382 end
365 383 end
366 384
367 385 # test mailer methods for each language
368 386 def test_issue_add
369 387 issue = Issue.find(1)
370 388 with_each_language_as_default do
371 389 assert Mailer.deliver_issue_add(issue)
372 390 end
373 391 end
374 392
375 393 def test_issue_edit
376 394 journal = Journal.find(1)
377 395 with_each_language_as_default do
378 396 assert Mailer.deliver_issue_edit(journal)
379 397 end
380 398 end
381 399
382 400 def test_issue_edit_should_send_private_notes_to_users_with_permission_only
383 401 journal = Journal.find(1)
384 402 journal.private_notes = true
385 403 journal.save!
386 404
387 405 Role.find(2).add_permission! :view_private_notes
388 406 Mailer.deliver_issue_edit(journal)
389 407 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
390 408
391 409 Role.find(2).remove_permission! :view_private_notes
392 410 Mailer.deliver_issue_edit(journal)
393 411 assert_equal %w(jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
394 412 end
395 413
396 414 def test_issue_edit_should_send_private_notes_to_watchers_with_permission_only
397 415 Issue.find(1).set_watcher(User.find_by_login('someone'))
398 416 journal = Journal.find(1)
399 417 journal.private_notes = true
400 418 journal.save!
401 419
402 420 Role.non_member.add_permission! :view_private_notes
403 421 Mailer.deliver_issue_edit(journal)
404 422 assert_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
405 423
406 424 Role.non_member.remove_permission! :view_private_notes
407 425 Mailer.deliver_issue_edit(journal)
408 426 assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
409 427 end
410 428
411 429 def test_issue_edit_should_mark_private_notes
412 430 journal = Journal.find(2)
413 431 journal.private_notes = true
414 432 journal.save!
415 433
416 434 with_settings :default_language => 'en' do
417 435 Mailer.deliver_issue_edit(journal)
418 436 end
419 437 assert_mail_body_match '(Private notes)', last_email
420 438 end
421 439
422 440 def test_issue_edit_with_relation_should_notify_users_who_can_see_the_related_issue
423 441 issue = Issue.generate!
424 442 issue.init_journal(User.find(1))
425 443 private_issue = Issue.generate!(:is_private => true)
426 444 IssueRelation.create!(:issue_from => issue, :issue_to => private_issue, :relation_type => 'relates')
427 445 issue.reload
428 446 assert_equal 1, issue.journals.size
429 447 journal = issue.journals.first
430 448 ActionMailer::Base.deliveries.clear
431 449
432 450 Mailer.deliver_issue_edit(journal)
433 451 last_email.bcc.each do |email|
434 452 user = User.find_by_mail(email)
435 453 assert private_issue.visible?(user), "Issue was not visible to #{user}"
436 454 end
437 455 end
438 456
439 457 def test_document_added
440 458 document = Document.find(1)
441 459 with_each_language_as_default do
442 460 assert Mailer.document_added(document).deliver
443 461 end
444 462 end
445 463
446 464 def test_attachments_added
447 465 attachements = [ Attachment.find_by_container_type('Document') ]
448 466 with_each_language_as_default do
449 467 assert Mailer.attachments_added(attachements).deliver
450 468 end
451 469 end
452 470
453 471 def test_version_file_added
454 472 attachements = [ Attachment.find_by_container_type('Version') ]
455 473 assert Mailer.attachments_added(attachements).deliver
456 474 assert_not_nil last_email.bcc
457 475 assert last_email.bcc.any?
458 476 assert_select_email do
459 477 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
460 478 end
461 479 end
462 480
463 481 def test_project_file_added
464 482 attachements = [ Attachment.find_by_container_type('Project') ]
465 483 assert Mailer.attachments_added(attachements).deliver
466 484 assert_not_nil last_email.bcc
467 485 assert last_email.bcc.any?
468 486 assert_select_email do
469 487 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
470 488 end
471 489 end
472 490
473 491 def test_news_added
474 492 news = News.first
475 493 with_each_language_as_default do
476 494 assert Mailer.news_added(news).deliver
477 495 end
478 496 end
479 497
480 498 def test_news_added_should_notify_project_news_watchers
481 499 user1 = User.generate!
482 500 user2 = User.generate!
483 501 news = News.find(1)
484 502 news.project.enabled_module('news').add_watcher(user1)
485 503
486 504 Mailer.news_added(news).deliver
487 505 assert_include user1.mail, last_email.bcc
488 506 assert_not_include user2.mail, last_email.bcc
489 507 end
490 508
491 509 def test_news_comment_added
492 510 comment = Comment.find(2)
493 511 with_each_language_as_default do
494 512 assert Mailer.news_comment_added(comment).deliver
495 513 end
496 514 end
497 515
498 516 def test_message_posted
499 517 message = Message.first
500 518 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
501 519 recipients = recipients.compact.uniq
502 520 with_each_language_as_default do
503 521 assert Mailer.message_posted(message).deliver
504 522 end
505 523 end
506 524
507 525 def test_wiki_content_added
508 526 content = WikiContent.find(1)
509 527 with_each_language_as_default do
510 528 assert_difference 'ActionMailer::Base.deliveries.size' do
511 529 assert Mailer.wiki_content_added(content).deliver
512 530 assert_select_email do
513 531 assert_select 'a[href=?]',
514 532 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
515 533 :text => 'CookBook documentation'
516 534 end
517 535 end
518 536 end
519 537 end
520 538
521 539 def test_wiki_content_updated
522 540 content = WikiContent.find(1)
523 541 with_each_language_as_default do
524 542 assert_difference 'ActionMailer::Base.deliveries.size' do
525 543 assert Mailer.wiki_content_updated(content).deliver
526 544 assert_select_email do
527 545 assert_select 'a[href=?]',
528 546 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
529 547 :text => 'CookBook documentation'
530 548 end
531 549 end
532 550 end
533 551 end
534 552
535 553 def test_account_information
536 554 user = User.find(2)
537 555 valid_languages.each do |lang|
538 556 user.update_attribute :language, lang.to_s
539 557 user.reload
540 558 assert Mailer.account_information(user, 'pAsswORd').deliver
541 559 end
542 560 end
543 561
544 562 def test_lost_password
545 563 token = Token.find(2)
546 564 valid_languages.each do |lang|
547 565 token.user.update_attribute :language, lang.to_s
548 566 token.reload
549 567 assert Mailer.lost_password(token).deliver
550 568 end
551 569 end
552 570
553 571 def test_register
554 572 token = Token.find(1)
555 573 Setting.host_name = 'redmine.foo'
556 574 Setting.protocol = 'https'
557 575
558 576 valid_languages.each do |lang|
559 577 token.user.update_attribute :language, lang.to_s
560 578 token.reload
561 579 ActionMailer::Base.deliveries.clear
562 580 assert Mailer.register(token).deliver
563 581 mail = last_email
564 582 assert_select_email do
565 583 assert_select "a[href=?]",
566 584 "https://redmine.foo/account/activate?token=#{token.value}",
567 585 :text => "https://redmine.foo/account/activate?token=#{token.value}"
568 586 end
569 587 end
570 588 end
571 589
572 590 def test_test
573 591 user = User.find(1)
574 592 valid_languages.each do |lang|
575 593 user.update_attribute :language, lang.to_s
576 594 assert Mailer.test_email(user).deliver
577 595 end
578 596 end
579 597
580 598 def test_reminders
581 599 Mailer.reminders(:days => 42)
582 600 assert_equal 1, ActionMailer::Base.deliveries.size
583 601 mail = last_email
584 602 assert mail.bcc.include?('dlopper@somenet.foo')
585 603 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
586 604 assert_equal '1 issue(s) due in the next 42 days', mail.subject
587 605 end
588 606
589 607 def test_reminders_should_not_include_closed_issues
590 608 with_settings :default_language => 'en' do
591 609 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
592 610 :subject => 'Closed issue', :assigned_to_id => 3,
593 611 :due_date => 5.days.from_now,
594 612 :author_id => 2)
595 613 ActionMailer::Base.deliveries.clear
596 614
597 615 Mailer.reminders(:days => 42)
598 616 assert_equal 1, ActionMailer::Base.deliveries.size
599 617 mail = last_email
600 618 assert mail.bcc.include?('dlopper@somenet.foo')
601 619 assert_mail_body_no_match 'Closed issue', mail
602 620 end
603 621 end
604 622
605 623 def test_reminders_for_users
606 624 Mailer.reminders(:days => 42, :users => ['5'])
607 625 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
608 626 Mailer.reminders(:days => 42, :users => ['3'])
609 627 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
610 628 mail = last_email
611 629 assert mail.bcc.include?('dlopper@somenet.foo')
612 630 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
613 631 end
614 632
615 633 def test_reminder_should_include_issues_assigned_to_groups
616 634 with_settings :default_language => 'en' do
617 635 group = Group.generate!
618 636 group.users << User.find(2)
619 637 group.users << User.find(3)
620 638
621 639 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
622 640 :subject => 'Assigned to group', :assigned_to => group,
623 641 :due_date => 5.days.from_now,
624 642 :author_id => 2)
625 643 ActionMailer::Base.deliveries.clear
626 644
627 645 Mailer.reminders(:days => 7)
628 646 assert_equal 2, ActionMailer::Base.deliveries.size
629 647 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
630 648 ActionMailer::Base.deliveries.each do |mail|
631 649 assert_mail_body_match 'Assigned to group', mail
632 650 end
633 651 end
634 652 end
635 653
636 654 def test_reminders_with_version_option
637 655 with_settings :default_language => 'en' do
638 656 version = Version.generate!(:name => 'Acme', :project_id => 1)
639 657 Issue.generate!(:assigned_to => User.find(2), :due_date => 5.days.from_now)
640 658 Issue.generate!(:assigned_to => User.find(3), :due_date => 5.days.from_now, :fixed_version => version)
641 659 ActionMailer::Base.deliveries.clear
642 660
643 661 Mailer.reminders(:days => 42, :version => 'acme')
644 662 assert_equal 1, ActionMailer::Base.deliveries.size
645 663
646 664 mail = last_email
647 665 assert mail.bcc.include?('dlopper@somenet.foo')
648 666 end
649 667 end
650 668
651 669 def test_mailer_should_not_change_locale
652 670 # Set current language to italian
653 671 set_language_if_valid 'it'
654 672 # Send an email to a french user
655 673 user = User.find(1)
656 674 user.language = 'fr'
657 675 Mailer.account_activated(user).deliver
658 676 mail = last_email
659 677 assert_mail_body_match 'Votre compte', mail
660 678
661 679 assert_equal :it, current_language
662 680 end
663 681
664 682 def test_with_deliveries_off
665 683 Mailer.with_deliveries false do
666 684 Mailer.test_email(User.find(1)).deliver
667 685 end
668 686 assert ActionMailer::Base.deliveries.empty?
669 687 # should restore perform_deliveries
670 688 assert ActionMailer::Base.perform_deliveries
671 689 end
672 690
673 691 def test_token_for_should_strip_trailing_gt_from_address_with_full_name
674 692 with_settings :mail_from => "Redmine Mailer<no-reply@redmine.org>" do
675 693 assert_match /\Aredmine.issue-\d+\.\d+\.[0-9a-f]+@redmine.org\z/, Mailer.token_for(Issue.generate!)
676 694 end
677 695 end
678 696
679 697 def test_layout_should_include_the_emails_header
680 698 with_settings :emails_header => "*Header content*" do
681 699 with_settings :plain_text_mail => 0 do
682 700 assert Mailer.test_email(User.find(1)).deliver
683 701 assert_select_email do
684 702 assert_select ".header" do
685 703 assert_select "strong", :text => "Header content"
686 704 end
687 705 end
688 706 end
689 707 with_settings :plain_text_mail => 1 do
690 708 assert Mailer.test_email(User.find(1)).deliver
691 709 mail = last_email
692 710 assert_not_nil mail
693 711 assert_include "*Header content*", mail.body.decoded
694 712 end
695 713 end
696 714 end
697 715
698 716 def test_layout_should_not_include_empty_emails_header
699 717 with_settings :emails_header => "", :plain_text_mail => 0 do
700 718 assert Mailer.test_email(User.find(1)).deliver
701 719 assert_select_email do
702 720 assert_select ".header", false
703 721 end
704 722 end
705 723 end
706 724
707 725 def test_layout_should_include_the_emails_footer
708 726 with_settings :emails_footer => "*Footer content*" do
709 727 with_settings :plain_text_mail => 0 do
710 728 assert Mailer.test_email(User.find(1)).deliver
711 729 assert_select_email do
712 730 assert_select ".footer" do
713 731 assert_select "strong", :text => "Footer content"
714 732 end
715 733 end
716 734 end
717 735 with_settings :plain_text_mail => 1 do
718 736 assert Mailer.test_email(User.find(1)).deliver
719 737 mail = last_email
720 738 assert_not_nil mail
721 739 assert_include "\n-- \n", mail.body.decoded
722 740 assert_include "*Footer content*", mail.body.decoded
723 741 end
724 742 end
725 743 end
726 744
727 745 def test_layout_should_not_include_empty_emails_footer
728 746 with_settings :emails_footer => "" do
729 747 with_settings :plain_text_mail => 0 do
730 748 assert Mailer.test_email(User.find(1)).deliver
731 749 assert_select_email do
732 750 assert_select ".footer", false
733 751 end
734 752 end
735 753 with_settings :plain_text_mail => 1 do
736 754 assert Mailer.test_email(User.find(1)).deliver
737 755 mail = last_email
738 756 assert_not_nil mail
739 757 assert_not_include "\n-- \n", mail.body.decoded
740 758 end
741 759 end
742 760 end
743 761
744 762 def test_should_escape_html_templates_only
745 763 Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
746 764 mail = last_email
747 765 assert_equal 2, mail.parts.size
748 766 assert_include '<tag>', text_part.body.encoded
749 767 assert_include '&lt;tag&gt;', html_part.body.encoded
750 768 end
751 769
752 770 def test_should_raise_delivery_errors_when_raise_delivery_errors_is_true
753 771 mail = Mailer.test_email(User.find(1))
754 772 mail.delivery_method.stubs(:deliver!).raises(Exception.new("delivery error"))
755 773
756 774 ActionMailer::Base.raise_delivery_errors = true
757 775 assert_raise Exception, "delivery error" do
758 776 mail.deliver
759 777 end
760 778 ensure
761 779 ActionMailer::Base.raise_delivery_errors = false
762 780 end
763 781
764 782 def test_should_log_delivery_errors_when_raise_delivery_errors_is_false
765 783 mail = Mailer.test_email(User.find(1))
766 784 mail.delivery_method.stubs(:deliver!).raises(Exception.new("delivery error"))
767 785
768 786 Rails.logger.expects(:error).with("Email delivery error: delivery error")
769 787 ActionMailer::Base.raise_delivery_errors = false
770 788 assert_nothing_raised do
771 789 mail.deliver
772 790 end
773 791 end
774 792
775 793 def test_with_synched_deliveries_should_yield_with_synced_deliveries
776 794 ActionMailer::Base.delivery_method = :async_smtp
777 795 ActionMailer::Base.async_smtp_settings = {:foo => 'bar'}
778 796
779 797 Mailer.with_synched_deliveries do
780 798 assert_equal :smtp, ActionMailer::Base.delivery_method
781 799 assert_equal({:foo => 'bar'}, ActionMailer::Base.smtp_settings)
782 800 end
783 801 assert_equal :async_smtp, ActionMailer::Base.delivery_method
784 802 ensure
785 803 ActionMailer::Base.delivery_method = :test
786 804 end
787 805
788 806 def test_email_addresses_should_keep_addresses
789 807 assert_equal ["foo@example.net"],
790 808 Mailer.email_addresses("foo@example.net")
791 809
792 810 assert_equal ["foo@example.net", "bar@example.net"],
793 811 Mailer.email_addresses(["foo@example.net", "bar@example.net"])
794 812 end
795 813
796 814 def test_email_addresses_should_replace_users_with_their_email_addresses
797 815 assert_equal ["admin@somenet.foo"],
798 816 Mailer.email_addresses(User.find(1))
799 817
800 818 assert_equal ["admin@somenet.foo", "jsmith@somenet.foo"],
801 819 Mailer.email_addresses(User.where(:id => [1,2])).sort
802 820 end
803 821
804 822 def test_email_addresses_should_include_notified_emails_addresses_only
805 823 EmailAddress.create!(:user_id => 2, :address => "another@somenet.foo", :notify => false)
806 824 EmailAddress.create!(:user_id => 2, :address => "another2@somenet.foo")
807 825
808 826 assert_equal ["another2@somenet.foo", "jsmith@somenet.foo"],
809 827 Mailer.email_addresses(User.find(2)).sort
810 828 end
811 829
812 830 private
813 831
814 832 def last_email
815 833 mail = ActionMailer::Base.deliveries.last
816 834 assert_not_nil mail
817 835 mail
818 836 end
819 837
820 838 def text_part
821 839 last_email.parts.detect {|part| part.content_type.include?('text/plain')}
822 840 end
823 841
824 842 def html_part
825 843 last_email.parts.detect {|part| part.content_type.include?('text/html')}
826 844 end
827 845
828 846 def with_each_language_as_default(&block)
829 847 valid_languages.each do |lang|
830 848 with_settings :default_language => lang.to_s do
831 849 yield lang
832 850 end
833 851 end
834 852 end
835 853 end
General Comments 0
You need to be logged in to leave comments. Login now