##// END OF EJS Templates
Override @#url_for@ in AM to force generation of absolute links (#10251)....
Etienne Massip -
r8902:7056649a4be9
parent child
Show More
@@ -1,477 +1,482
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class Mailer < ActionMailer::Base
18 class Mailer < ActionMailer::Base
19 layout 'mailer'
19 layout 'mailer'
20 helper :application
20 helper :application
21 helper :issues
21 helper :issues
22 helper :custom_fields
22 helper :custom_fields
23
23
24 include ActionController::UrlWriter
24 include ActionController::UrlWriter
25 include Redmine::I18n
25 include Redmine::I18n
26
26
27 def self.default_url_options
27 def self.default_url_options
28 h = Setting.host_name
28 h = Setting.host_name
29 h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
29 h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
30 { :host => h, :protocol => Setting.protocol }
30 { :host => h, :protocol => Setting.protocol }
31 end
31 end
32
32
33 def url_for(options)
34 options[:only_path] = false if options.is_a?(Hash)
35 super options
36 end
37
33 # Builds a tmail object used to email recipients of the added issue.
38 # Builds a tmail object used to email recipients of the added issue.
34 #
39 #
35 # Example:
40 # Example:
36 # issue_add(issue) => tmail object
41 # issue_add(issue) => tmail object
37 # Mailer.deliver_issue_add(issue) => sends an email to issue recipients
42 # Mailer.deliver_issue_add(issue) => sends an email to issue recipients
38 def issue_add(issue)
43 def issue_add(issue)
39 redmine_headers 'Project' => issue.project.identifier,
44 redmine_headers 'Project' => issue.project.identifier,
40 'Issue-Id' => issue.id,
45 'Issue-Id' => issue.id,
41 'Issue-Author' => issue.author.login
46 'Issue-Author' => issue.author.login
42 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
47 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
43 message_id issue
48 message_id issue
44 @author = issue.author
49 @author = issue.author
45 recipients issue.recipients
50 recipients issue.recipients
46 cc(issue.watcher_recipients - @recipients)
51 cc(issue.watcher_recipients - @recipients)
47 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
52 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
48 body :issue => issue,
53 body :issue => issue,
49 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
54 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
50 render_multipart('issue_add', body)
55 render_multipart('issue_add', body)
51 end
56 end
52
57
53 # Builds a tmail object used to email recipients of the edited issue.
58 # Builds a tmail object used to email recipients of the edited issue.
54 #
59 #
55 # Example:
60 # Example:
56 # issue_edit(journal) => tmail object
61 # issue_edit(journal) => tmail object
57 # Mailer.deliver_issue_edit(journal) => sends an email to issue recipients
62 # Mailer.deliver_issue_edit(journal) => sends an email to issue recipients
58 def issue_edit(journal)
63 def issue_edit(journal)
59 issue = journal.journalized.reload
64 issue = journal.journalized.reload
60 redmine_headers 'Project' => issue.project.identifier,
65 redmine_headers 'Project' => issue.project.identifier,
61 'Issue-Id' => issue.id,
66 'Issue-Id' => issue.id,
62 'Issue-Author' => issue.author.login
67 'Issue-Author' => issue.author.login
63 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
68 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
64 message_id journal
69 message_id journal
65 references issue
70 references issue
66 @author = journal.user
71 @author = journal.user
67 recipients issue.recipients
72 recipients issue.recipients
68 # Watchers in cc
73 # Watchers in cc
69 cc(issue.watcher_recipients - @recipients)
74 cc(issue.watcher_recipients - @recipients)
70 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
75 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
71 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
76 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
72 s << issue.subject
77 s << issue.subject
73 subject s
78 subject s
74 body :issue => issue,
79 body :issue => issue,
75 :journal => journal,
80 :journal => journal,
76 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
81 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
77
82
78 render_multipart('issue_edit', body)
83 render_multipart('issue_edit', body)
79 end
84 end
80
85
81 def reminder(user, issues, days)
86 def reminder(user, issues, days)
82 set_language_if_valid user.language
87 set_language_if_valid user.language
83 recipients user.mail
88 recipients user.mail
84 subject l(:mail_subject_reminder, :count => issues.size, :days => days)
89 subject l(:mail_subject_reminder, :count => issues.size, :days => days)
85 body :issues => issues,
90 body :issues => issues,
86 :days => days,
91 :days => days,
87 :issues_url => url_for(:controller => 'issues', :action => 'index',
92 :issues_url => url_for(:controller => 'issues', :action => 'index',
88 :set_filter => 1, :assigned_to_id => user.id,
93 :set_filter => 1, :assigned_to_id => user.id,
89 :sort => 'due_date:asc')
94 :sort => 'due_date:asc')
90 render_multipart('reminder', body)
95 render_multipart('reminder', body)
91 end
96 end
92
97
93 # Builds a tmail object used to email users belonging to the added document's project.
98 # Builds a tmail object used to email users belonging to the added document's project.
94 #
99 #
95 # Example:
100 # Example:
96 # document_added(document) => tmail object
101 # document_added(document) => tmail object
97 # Mailer.deliver_document_added(document) => sends an email to the document's project recipients
102 # Mailer.deliver_document_added(document) => sends an email to the document's project recipients
98 def document_added(document)
103 def document_added(document)
99 redmine_headers 'Project' => document.project.identifier
104 redmine_headers 'Project' => document.project.identifier
100 recipients document.recipients
105 recipients document.recipients
101 subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
106 subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
102 body :document => document,
107 body :document => document,
103 :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
108 :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
104 render_multipart('document_added', body)
109 render_multipart('document_added', body)
105 end
110 end
106
111
107 # Builds a tmail object used to email recipients of a project when an attachements are added.
112 # Builds a tmail object used to email recipients of a project when an attachements are added.
108 #
113 #
109 # Example:
114 # Example:
110 # attachments_added(attachments) => tmail object
115 # attachments_added(attachments) => tmail object
111 # Mailer.deliver_attachments_added(attachments) => sends an email to the project's recipients
116 # Mailer.deliver_attachments_added(attachments) => sends an email to the project's recipients
112 def attachments_added(attachments)
117 def attachments_added(attachments)
113 container = attachments.first.container
118 container = attachments.first.container
114 added_to = ''
119 added_to = ''
115 added_to_url = ''
120 added_to_url = ''
116 case container.class.name
121 case container.class.name
117 when 'Project'
122 when 'Project'
118 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
123 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
119 added_to = "#{l(:label_project)}: #{container}"
124 added_to = "#{l(:label_project)}: #{container}"
120 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
125 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
121 when 'Version'
126 when 'Version'
122 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
127 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
123 added_to = "#{l(:label_version)}: #{container.name}"
128 added_to = "#{l(:label_version)}: #{container.name}"
124 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
129 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
125 when 'Document'
130 when 'Document'
126 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
131 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
127 added_to = "#{l(:label_document)}: #{container.title}"
132 added_to = "#{l(:label_document)}: #{container.title}"
128 recipients container.recipients
133 recipients container.recipients
129 end
134 end
130 redmine_headers 'Project' => container.project.identifier
135 redmine_headers 'Project' => container.project.identifier
131 subject "[#{container.project.name}] #{l(:label_attachment_new)}"
136 subject "[#{container.project.name}] #{l(:label_attachment_new)}"
132 body :attachments => attachments,
137 body :attachments => attachments,
133 :added_to => added_to,
138 :added_to => added_to,
134 :added_to_url => added_to_url
139 :added_to_url => added_to_url
135 render_multipart('attachments_added', body)
140 render_multipart('attachments_added', body)
136 end
141 end
137
142
138 # Builds a tmail object used to email recipients of a news' project when a news item is added.
143 # Builds a tmail object used to email recipients of a news' project when a news item is added.
139 #
144 #
140 # Example:
145 # Example:
141 # news_added(news) => tmail object
146 # news_added(news) => tmail object
142 # Mailer.deliver_news_added(news) => sends an email to the news' project recipients
147 # Mailer.deliver_news_added(news) => sends an email to the news' project recipients
143 def news_added(news)
148 def news_added(news)
144 redmine_headers 'Project' => news.project.identifier
149 redmine_headers 'Project' => news.project.identifier
145 message_id news
150 message_id news
146 recipients news.recipients
151 recipients news.recipients
147 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
152 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
148 body :news => news,
153 body :news => news,
149 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
154 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
150 render_multipart('news_added', body)
155 render_multipart('news_added', body)
151 end
156 end
152
157
153 # Builds a tmail object used to email recipients of a news' project when a news comment is added.
158 # Builds a tmail object used to email recipients of a news' project when a news comment is added.
154 #
159 #
155 # Example:
160 # Example:
156 # news_comment_added(comment) => tmail object
161 # news_comment_added(comment) => tmail object
157 # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
162 # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
158 def news_comment_added(comment)
163 def news_comment_added(comment)
159 news = comment.commented
164 news = comment.commented
160 redmine_headers 'Project' => news.project.identifier
165 redmine_headers 'Project' => news.project.identifier
161 message_id comment
166 message_id comment
162 recipients news.recipients
167 recipients news.recipients
163 cc news.watcher_recipients
168 cc news.watcher_recipients
164 subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
169 subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
165 body :news => news,
170 body :news => news,
166 :comment => comment,
171 :comment => comment,
167 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
172 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
168 render_multipart('news_comment_added', body)
173 render_multipart('news_comment_added', body)
169 end
174 end
170
175
171 # Builds a tmail object used to email the recipients of the specified message that was posted.
176 # Builds a tmail object used to email the recipients of the specified message that was posted.
172 #
177 #
173 # Example:
178 # Example:
174 # message_posted(message) => tmail object
179 # message_posted(message) => tmail object
175 # Mailer.deliver_message_posted(message) => sends an email to the recipients
180 # Mailer.deliver_message_posted(message) => sends an email to the recipients
176 def message_posted(message)
181 def message_posted(message)
177 redmine_headers 'Project' => message.project.identifier,
182 redmine_headers 'Project' => message.project.identifier,
178 'Topic-Id' => (message.parent_id || message.id)
183 'Topic-Id' => (message.parent_id || message.id)
179 message_id message
184 message_id message
180 references message.parent unless message.parent.nil?
185 references message.parent unless message.parent.nil?
181 recipients(message.recipients)
186 recipients(message.recipients)
182 cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
187 cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
183 subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
188 subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
184 body :message => message,
189 body :message => message,
185 :message_url => url_for(message.event_url)
190 :message_url => url_for(message.event_url)
186 render_multipart('message_posted', body)
191 render_multipart('message_posted', body)
187 end
192 end
188
193
189 # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
194 # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
190 #
195 #
191 # Example:
196 # Example:
192 # wiki_content_added(wiki_content) => tmail object
197 # wiki_content_added(wiki_content) => tmail object
193 # Mailer.deliver_wiki_content_added(wiki_content) => sends an email to the project's recipients
198 # Mailer.deliver_wiki_content_added(wiki_content) => sends an email to the project's recipients
194 def wiki_content_added(wiki_content)
199 def wiki_content_added(wiki_content)
195 redmine_headers 'Project' => wiki_content.project.identifier,
200 redmine_headers 'Project' => wiki_content.project.identifier,
196 'Wiki-Page-Id' => wiki_content.page.id
201 'Wiki-Page-Id' => wiki_content.page.id
197 message_id wiki_content
202 message_id wiki_content
198 recipients wiki_content.recipients
203 recipients wiki_content.recipients
199 cc(wiki_content.page.wiki.watcher_recipients - recipients)
204 cc(wiki_content.page.wiki.watcher_recipients - recipients)
200 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
205 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
201 body :wiki_content => wiki_content,
206 body :wiki_content => wiki_content,
202 :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
207 :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
203 :project_id => wiki_content.project,
208 :project_id => wiki_content.project,
204 :id => wiki_content.page.title)
209 :id => wiki_content.page.title)
205 render_multipart('wiki_content_added', body)
210 render_multipart('wiki_content_added', body)
206 end
211 end
207
212
208 # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
213 # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
209 #
214 #
210 # Example:
215 # Example:
211 # wiki_content_updated(wiki_content) => tmail object
216 # wiki_content_updated(wiki_content) => tmail object
212 # Mailer.deliver_wiki_content_updated(wiki_content) => sends an email to the project's recipients
217 # Mailer.deliver_wiki_content_updated(wiki_content) => sends an email to the project's recipients
213 def wiki_content_updated(wiki_content)
218 def wiki_content_updated(wiki_content)
214 redmine_headers 'Project' => wiki_content.project.identifier,
219 redmine_headers 'Project' => wiki_content.project.identifier,
215 'Wiki-Page-Id' => wiki_content.page.id
220 'Wiki-Page-Id' => wiki_content.page.id
216 message_id wiki_content
221 message_id wiki_content
217 recipients wiki_content.recipients
222 recipients wiki_content.recipients
218 cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients)
223 cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients)
219 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
224 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
220 body :wiki_content => wiki_content,
225 body :wiki_content => wiki_content,
221 :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
226 :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
222 :project_id => wiki_content.project,
227 :project_id => wiki_content.project,
223 :id => wiki_content.page.title),
228 :id => wiki_content.page.title),
224 :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff',
229 :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff',
225 :project_id => wiki_content.project, :id => wiki_content.page.title,
230 :project_id => wiki_content.project, :id => wiki_content.page.title,
226 :version => wiki_content.version)
231 :version => wiki_content.version)
227 render_multipart('wiki_content_updated', body)
232 render_multipart('wiki_content_updated', body)
228 end
233 end
229
234
230 # Builds a tmail object used to email the specified user their account information.
235 # Builds a tmail object used to email the specified user their account information.
231 #
236 #
232 # Example:
237 # Example:
233 # account_information(user, password) => tmail object
238 # account_information(user, password) => tmail object
234 # Mailer.deliver_account_information(user, password) => sends account information to the user
239 # Mailer.deliver_account_information(user, password) => sends account information to the user
235 def account_information(user, password)
240 def account_information(user, password)
236 set_language_if_valid user.language
241 set_language_if_valid user.language
237 recipients user.mail
242 recipients user.mail
238 subject l(:mail_subject_register, Setting.app_title)
243 subject l(:mail_subject_register, Setting.app_title)
239 body :user => user,
244 body :user => user,
240 :password => password,
245 :password => password,
241 :login_url => url_for(:controller => 'account', :action => 'login')
246 :login_url => url_for(:controller => 'account', :action => 'login')
242 render_multipart('account_information', body)
247 render_multipart('account_information', body)
243 end
248 end
244
249
245 # Builds a tmail object used to email all active administrators of an account activation request.
250 # Builds a tmail object used to email all active administrators of an account activation request.
246 #
251 #
247 # Example:
252 # Example:
248 # account_activation_request(user) => tmail object
253 # account_activation_request(user) => tmail object
249 # Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators
254 # Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators
250 def account_activation_request(user)
255 def account_activation_request(user)
251 # Send the email to all active administrators
256 # Send the email to all active administrators
252 recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
257 recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
253 subject l(:mail_subject_account_activation_request, Setting.app_title)
258 subject l(:mail_subject_account_activation_request, Setting.app_title)
254 body :user => user,
259 body :user => user,
255 :url => url_for(:controller => 'users', :action => 'index',
260 :url => url_for(:controller => 'users', :action => 'index',
256 :status => User::STATUS_REGISTERED,
261 :status => User::STATUS_REGISTERED,
257 :sort_key => 'created_on', :sort_order => 'desc')
262 :sort_key => 'created_on', :sort_order => 'desc')
258 render_multipart('account_activation_request', body)
263 render_multipart('account_activation_request', body)
259 end
264 end
260
265
261 # Builds a tmail object used to email the specified user that their account was activated by an administrator.
266 # Builds a tmail object used to email the specified user that their account was activated by an administrator.
262 #
267 #
263 # Example:
268 # Example:
264 # account_activated(user) => tmail object
269 # account_activated(user) => tmail object
265 # Mailer.deliver_account_activated(user) => sends an email to the registered user
270 # Mailer.deliver_account_activated(user) => sends an email to the registered user
266 def account_activated(user)
271 def account_activated(user)
267 set_language_if_valid user.language
272 set_language_if_valid user.language
268 recipients user.mail
273 recipients user.mail
269 subject l(:mail_subject_register, Setting.app_title)
274 subject l(:mail_subject_register, Setting.app_title)
270 body :user => user,
275 body :user => user,
271 :login_url => url_for(:controller => 'account', :action => 'login')
276 :login_url => url_for(:controller => 'account', :action => 'login')
272 render_multipart('account_activated', body)
277 render_multipart('account_activated', body)
273 end
278 end
274
279
275 def lost_password(token)
280 def lost_password(token)
276 set_language_if_valid(token.user.language)
281 set_language_if_valid(token.user.language)
277 recipients token.user.mail
282 recipients token.user.mail
278 subject l(:mail_subject_lost_password, Setting.app_title)
283 subject l(:mail_subject_lost_password, Setting.app_title)
279 body :token => token,
284 body :token => token,
280 :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
285 :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
281 render_multipart('lost_password', body)
286 render_multipart('lost_password', body)
282 end
287 end
283
288
284 def register(token)
289 def register(token)
285 set_language_if_valid(token.user.language)
290 set_language_if_valid(token.user.language)
286 recipients token.user.mail
291 recipients token.user.mail
287 subject l(:mail_subject_register, Setting.app_title)
292 subject l(:mail_subject_register, Setting.app_title)
288 body :token => token,
293 body :token => token,
289 :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
294 :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
290 render_multipart('register', body)
295 render_multipart('register', body)
291 end
296 end
292
297
293 def test(user)
298 def test(user)
294 set_language_if_valid(user.language)
299 set_language_if_valid(user.language)
295 recipients user.mail
300 recipients user.mail
296 subject 'Redmine test'
301 subject 'Redmine test'
297 body :url => url_for(:controller => 'welcome')
302 body :url => url_for(:controller => 'welcome')
298 render_multipart('test', body)
303 render_multipart('test', body)
299 end
304 end
300
305
301 # Overrides default deliver! method to prevent from sending an email
306 # Overrides default deliver! method to prevent from sending an email
302 # with no recipient, cc or bcc
307 # with no recipient, cc or bcc
303 def deliver!(mail = @mail)
308 def deliver!(mail = @mail)
304 set_language_if_valid @initial_language
309 set_language_if_valid @initial_language
305 return false if (recipients.nil? || recipients.empty?) &&
310 return false if (recipients.nil? || recipients.empty?) &&
306 (cc.nil? || cc.empty?) &&
311 (cc.nil? || cc.empty?) &&
307 (bcc.nil? || bcc.empty?)
312 (bcc.nil? || bcc.empty?)
308
313
309 # Set Message-Id and References
314 # Set Message-Id and References
310 if @message_id_object
315 if @message_id_object
311 mail.message_id = self.class.message_id_for(@message_id_object)
316 mail.message_id = self.class.message_id_for(@message_id_object)
312 end
317 end
313 if @references_objects
318 if @references_objects
314 mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
319 mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
315 end
320 end
316
321
317 # Log errors when raise_delivery_errors is set to false, Rails does not
322 # Log errors when raise_delivery_errors is set to false, Rails does not
318 raise_errors = self.class.raise_delivery_errors
323 raise_errors = self.class.raise_delivery_errors
319 self.class.raise_delivery_errors = true
324 self.class.raise_delivery_errors = true
320 begin
325 begin
321 return super(mail)
326 return super(mail)
322 rescue Exception => e
327 rescue Exception => e
323 if raise_errors
328 if raise_errors
324 raise e
329 raise e
325 elsif mylogger
330 elsif mylogger
326 mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
331 mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
327 end
332 end
328 ensure
333 ensure
329 self.class.raise_delivery_errors = raise_errors
334 self.class.raise_delivery_errors = raise_errors
330 end
335 end
331 end
336 end
332
337
333 # Sends reminders to issue assignees
338 # Sends reminders to issue assignees
334 # Available options:
339 # Available options:
335 # * :days => how many days in the future to remind about (defaults to 7)
340 # * :days => how many days in the future to remind about (defaults to 7)
336 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
341 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
337 # * :project => id or identifier of project to process (defaults to all projects)
342 # * :project => id or identifier of project to process (defaults to all projects)
338 # * :users => array of user ids who should be reminded
343 # * :users => array of user ids who should be reminded
339 def self.reminders(options={})
344 def self.reminders(options={})
340 days = options[:days] || 7
345 days = options[:days] || 7
341 project = options[:project] ? Project.find(options[:project]) : nil
346 project = options[:project] ? Project.find(options[:project]) : nil
342 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
347 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
343 user_ids = options[:users]
348 user_ids = options[:users]
344
349
345 scope = Issue.open.scoped(:conditions => ["#{Issue.table_name}.assigned_to_id IS NOT NULL" +
350 scope = Issue.open.scoped(:conditions => ["#{Issue.table_name}.assigned_to_id IS NOT NULL" +
346 " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
351 " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
347 " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date]
352 " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date]
348 )
353 )
349 scope = scope.scoped(:conditions => {:assigned_to_id => user_ids}) if user_ids.present?
354 scope = scope.scoped(:conditions => {:assigned_to_id => user_ids}) if user_ids.present?
350 scope = scope.scoped(:conditions => {:project_id => project.id}) if project
355 scope = scope.scoped(:conditions => {:project_id => project.id}) if project
351 scope = scope.scoped(:conditions => {:tracker_id => tracker.id}) if tracker
356 scope = scope.scoped(:conditions => {:tracker_id => tracker.id}) if tracker
352
357
353 issues_by_assignee = scope.all(:include => [:status, :assigned_to, :project, :tracker]).group_by(&:assigned_to)
358 issues_by_assignee = scope.all(:include => [:status, :assigned_to, :project, :tracker]).group_by(&:assigned_to)
354 issues_by_assignee.each do |assignee, issues|
359 issues_by_assignee.each do |assignee, issues|
355 deliver_reminder(assignee, issues, days) if assignee && assignee.active?
360 deliver_reminder(assignee, issues, days) if assignee && assignee.active?
356 end
361 end
357 end
362 end
358
363
359 # Activates/desactivates email deliveries during +block+
364 # Activates/desactivates email deliveries during +block+
360 def self.with_deliveries(enabled = true, &block)
365 def self.with_deliveries(enabled = true, &block)
361 was_enabled = ActionMailer::Base.perform_deliveries
366 was_enabled = ActionMailer::Base.perform_deliveries
362 ActionMailer::Base.perform_deliveries = !!enabled
367 ActionMailer::Base.perform_deliveries = !!enabled
363 yield
368 yield
364 ensure
369 ensure
365 ActionMailer::Base.perform_deliveries = was_enabled
370 ActionMailer::Base.perform_deliveries = was_enabled
366 end
371 end
367
372
368 private
373 private
369 def initialize_defaults(method_name)
374 def initialize_defaults(method_name)
370 super
375 super
371 @initial_language = current_language
376 @initial_language = current_language
372 set_language_if_valid Setting.default_language
377 set_language_if_valid Setting.default_language
373 from Setting.mail_from
378 from Setting.mail_from
374
379
375 # Common headers
380 # Common headers
376 headers 'X-Mailer' => 'Redmine',
381 headers 'X-Mailer' => 'Redmine',
377 'X-Redmine-Host' => Setting.host_name,
382 'X-Redmine-Host' => Setting.host_name,
378 'X-Redmine-Site' => Setting.app_title,
383 'X-Redmine-Site' => Setting.app_title,
379 'X-Auto-Response-Suppress' => 'OOF',
384 'X-Auto-Response-Suppress' => 'OOF',
380 'Auto-Submitted' => 'auto-generated'
385 'Auto-Submitted' => 'auto-generated'
381 end
386 end
382
387
383 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
388 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
384 def redmine_headers(h)
389 def redmine_headers(h)
385 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
390 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
386 end
391 end
387
392
388 # Overrides the create_mail method
393 # Overrides the create_mail method
389 def create_mail
394 def create_mail
390 # Removes the current user from the recipients and cc
395 # Removes the current user from the recipients and cc
391 # if he doesn't want to receive notifications about what he does
396 # if he doesn't want to receive notifications about what he does
392 @author ||= User.current
397 @author ||= User.current
393 if @author.pref[:no_self_notified]
398 if @author.pref[:no_self_notified]
394 recipients.delete(@author.mail) if recipients
399 recipients.delete(@author.mail) if recipients
395 cc.delete(@author.mail) if cc
400 cc.delete(@author.mail) if cc
396 end
401 end
397
402
398 if @author.logged?
403 if @author.logged?
399 redmine_headers 'Sender' => @author.login
404 redmine_headers 'Sender' => @author.login
400 end
405 end
401
406
402 notified_users = [recipients, cc].flatten.compact.uniq
407 notified_users = [recipients, cc].flatten.compact.uniq
403 # Rails would log recipients only, not cc and bcc
408 # Rails would log recipients only, not cc and bcc
404 mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
409 mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
405
410
406 # Blind carbon copy recipients
411 # Blind carbon copy recipients
407 if Setting.bcc_recipients?
412 if Setting.bcc_recipients?
408 bcc(notified_users)
413 bcc(notified_users)
409 recipients []
414 recipients []
410 cc []
415 cc []
411 end
416 end
412 super
417 super
413 end
418 end
414
419
415 # Rails 2.3 has problems rendering implicit multipart messages with
420 # Rails 2.3 has problems rendering implicit multipart messages with
416 # layouts so this method will wrap an multipart messages with
421 # layouts so this method will wrap an multipart messages with
417 # explicit parts.
422 # explicit parts.
418 #
423 #
419 # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
424 # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
420 # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
425 # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
421
426
422 def render_multipart(method_name, body)
427 def render_multipart(method_name, body)
423 if Setting.plain_text_mail?
428 if Setting.plain_text_mail?
424 content_type "text/plain"
429 content_type "text/plain"
425 body render(:file => "#{method_name}.text.erb",
430 body render(:file => "#{method_name}.text.erb",
426 :body => body,
431 :body => body,
427 :layout => 'mailer.text.erb')
432 :layout => 'mailer.text.erb')
428 else
433 else
429 content_type "multipart/alternative"
434 content_type "multipart/alternative"
430 part :content_type => "text/plain",
435 part :content_type => "text/plain",
431 :body => render(:file => "#{method_name}.text.erb",
436 :body => render(:file => "#{method_name}.text.erb",
432 :body => body, :layout => 'mailer.text.erb')
437 :body => body, :layout => 'mailer.text.erb')
433 part :content_type => "text/html",
438 part :content_type => "text/html",
434 :body => render_message("#{method_name}.html.erb", body)
439 :body => render_message("#{method_name}.html.erb", body)
435 end
440 end
436 end
441 end
437
442
438 # Makes partial rendering work with Rails 1.2 (retro-compatibility)
443 # Makes partial rendering work with Rails 1.2 (retro-compatibility)
439 def self.controller_path
444 def self.controller_path
440 ''
445 ''
441 end unless respond_to?('controller_path')
446 end unless respond_to?('controller_path')
442
447
443 # Returns a predictable Message-Id for the given object
448 # Returns a predictable Message-Id for the given object
444 def self.message_id_for(object)
449 def self.message_id_for(object)
445 # id + timestamp should reduce the odds of a collision
450 # id + timestamp should reduce the odds of a collision
446 # as far as we don't send multiple emails for the same object
451 # as far as we don't send multiple emails for the same object
447 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
452 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
448 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
453 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
449 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
454 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
450 host = "#{::Socket.gethostname}.redmine" if host.empty?
455 host = "#{::Socket.gethostname}.redmine" if host.empty?
451 "<#{hash}@#{host}>"
456 "<#{hash}@#{host}>"
452 end
457 end
453
458
454 private
459 private
455
460
456 def message_id(object)
461 def message_id(object)
457 @message_id_object = object
462 @message_id_object = object
458 end
463 end
459
464
460 def references(object)
465 def references(object)
461 @references_objects ||= []
466 @references_objects ||= []
462 @references_objects << object
467 @references_objects << object
463 end
468 end
464
469
465 def mylogger
470 def mylogger
466 Rails.logger
471 Rails.logger
467 end
472 end
468 end
473 end
469
474
470 # Patch TMail so that message_id is not overwritten
475 # Patch TMail so that message_id is not overwritten
471 module TMail
476 module TMail
472 class Mail
477 class Mail
473 def add_message_id( fqdn = nil )
478 def add_message_id( fqdn = nil )
474 self.message_id ||= ::TMail::new_message_id(fqdn)
479 self.message_id ||= ::TMail::new_message_id(fqdn)
475 end
480 end
476 end
481 end
477 end
482 end
@@ -1,15 +1,15
1 <h1><%= link_to(h("#{issue.tracker.name} ##{issue.id}: #{issue.subject}"), issue_url) %></h1>
1 <h1><%= link_to(h("#{issue.tracker.name} ##{issue.id}: #{issue.subject}"), issue_url) %></h1>
2
2
3 <ul>
3 <ul>
4 <li><%=l(:field_author)%>: <%=h issue.author %></li>
4 <li><%=l(:field_author)%>: <%=h issue.author %></li>
5 <li><%=l(:field_status)%>: <%=h issue.status %></li>
5 <li><%=l(:field_status)%>: <%=h issue.status %></li>
6 <li><%=l(:field_priority)%>: <%=h issue.priority %></li>
6 <li><%=l(:field_priority)%>: <%=h issue.priority %></li>
7 <li><%=l(:field_assigned_to)%>: <%=h issue.assigned_to %></li>
7 <li><%=l(:field_assigned_to)%>: <%=h issue.assigned_to %></li>
8 <li><%=l(:field_category)%>: <%=h issue.category %></li>
8 <li><%=l(:field_category)%>: <%=h issue.category %></li>
9 <li><%=l(:field_fixed_version)%>: <%=h issue.fixed_version %></li>
9 <li><%=l(:field_fixed_version)%>: <%=h issue.fixed_version %></li>
10 <% issue.custom_field_values.each do |c| %>
10 <% issue.custom_field_values.each do |c| %>
11 <li><%=h c.custom_field.name %>: <%=h show_value(c) %></li>
11 <li><%=h c.custom_field.name %>: <%=h show_value(c) %></li>
12 <% end %>
12 <% end %>
13 </ul>
13 </ul>
14
14
15 <%= textilizable(issue, :description, :only_path => false) %>
15 <%= textilizable(issue, :description) %>
@@ -1,3 +1,3
1 <%= link_to(h(@document.title), @document_url) %> (<%=h @document.category.name %>)<br />
1 <%= link_to(h(@document.title), @document_url) %> (<%=h @document.category.name %>)<br />
2 <br />
2 <br />
3 <%= textilizable(@document, :description, :only_path => false) %>
3 <%= textilizable(@document, :description) %>
@@ -1,11 +1,11
1 <%= l(:text_issue_updated, :id => "##{@issue.id}", :author => h(@journal.user)) %>
1 <%= l(:text_issue_updated, :id => "##{@issue.id}", :author => h(@journal.user)) %>
2
2
3 <ul>
3 <ul>
4 <% details_to_strings(@journal.details).each do |string| %>
4 <% details_to_strings(@journal.details).each do |string| %>
5 <li><%= string %></li>
5 <li><%= string %></li>
6 <% end %>
6 <% end %>
7 </ul>
7 </ul>
8
8
9 <%= textilizable(@journal, :notes, :only_path => false) %>
9 <%= textilizable(@journal, :notes) %>
10 <hr />
10 <hr />
11 <%= render :partial => "issue.html.erb", :locals => { :issue => @issue, :issue_url => @issue_url } %>
11 <%= render :partial => "issue.html.erb", :locals => { :issue => @issue, :issue_url => @issue_url } %>
@@ -1,4 +1,4
1 <h1><%=h @message.board.project.name %> - <%=h @message.board.name %>: <%= link_to(h(@message.subject), @message_url) %></h1>
1 <h1><%=h @message.board.project.name %> - <%=h @message.board.name %>: <%= link_to(h(@message.subject), @message_url) %></h1>
2 <em><%=h @message.author %></em>
2 <em><%=h @message.author %></em>
3
3
4 <%= textilizable(@message, :content, :only_path => false) %>
4 <%= textilizable(@message, :content) %>
@@ -1,4 +1,4
1 <h1><%= link_to(h(@news.title), @news_url) %></h1>
1 <h1><%= link_to(h(@news.title), @news_url) %></h1>
2 <em><%=h @news.author.name %></em>
2 <em><%=h @news.author.name %></em>
3
3
4 <%= textilizable(@news, :description, :only_path => false) %>
4 <%= textilizable(@news, :description) %>
@@ -1,5 +1,5
1 <h1><%= link_to(h(@news.title), @news_url) %></h1>
1 <h1><%= link_to(h(@news.title), @news_url) %></h1>
2
2
3 <p><%= l(:text_user_wrote, :value => h(@comment.author)) %></p>
3 <p><%= l(:text_user_wrote, :value => h(@comment.author)) %></p>
4
4
5 <%= textilizable @comment, :comments, :only_path => false %>
5 <%= textilizable @comment, :comments %>
@@ -1,9 +1,9
1 <p><%= l(:mail_body_reminder, :count => @issues.size, :days => @days) %></p>
1 <p><%= l(:mail_body_reminder, :count => @issues.size, :days => @days) %></p>
2
2
3 <ul>
3 <ul>
4 <% @issues.each do |issue| -%>
4 <% @issues.each do |issue| -%>
5 <li><%=h issue.project %> - <%=link_to(h("#{issue.tracker} ##{issue.id}"), :controller => 'issues', :action => 'show', :id => issue, :only_path => false)%>: <%=h issue.subject %></li>
5 <li><%=h issue.project %> - <%=link_to(h("#{issue.tracker} ##{issue.id}"), :controller => 'issues', :action => 'show', :id => issue)%>: <%=h issue.subject %></li>
6 <% end -%>
6 <% end -%>
7 </ul>
7 </ul>
8
8
9 <p><%= link_to l(:label_issue_view_all), @issues_url %></p>
9 <p><%= link_to l(:label_issue_view_all), @issues_url %></p>
@@ -1,36 +1,43
1 ---
1 ---
2 journal_details_001:
2 journal_details_001:
3 old_value: "1"
3 old_value: "1"
4 property: attr
4 property: attr
5 id: 1
5 id: 1
6 value: "2"
6 value: "2"
7 prop_key: status_id
7 prop_key: status_id
8 journal_id: 1
8 journal_id: 1
9 journal_details_002:
9 journal_details_002:
10 old_value: "40"
10 old_value: "40"
11 property: attr
11 property: attr
12 id: 2
12 id: 2
13 value: "30"
13 value: "30"
14 prop_key: done_ratio
14 prop_key: done_ratio
15 journal_id: 1
15 journal_id: 1
16 journal_details_003:
16 journal_details_003:
17 old_value: nil
17 old_value: nil
18 property: attr
18 property: attr
19 id: 3
19 id: 3
20 value: "6"
20 value: "6"
21 prop_key: fixed_version_id
21 prop_key: fixed_version_id
22 journal_id: 4
22 journal_id: 4
23 journal_details_004:
23 journal_details_004:
24 old_value: "This word was removed and an other was"
24 old_value: "This word was removed and an other was"
25 property: attr
25 property: attr
26 id: 4
26 id: 4
27 value: "This word was and an other was added"
27 value: "This word was and an other was added"
28 prop_key: description
28 prop_key: description
29 journal_id: 3
29 journal_id: 3
30 journal_details_005:
30 journal_details_005:
31 old_value: Old value
31 old_value: Old value
32 property: cf
32 property: cf
33 id: 5
33 id: 5
34 value: New value
34 value: New value
35 prop_key: 2
35 prop_key: 2
36 journal_id: 3
36 journal_id: 3
37 journal_details_006:
38 old_value: nil
39 property: attachment
40 id: 6
41 value: 060719210727_picture.jpg
42 prop_key: 4
43 journal_id: 3
@@ -1,36 +1,36
1 ---
1 ---
2 journals_001:
2 journals_001:
3 created_on: <%= 2.days.ago.to_date.to_s(:db) %>
3 created_on: <%= 2.days.ago.to_date.to_s(:db) %>
4 notes: "Journal notes"
4 notes: "Journal notes"
5 id: 1
5 id: 1
6 journalized_type: Issue
6 journalized_type: Issue
7 user_id: 1
7 user_id: 1
8 journalized_id: 1
8 journalized_id: 1
9 journals_002:
9 journals_002:
10 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
10 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
11 notes: "Some notes with Redmine links: #2, r2."
11 notes: "Some notes with Redmine links: #2, r2."
12 id: 2
12 id: 2
13 journalized_type: Issue
13 journalized_type: Issue
14 user_id: 2
14 user_id: 2
15 journalized_id: 1
15 journalized_id: 1
16 journals_003:
16 journals_003:
17 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
17 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
18 notes: "A comment with inline image: !picture.jpg!"
18 notes: "A comment with inline image: !picture.jpg! and a reference to #1 and r2."
19 id: 3
19 id: 3
20 journalized_type: Issue
20 journalized_type: Issue
21 user_id: 2
21 user_id: 2
22 journalized_id: 2
22 journalized_id: 2
23 journals_004:
23 journals_004:
24 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
24 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
25 notes: "A comment with a private version."
25 notes: "A comment with a private version."
26 id: 4
26 id: 4
27 journalized_type: Issue
27 journalized_type: Issue
28 user_id: 1
28 user_id: 1
29 journalized_id: 6
29 journalized_id: 6
30 journals_005:
30 journals_005:
31 id: 5
31 id: 5
32 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
32 created_on: <%= 1.days.ago.to_date.to_s(:db) %>
33 notes: "A comment on a private issue."
33 notes: "A comment on a private issue."
34 user_id: 2
34 user_id: 2
35 journalized_type: Issue
35 journalized_type: Issue
36 journalized_id: 14
36 journalized_id: 14
@@ -1,526 +1,549
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class MailerTest < ActiveSupport::TestCase
20 class MailerTest < ActiveSupport::TestCase
21 include Redmine::I18n
21 include Redmine::I18n
22 include ActionController::Assertions::SelectorAssertions
22 include ActionController::Assertions::SelectorAssertions
23 fixtures :projects, :enabled_modules, :issues, :users, :members,
23 fixtures :projects, :enabled_modules, :issues, :users, :members,
24 :member_roles, :roles, :documents, :attachments, :news,
24 :member_roles, :roles, :documents, :attachments, :news,
25 :tokens, :journals, :journal_details, :changesets, :trackers,
25 :tokens, :journals, :journal_details, :changesets, :trackers,
26 :issue_statuses, :enumerations, :messages, :boards, :repositories,
26 :issue_statuses, :enumerations, :messages, :boards, :repositories,
27 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
27 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
28 :versions,
28 :versions,
29 :comments
29 :comments
30
30
31 def setup
31 def setup
32 ActionMailer::Base.deliveries.clear
32 ActionMailer::Base.deliveries.clear
33 Setting.host_name = 'mydomain.foo'
33 Setting.host_name = 'mydomain.foo'
34 Setting.protocol = 'http'
34 Setting.protocol = 'http'
35 Setting.plain_text_mail = '0'
35 Setting.plain_text_mail = '0'
36 end
36 end
37
37
38 def test_generated_links_in_emails
38 def test_generated_links_in_emails
39 Setting.default_language = 'en'
39 Setting.host_name = 'mydomain.foo'
40 Setting.host_name = 'mydomain.foo'
40 Setting.protocol = 'https'
41 Setting.protocol = 'https'
41
42
42 journal = Journal.find(2)
43 journal = Journal.find(3)
43 assert Mailer.deliver_issue_edit(journal)
44 assert Mailer.deliver_issue_edit(journal)
44
45
45 mail = ActionMailer::Base.deliveries.last
46 mail = last_email
46 assert_not_nil mail
47 assert_not_nil mail
47
48
48 assert_select_email do
49 assert_select_email do
49 # link to the main ticket
50 # link to the main ticket
50 assert_select "a[href=?]",
51 assert_select 'a[href=?]',
51 "https://mydomain.foo/issues/1#change-2",
52 'https://mydomain.foo/issues/2#change-3',
52 :text => "Bug #1: Can't print recipes"
53 :text => 'Feature request #2: Add ingredients categories'
53 # link to a referenced ticket
54 # link to a referenced ticket
54 assert_select "a[href=?][title=?]",
55 assert_select 'a[href=?][title=?]',
55 "https://mydomain.foo/issues/2",
56 'https://mydomain.foo/issues/1',
56 "Add ingredients categories (Assigned)",
57 'Can\'t print recipes (New)',
57 :text => "#2"
58 :text => '#1'
58 # link to a changeset
59 # link to a changeset
59 assert_select "a[href=?][title=?]",
60 assert_select 'a[href=?][title=?]',
60 "https://mydomain.foo/projects/ecookbook/repository/revisions/2",
61 'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
61 "This commit fixes #1, #2 and references #1 &amp; #3",
62 'This commit fixes #1, #2 and references #1 &amp; #3',
62 :text => "r2"
63 :text => 'r2'
64 # link to a description diff
65 assert_select 'a[href=?][title=?]',
66 'https://mydomain.foo/journals/diff/3?detail_id=4',
67 'View differences',
68 :text => 'diff'
69 # link to an attachment
70 assert_select 'a[href=?]',
71 'https://mydomain.foo/attachments/download/4/source.rb',
72 :text => 'source.rb'
63 end
73 end
64 end
74 end
65
75
66 def test_generated_links_with_prefix
76 def test_generated_links_with_prefix
77 Setting.default_language = 'en'
67 relative_url_root = Redmine::Utils.relative_url_root
78 relative_url_root = Redmine::Utils.relative_url_root
68 Setting.host_name = 'mydomain.foo/rdm'
79 Setting.host_name = 'mydomain.foo/rdm'
69 Setting.protocol = 'http'
80 Setting.protocol = 'http'
70 Redmine::Utils.relative_url_root = '/rdm'
81 Redmine::Utils.relative_url_root = '/rdm'
71
82
72 journal = Journal.find(2)
83 journal = Journal.find(3)
73 assert Mailer.deliver_issue_edit(journal)
84 assert Mailer.deliver_issue_edit(journal)
74
85
75 mail = ActionMailer::Base.deliveries.last
86 mail = last_email
76 assert_not_nil mail
87 assert_not_nil mail
77
88
78 assert_select_email do
89 assert_select_email do
79 # link to the main ticket
90 # link to the main ticket
80 assert_select "a[href=?]",
91 assert_select 'a[href=?]',
81 "http://mydomain.foo/rdm/issues/1#change-2",
92 'http://mydomain.foo/rdm/issues/2#change-3',
82 :text => "Bug #1: Can't print recipes"
93 :text => 'Feature request #2: Add ingredients categories'
83 # link to a referenced ticket
94 # link to a referenced ticket
84 assert_select "a[href=?][title=?]",
95 assert_select 'a[href=?][title=?]',
85 "http://mydomain.foo/rdm/issues/2",
96 'http://mydomain.foo/rdm/issues/1',
86 "Add ingredients categories (Assigned)",
97 'Can\'t print recipes (New)',
87 :text => "#2"
98 :text => '#1'
88 # link to a changeset
99 # link to a changeset
89 assert_select "a[href=?][title=?]",
100 assert_select 'a[href=?][title=?]',
90 "http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2",
101 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
91 "This commit fixes #1, #2 and references #1 &amp; #3",
102 'This commit fixes #1, #2 and references #1 &amp; #3',
92 :text => "r2"
103 :text => 'r2'
104 # link to a description diff
105 assert_select 'a[href=?][title=?]',
106 'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
107 'View differences',
108 :text => 'diff'
109 # link to an attachment
110 assert_select 'a[href=?]',
111 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
112 :text => 'source.rb'
93 end
113 end
94 ensure
114 ensure
95 # restore it
115 # restore it
96 Redmine::Utils.relative_url_root = relative_url_root
116 Redmine::Utils.relative_url_root = relative_url_root
97 end
117 end
98
118
99 def test_generated_links_with_prefix_and_no_relative_url_root
119 def test_generated_links_with_prefix_and_no_relative_url_root
120 Setting.default_language = 'en'
100 relative_url_root = Redmine::Utils.relative_url_root
121 relative_url_root = Redmine::Utils.relative_url_root
101 Setting.host_name = 'mydomain.foo/rdm'
122 Setting.host_name = 'mydomain.foo/rdm'
102 Setting.protocol = 'http'
123 Setting.protocol = 'http'
103 Redmine::Utils.relative_url_root = nil
124 Redmine::Utils.relative_url_root = nil
104
125
105 journal = Journal.find(2)
126 journal = Journal.find(3)
106 assert Mailer.deliver_issue_edit(journal)
127 assert Mailer.deliver_issue_edit(journal)
107
128
108 mail = ActionMailer::Base.deliveries.last
129 mail = last_email
109 assert_not_nil mail
130 assert_not_nil mail
110
131
111 assert_select_email do
132 assert_select_email do
112 # link to the main ticket
133 # link to the main ticket
113 assert_select "a[href=?]",
134 assert_select 'a[href=?]',
114 "http://mydomain.foo/rdm/issues/1#change-2",
135 'http://mydomain.foo/rdm/issues/2#change-3',
115 :text => "Bug #1: Can't print recipes"
136 :text => 'Feature request #2: Add ingredients categories'
116 # link to a referenced ticket
137 # link to a referenced ticket
117 assert_select "a[href=?][title=?]",
138 assert_select 'a[href=?][title=?]',
118 "http://mydomain.foo/rdm/issues/2",
139 'http://mydomain.foo/rdm/issues/1',
119 "Add ingredients categories (Assigned)",
140 'Can\'t print recipes (New)',
120 :text => "#2"
141 :text => '#1'
121 # link to a changeset
142 # link to a changeset
122 assert_select "a[href=?][title=?]",
143 assert_select 'a[href=?][title=?]',
123 "http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2",
144 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
124 "This commit fixes #1, #2 and references #1 &amp; #3",
145 'This commit fixes #1, #2 and references #1 &amp; #3',
125 :text => "r2"
146 :text => 'r2'
147 # link to a description diff
148 assert_select 'a[href=?][title=?]',
149 'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
150 'View differences',
151 :text => 'diff'
152 # link to an attachment
153 assert_select 'a[href=?]',
154 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
155 :text => 'source.rb'
126 end
156 end
127 ensure
157 ensure
128 # restore it
158 # restore it
129 Redmine::Utils.relative_url_root = relative_url_root
159 Redmine::Utils.relative_url_root = relative_url_root
130 end
160 end
131
161
132 def test_email_headers
162 def test_email_headers
133 issue = Issue.find(1)
163 issue = Issue.find(1)
134 Mailer.deliver_issue_add(issue)
164 Mailer.deliver_issue_add(issue)
135 mail = ActionMailer::Base.deliveries.last
165 mail = last_email
136 assert_not_nil mail
166 assert_not_nil mail
137 assert_equal 'OOF', mail.header_string('X-Auto-Response-Suppress')
167 assert_equal 'OOF', mail.header_string('X-Auto-Response-Suppress')
138 assert_equal 'auto-generated', mail.header_string('Auto-Submitted')
168 assert_equal 'auto-generated', mail.header_string('Auto-Submitted')
139 end
169 end
140
170
141 def test_email_headers_should_include_sender
171 def test_email_headers_should_include_sender
142 issue = Issue.find(1)
172 issue = Issue.find(1)
143 Mailer.deliver_issue_add(issue)
173 Mailer.deliver_issue_add(issue)
144 mail = ActionMailer::Base.deliveries.last
174 mail = last_email
145 assert_not_nil mail
146 assert_equal issue.author.login, mail.header_string('X-Redmine-Sender')
175 assert_equal issue.author.login, mail.header_string('X-Redmine-Sender')
147 end
176 end
148
177
149 def test_plain_text_mail
178 def test_plain_text_mail
150 Setting.plain_text_mail = 1
179 Setting.plain_text_mail = 1
151 journal = Journal.find(2)
180 journal = Journal.find(2)
152 Mailer.deliver_issue_edit(journal)
181 Mailer.deliver_issue_edit(journal)
153 mail = ActionMailer::Base.deliveries.last
182 mail = last_email
154 assert_equal "text/plain", mail.content_type
183 assert_equal "text/plain", mail.content_type
155 assert_equal 0, mail.parts.size
184 assert_equal 0, mail.parts.size
156 assert !mail.encoded.include?('href')
185 assert !mail.encoded.include?('href')
157 end
186 end
158
187
159 def test_html_mail
188 def test_html_mail
160 Setting.plain_text_mail = 0
189 Setting.plain_text_mail = 0
161 journal = Journal.find(2)
190 journal = Journal.find(2)
162 Mailer.deliver_issue_edit(journal)
191 Mailer.deliver_issue_edit(journal)
163 mail = ActionMailer::Base.deliveries.last
192 mail = last_email
164 assert_equal 2, mail.parts.size
193 assert_equal 2, mail.parts.size
165 assert mail.encoded.include?('href')
194 assert mail.encoded.include?('href')
166 end
195 end
167
196
168 def test_from_header
197 def test_from_header
169 with_settings :mail_from => 'redmine@example.net' do
198 with_settings :mail_from => 'redmine@example.net' do
170 Mailer.deliver_test(User.find(1))
199 Mailer.deliver_test(User.find(1))
171 end
200 end
172 mail = ActionMailer::Base.deliveries.last
201 mail = last_email
173 assert_not_nil mail
174 assert_equal 'redmine@example.net', mail.from_addrs.first.address
202 assert_equal 'redmine@example.net', mail.from_addrs.first.address
175 end
203 end
176
204
177 def test_from_header_with_phrase
205 def test_from_header_with_phrase
178 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
206 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
179 Mailer.deliver_test(User.find(1))
207 Mailer.deliver_test(User.find(1))
180 end
208 end
181 mail = ActionMailer::Base.deliveries.last
209 mail = last_email
182 assert_not_nil mail
183 assert_equal 'redmine@example.net', mail.from_addrs.first.address
210 assert_equal 'redmine@example.net', mail.from_addrs.first.address
184 assert_equal 'Redmine app', mail.from_addrs.first.name
211 assert_equal 'Redmine app', mail.from_addrs.first.name
185 end
212 end
186
213
187 def test_should_not_send_email_without_recipient
214 def test_should_not_send_email_without_recipient
188 news = News.find(:first)
215 news = News.find(:first)
189 user = news.author
216 user = news.author
190 # Remove members except news author
217 # Remove members except news author
191 news.project.memberships.each {|m| m.destroy unless m.user == user}
218 news.project.memberships.each {|m| m.destroy unless m.user == user}
192
219
193 user.pref[:no_self_notified] = false
220 user.pref[:no_self_notified] = false
194 user.pref.save
221 user.pref.save
195 User.current = user
222 User.current = user
196 Mailer.deliver_news_added(news.reload)
223 Mailer.deliver_news_added(news.reload)
197 assert_equal 1, last_email.bcc.size
224 assert_equal 1, last_email.bcc.size
198
225
199 # nobody to notify
226 # nobody to notify
200 user.pref[:no_self_notified] = true
227 user.pref[:no_self_notified] = true
201 user.pref.save
228 user.pref.save
202 User.current = user
229 User.current = user
203 ActionMailer::Base.deliveries.clear
230 ActionMailer::Base.deliveries.clear
204 Mailer.deliver_news_added(news.reload)
231 Mailer.deliver_news_added(news.reload)
205 assert ActionMailer::Base.deliveries.empty?
232 assert ActionMailer::Base.deliveries.empty?
206 end
233 end
207
234
208 def test_issue_add_message_id
235 def test_issue_add_message_id
209 issue = Issue.find(1)
236 issue = Issue.find(1)
210 Mailer.deliver_issue_add(issue)
237 Mailer.deliver_issue_add(issue)
211 mail = ActionMailer::Base.deliveries.last
238 mail = last_email
212 assert_not_nil mail
213 assert_equal Mailer.message_id_for(issue), mail.message_id
239 assert_equal Mailer.message_id_for(issue), mail.message_id
214 assert_nil mail.references
240 assert_nil mail.references
215 end
241 end
216
242
217 def test_issue_edit_message_id
243 def test_issue_edit_message_id
218 journal = Journal.find(1)
244 journal = Journal.find(1)
219 Mailer.deliver_issue_edit(journal)
245 Mailer.deliver_issue_edit(journal)
220 mail = ActionMailer::Base.deliveries.last
246 mail = last_email
221 assert_not_nil mail
222 assert_equal Mailer.message_id_for(journal), mail.message_id
247 assert_equal Mailer.message_id_for(journal), mail.message_id
223 assert_equal Mailer.message_id_for(journal.issue), mail.references.first.to_s
248 assert_equal Mailer.message_id_for(journal.issue), mail.references.first.to_s
224 assert_select_email do
249 assert_select_email do
225 # link to the update
250 # link to the update
226 assert_select "a[href=?]",
251 assert_select "a[href=?]",
227 "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
252 "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
228 end
253 end
229 end
254 end
230
255
231 def test_message_posted_message_id
256 def test_message_posted_message_id
232 message = Message.find(1)
257 message = Message.find(1)
233 Mailer.deliver_message_posted(message)
258 Mailer.deliver_message_posted(message)
234 mail = ActionMailer::Base.deliveries.last
259 mail = last_email
235 assert_not_nil mail
236 assert_equal Mailer.message_id_for(message), mail.message_id
260 assert_equal Mailer.message_id_for(message), mail.message_id
237 assert_nil mail.references
261 assert_nil mail.references
238 assert_select_email do
262 assert_select_email do
239 # link to the message
263 # link to the message
240 assert_select "a[href=?]",
264 assert_select "a[href=?]",
241 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
265 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
242 :text => message.subject
266 :text => message.subject
243 end
267 end
244 end
268 end
245
269
246 def test_reply_posted_message_id
270 def test_reply_posted_message_id
247 message = Message.find(3)
271 message = Message.find(3)
248 Mailer.deliver_message_posted(message)
272 Mailer.deliver_message_posted(message)
249 mail = ActionMailer::Base.deliveries.last
273 mail = last_email
250 assert_not_nil mail
251 assert_equal Mailer.message_id_for(message), mail.message_id
274 assert_equal Mailer.message_id_for(message), mail.message_id
252 assert_equal Mailer.message_id_for(message.parent), mail.references.first.to_s
275 assert_equal Mailer.message_id_for(message.parent), mail.references.first.to_s
253 assert_select_email do
276 assert_select_email do
254 # link to the reply
277 # link to the reply
255 assert_select "a[href=?]",
278 assert_select "a[href=?]",
256 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
279 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
257 :text => message.subject
280 :text => message.subject
258 end
281 end
259 end
282 end
260
283
261 context("#issue_add") do
284 context("#issue_add") do
262 setup do
285 setup do
263 ActionMailer::Base.deliveries.clear
286 ActionMailer::Base.deliveries.clear
264 Setting.bcc_recipients = '1'
287 Setting.bcc_recipients = '1'
265 @issue = Issue.find(1)
288 @issue = Issue.find(1)
266 end
289 end
267
290
268 should "notify project members" do
291 should "notify project members" do
269 assert Mailer.deliver_issue_add(@issue)
292 assert Mailer.deliver_issue_add(@issue)
270 assert last_email.bcc.include?('dlopper@somenet.foo')
293 assert last_email.bcc.include?('dlopper@somenet.foo')
271 end
294 end
272
295
273 should "not notify project members that are not allow to view the issue" do
296 should "not notify project members that are not allow to view the issue" do
274 Role.find(2).remove_permission!(:view_issues)
297 Role.find(2).remove_permission!(:view_issues)
275 assert Mailer.deliver_issue_add(@issue)
298 assert Mailer.deliver_issue_add(@issue)
276 assert !last_email.bcc.include?('dlopper@somenet.foo')
299 assert !last_email.bcc.include?('dlopper@somenet.foo')
277 end
300 end
278
301
279 should "notify issue watchers" do
302 should "notify issue watchers" do
280 user = User.find(9)
303 user = User.find(9)
281 # minimal email notification options
304 # minimal email notification options
282 user.pref[:no_self_notified] = '1'
305 user.pref[:no_self_notified] = '1'
283 user.pref.save
306 user.pref.save
284 user.mail_notification = false
307 user.mail_notification = false
285 user.save
308 user.save
286
309
287 Watcher.create!(:watchable => @issue, :user => user)
310 Watcher.create!(:watchable => @issue, :user => user)
288 assert Mailer.deliver_issue_add(@issue)
311 assert Mailer.deliver_issue_add(@issue)
289 assert last_email.bcc.include?(user.mail)
312 assert last_email.bcc.include?(user.mail)
290 end
313 end
291
314
292 should "not notify watchers not allowed to view the issue" do
315 should "not notify watchers not allowed to view the issue" do
293 user = User.find(9)
316 user = User.find(9)
294 Watcher.create!(:watchable => @issue, :user => user)
317 Watcher.create!(:watchable => @issue, :user => user)
295 Role.non_member.remove_permission!(:view_issues)
318 Role.non_member.remove_permission!(:view_issues)
296 assert Mailer.deliver_issue_add(@issue)
319 assert Mailer.deliver_issue_add(@issue)
297 assert !last_email.bcc.include?(user.mail)
320 assert !last_email.bcc.include?(user.mail)
298 end
321 end
299 end
322 end
300
323
301 # test mailer methods for each language
324 # test mailer methods for each language
302 def test_issue_add
325 def test_issue_add
303 issue = Issue.find(1)
326 issue = Issue.find(1)
304 valid_languages.each do |lang|
327 valid_languages.each do |lang|
305 Setting.default_language = lang.to_s
328 Setting.default_language = lang.to_s
306 assert Mailer.deliver_issue_add(issue)
329 assert Mailer.deliver_issue_add(issue)
307 end
330 end
308 end
331 end
309
332
310 def test_issue_edit
333 def test_issue_edit
311 journal = Journal.find(1)
334 journal = Journal.find(1)
312 valid_languages.each do |lang|
335 valid_languages.each do |lang|
313 Setting.default_language = lang.to_s
336 Setting.default_language = lang.to_s
314 assert Mailer.deliver_issue_edit(journal)
337 assert Mailer.deliver_issue_edit(journal)
315 end
338 end
316 end
339 end
317
340
318 def test_document_added
341 def test_document_added
319 document = Document.find(1)
342 document = Document.find(1)
320 valid_languages.each do |lang|
343 valid_languages.each do |lang|
321 Setting.default_language = lang.to_s
344 Setting.default_language = lang.to_s
322 assert Mailer.deliver_document_added(document)
345 assert Mailer.deliver_document_added(document)
323 end
346 end
324 end
347 end
325
348
326 def test_attachments_added
349 def test_attachments_added
327 attachements = [ Attachment.find_by_container_type('Document') ]
350 attachements = [ Attachment.find_by_container_type('Document') ]
328 valid_languages.each do |lang|
351 valid_languages.each do |lang|
329 Setting.default_language = lang.to_s
352 Setting.default_language = lang.to_s
330 assert Mailer.deliver_attachments_added(attachements)
353 assert Mailer.deliver_attachments_added(attachements)
331 end
354 end
332 end
355 end
333
356
334 def test_version_file_added
357 def test_version_file_added
335 attachements = [ Attachment.find_by_container_type('Version') ]
358 attachements = [ Attachment.find_by_container_type('Version') ]
336 assert Mailer.deliver_attachments_added(attachements)
359 assert Mailer.deliver_attachments_added(attachements)
337 assert_not_nil last_email.bcc
360 assert_not_nil last_email.bcc
338 assert last_email.bcc.any?
361 assert last_email.bcc.any?
339 assert_select_email do
362 assert_select_email do
340 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
363 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
341 end
364 end
342 end
365 end
343
366
344 def test_project_file_added
367 def test_project_file_added
345 attachements = [ Attachment.find_by_container_type('Project') ]
368 attachements = [ Attachment.find_by_container_type('Project') ]
346 assert Mailer.deliver_attachments_added(attachements)
369 assert Mailer.deliver_attachments_added(attachements)
347 assert_not_nil last_email.bcc
370 assert_not_nil last_email.bcc
348 assert last_email.bcc.any?
371 assert last_email.bcc.any?
349 assert_select_email do
372 assert_select_email do
350 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
373 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
351 end
374 end
352 end
375 end
353
376
354 def test_news_added
377 def test_news_added
355 news = News.find(:first)
378 news = News.find(:first)
356 valid_languages.each do |lang|
379 valid_languages.each do |lang|
357 Setting.default_language = lang.to_s
380 Setting.default_language = lang.to_s
358 assert Mailer.deliver_news_added(news)
381 assert Mailer.deliver_news_added(news)
359 end
382 end
360 end
383 end
361
384
362 def test_news_comment_added
385 def test_news_comment_added
363 comment = Comment.find(2)
386 comment = Comment.find(2)
364 valid_languages.each do |lang|
387 valid_languages.each do |lang|
365 Setting.default_language = lang.to_s
388 Setting.default_language = lang.to_s
366 assert Mailer.deliver_news_comment_added(comment)
389 assert Mailer.deliver_news_comment_added(comment)
367 end
390 end
368 end
391 end
369
392
370 def test_message_posted
393 def test_message_posted
371 message = Message.find(:first)
394 message = Message.find(:first)
372 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
395 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
373 recipients = recipients.compact.uniq
396 recipients = recipients.compact.uniq
374 valid_languages.each do |lang|
397 valid_languages.each do |lang|
375 Setting.default_language = lang.to_s
398 Setting.default_language = lang.to_s
376 assert Mailer.deliver_message_posted(message)
399 assert Mailer.deliver_message_posted(message)
377 end
400 end
378 end
401 end
379
402
380 def test_wiki_content_added
403 def test_wiki_content_added
381 content = WikiContent.find(:first)
404 content = WikiContent.find(:first)
382 valid_languages.each do |lang|
405 valid_languages.each do |lang|
383 Setting.default_language = lang.to_s
406 Setting.default_language = lang.to_s
384 assert_difference 'ActionMailer::Base.deliveries.size' do
407 assert_difference 'ActionMailer::Base.deliveries.size' do
385 assert Mailer.deliver_wiki_content_added(content)
408 assert Mailer.deliver_wiki_content_added(content)
386 end
409 end
387 end
410 end
388 end
411 end
389
412
390 def test_wiki_content_updated
413 def test_wiki_content_updated
391 content = WikiContent.find(:first)
414 content = WikiContent.find(:first)
392 valid_languages.each do |lang|
415 valid_languages.each do |lang|
393 Setting.default_language = lang.to_s
416 Setting.default_language = lang.to_s
394 assert_difference 'ActionMailer::Base.deliveries.size' do
417 assert_difference 'ActionMailer::Base.deliveries.size' do
395 assert Mailer.deliver_wiki_content_updated(content)
418 assert Mailer.deliver_wiki_content_updated(content)
396 end
419 end
397 end
420 end
398 end
421 end
399
422
400 def test_account_information
423 def test_account_information
401 user = User.find(2)
424 user = User.find(2)
402 valid_languages.each do |lang|
425 valid_languages.each do |lang|
403 user.update_attribute :language, lang.to_s
426 user.update_attribute :language, lang.to_s
404 user.reload
427 user.reload
405 assert Mailer.deliver_account_information(user, 'pAsswORd')
428 assert Mailer.deliver_account_information(user, 'pAsswORd')
406 end
429 end
407 end
430 end
408
431
409 def test_lost_password
432 def test_lost_password
410 token = Token.find(2)
433 token = Token.find(2)
411 valid_languages.each do |lang|
434 valid_languages.each do |lang|
412 token.user.update_attribute :language, lang.to_s
435 token.user.update_attribute :language, lang.to_s
413 token.reload
436 token.reload
414 assert Mailer.deliver_lost_password(token)
437 assert Mailer.deliver_lost_password(token)
415 end
438 end
416 end
439 end
417
440
418 def test_register
441 def test_register
419 token = Token.find(1)
442 token = Token.find(1)
420 Setting.host_name = 'redmine.foo'
443 Setting.host_name = 'redmine.foo'
421 Setting.protocol = 'https'
444 Setting.protocol = 'https'
422
445
423 valid_languages.each do |lang|
446 valid_languages.each do |lang|
424 token.user.update_attribute :language, lang.to_s
447 token.user.update_attribute :language, lang.to_s
425 token.reload
448 token.reload
426 ActionMailer::Base.deliveries.clear
449 ActionMailer::Base.deliveries.clear
427 assert Mailer.deliver_register(token)
450 assert Mailer.deliver_register(token)
428 mail = ActionMailer::Base.deliveries.last
451 mail = last_email
429 assert_select_email do
452 assert_select_email do
430 assert_select "a[href=?]",
453 assert_select "a[href=?]",
431 "https://redmine.foo/account/activate?token=#{token.value}",
454 "https://redmine.foo/account/activate?token=#{token.value}",
432 :text => "https://redmine.foo/account/activate?token=#{token.value}"
455 :text => "https://redmine.foo/account/activate?token=#{token.value}"
433 end
456 end
434 end
457 end
435 end
458 end
436
459
437 def test_test
460 def test_test
438 user = User.find(1)
461 user = User.find(1)
439 valid_languages.each do |lang|
462 valid_languages.each do |lang|
440 user.update_attribute :language, lang.to_s
463 user.update_attribute :language, lang.to_s
441 assert Mailer.deliver_test(user)
464 assert Mailer.deliver_test(user)
442 end
465 end
443 end
466 end
444
467
445 def test_reminders
468 def test_reminders
446 Mailer.reminders(:days => 42)
469 Mailer.reminders(:days => 42)
447 assert_equal 1, ActionMailer::Base.deliveries.size
470 assert_equal 1, ActionMailer::Base.deliveries.size
448 mail = ActionMailer::Base.deliveries.last
471 mail = last_email
449 assert mail.bcc.include?('dlopper@somenet.foo')
472 assert mail.bcc.include?('dlopper@somenet.foo')
450 assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
473 assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
451 assert_equal '1 issue(s) due in the next 42 days', mail.subject
474 assert_equal '1 issue(s) due in the next 42 days', mail.subject
452 end
475 end
453
476
454 def test_reminders_should_not_include_closed_issues
477 def test_reminders_should_not_include_closed_issues
455 with_settings :default_language => 'en' do
478 with_settings :default_language => 'en' do
456 Issue.generate!(:project_id => 1, :tracker_id => 1, :status_id => 5,
479 Issue.generate!(:project_id => 1, :tracker_id => 1, :status_id => 5,
457 :subject => 'Closed issue', :assigned_to_id => 3,
480 :subject => 'Closed issue', :assigned_to_id => 3,
458 :due_date => 5.days.from_now)
481 :due_date => 5.days.from_now)
459 ActionMailer::Base.deliveries.clear
482 ActionMailer::Base.deliveries.clear
460
483
461 Mailer.reminders(:days => 42)
484 Mailer.reminders(:days => 42)
462 assert_equal 1, ActionMailer::Base.deliveries.size
485 assert_equal 1, ActionMailer::Base.deliveries.size
463 mail = ActionMailer::Base.deliveries.last
486 mail = last_email
464 assert mail.bcc.include?('dlopper@somenet.foo')
487 assert mail.bcc.include?('dlopper@somenet.foo')
465 assert !mail.body.include?('Closed issue')
488 assert !mail.body.include?('Closed issue')
466 end
489 end
467 end
490 end
468
491
469 def test_reminders_for_users
492 def test_reminders_for_users
470 Mailer.reminders(:days => 42, :users => ['5'])
493 Mailer.reminders(:days => 42, :users => ['5'])
471 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
494 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
472 Mailer.reminders(:days => 42, :users => ['3'])
495 Mailer.reminders(:days => 42, :users => ['3'])
473 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
496 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
474 mail = ActionMailer::Base.deliveries.last
497 mail = last_email
475 assert mail.bcc.include?('dlopper@somenet.foo')
498 assert mail.bcc.include?('dlopper@somenet.foo')
476 assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
499 assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
477 end
500 end
478
501
479 def last_email
502 def last_email
480 mail = ActionMailer::Base.deliveries.last
503 mail = ActionMailer::Base.deliveries.last
481 assert_not_nil mail
504 assert_not_nil mail
482 mail
505 mail
483 end
506 end
484
507
485 def test_mailer_should_not_change_locale
508 def test_mailer_should_not_change_locale
486 Setting.default_language = 'en'
509 Setting.default_language = 'en'
487 # Set current language to italian
510 # Set current language to italian
488 set_language_if_valid 'it'
511 set_language_if_valid 'it'
489 # Send an email to a french user
512 # Send an email to a french user
490 user = User.find(1)
513 user = User.find(1)
491 user.language = 'fr'
514 user.language = 'fr'
492 Mailer.deliver_account_activated(user)
515 Mailer.deliver_account_activated(user)
493 mail = ActionMailer::Base.deliveries.last
516 mail = last_email
494 assert mail.body.include?('Votre compte')
517 assert mail.body.include?('Votre compte')
495
518
496 assert_equal :it, current_language
519 assert_equal :it, current_language
497 end
520 end
498
521
499 def test_with_deliveries_off
522 def test_with_deliveries_off
500 Mailer.with_deliveries false do
523 Mailer.with_deliveries false do
501 Mailer.deliver_test(User.find(1))
524 Mailer.deliver_test(User.find(1))
502 end
525 end
503 assert ActionMailer::Base.deliveries.empty?
526 assert ActionMailer::Base.deliveries.empty?
504 # should restore perform_deliveries
527 # should restore perform_deliveries
505 assert ActionMailer::Base.perform_deliveries
528 assert ActionMailer::Base.perform_deliveries
506 end
529 end
507
530
508 def test_tmail_to_header_field_should_not_include_blank_lines
531 def test_tmail_to_header_field_should_not_include_blank_lines
509 mail = TMail::Mail.new
532 mail = TMail::Mail.new
510 mail.to = ["a.user@example.com", "v.user2@example.com", "e.smith@example.com", "info@example.com", "v.pupkin@example.com",
533 mail.to = ["a.user@example.com", "v.user2@example.com", "e.smith@example.com", "info@example.com", "v.pupkin@example.com",
511 "b.user@example.com", "w.user2@example.com", "f.smith@example.com", "info2@example.com", "w.pupkin@example.com"]
534 "b.user@example.com", "w.user2@example.com", "f.smith@example.com", "info2@example.com", "w.pupkin@example.com"]
512
535
513 assert !mail.encoded.strip.split("\r\n").detect(&:blank?), "#{mail.encoded} malformed"
536 assert !mail.encoded.strip.split("\r\n").detect(&:blank?), "#{mail.encoded} malformed"
514 end
537 end
515
538
516 def test_layout_should_include_the_emails_header
539 def test_layout_should_include_the_emails_header
517 with_settings :emails_header => "*Header content*" do
540 with_settings :emails_header => "*Header content*" do
518 assert Mailer.deliver_test(User.find(1))
541 assert Mailer.deliver_test(User.find(1))
519 assert_select_email do
542 assert_select_email do
520 assert_select ".header" do
543 assert_select ".header" do
521 assert_select "strong", :text => "Header content"
544 assert_select "strong", :text => "Header content"
522 end
545 end
523 end
546 end
524 end
547 end
525 end
548 end
526 end
549 end
General Comments 0
You need to be logged in to leave comments. Login now