##// END OF EJS Templates
Fixed: Links in Forum mails should redirect to message, not topic (#4884)....
Jean-Philippe Lang -
r3344:dab0c07fba56
parent child
Show More
@@ -1,428 +1,428
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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 # Builds a tmail object used to email recipients of the added issue.
33 # Builds a tmail object used to email recipients of the added issue.
34 #
34 #
35 # Example:
35 # Example:
36 # issue_add(issue) => tmail object
36 # issue_add(issue) => tmail object
37 # Mailer.deliver_issue_add(issue) => sends an email to issue recipients
37 # Mailer.deliver_issue_add(issue) => sends an email to issue recipients
38 def issue_add(issue)
38 def issue_add(issue)
39 redmine_headers 'Project' => issue.project.identifier,
39 redmine_headers 'Project' => issue.project.identifier,
40 'Issue-Id' => issue.id,
40 'Issue-Id' => issue.id,
41 'Issue-Author' => issue.author.login
41 'Issue-Author' => issue.author.login
42 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
42 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
43 message_id issue
43 message_id issue
44 recipients issue.recipients
44 recipients issue.recipients
45 cc(issue.watcher_recipients - @recipients)
45 cc(issue.watcher_recipients - @recipients)
46 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
46 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
47 body :issue => issue,
47 body :issue => issue,
48 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
48 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
49 render_multipart('issue_add', body)
49 render_multipart('issue_add', body)
50 end
50 end
51
51
52 # Builds a tmail object used to email recipients of the edited issue.
52 # Builds a tmail object used to email recipients of the edited issue.
53 #
53 #
54 # Example:
54 # Example:
55 # issue_edit(journal) => tmail object
55 # issue_edit(journal) => tmail object
56 # Mailer.deliver_issue_edit(journal) => sends an email to issue recipients
56 # Mailer.deliver_issue_edit(journal) => sends an email to issue recipients
57 def issue_edit(journal)
57 def issue_edit(journal)
58 issue = journal.journalized.reload
58 issue = journal.journalized.reload
59 redmine_headers 'Project' => issue.project.identifier,
59 redmine_headers 'Project' => issue.project.identifier,
60 'Issue-Id' => issue.id,
60 'Issue-Id' => issue.id,
61 'Issue-Author' => issue.author.login
61 'Issue-Author' => issue.author.login
62 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
62 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
63 message_id journal
63 message_id journal
64 references issue
64 references issue
65 @author = journal.user
65 @author = journal.user
66 recipients issue.recipients
66 recipients issue.recipients
67 # Watchers in cc
67 # Watchers in cc
68 cc(issue.watcher_recipients - @recipients)
68 cc(issue.watcher_recipients - @recipients)
69 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
69 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
70 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
70 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
71 s << issue.subject
71 s << issue.subject
72 subject s
72 subject s
73 body :issue => issue,
73 body :issue => issue,
74 :journal => journal,
74 :journal => journal,
75 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
75 :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
76
76
77 render_multipart('issue_edit', body)
77 render_multipart('issue_edit', body)
78 end
78 end
79
79
80 def reminder(user, issues, days)
80 def reminder(user, issues, days)
81 set_language_if_valid user.language
81 set_language_if_valid user.language
82 recipients user.mail
82 recipients user.mail
83 subject l(:mail_subject_reminder, issues.size)
83 subject l(:mail_subject_reminder, issues.size)
84 body :issues => issues,
84 body :issues => issues,
85 :days => days,
85 :days => days,
86 :issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc')
86 :issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc')
87 render_multipart('reminder', body)
87 render_multipart('reminder', body)
88 end
88 end
89
89
90 # Builds a tmail object used to email users belonging to the added document's project.
90 # Builds a tmail object used to email users belonging to the added document's project.
91 #
91 #
92 # Example:
92 # Example:
93 # document_added(document) => tmail object
93 # document_added(document) => tmail object
94 # Mailer.deliver_document_added(document) => sends an email to the document's project recipients
94 # Mailer.deliver_document_added(document) => sends an email to the document's project recipients
95 def document_added(document)
95 def document_added(document)
96 redmine_headers 'Project' => document.project.identifier
96 redmine_headers 'Project' => document.project.identifier
97 recipients document.recipients
97 recipients document.recipients
98 subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
98 subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
99 body :document => document,
99 body :document => document,
100 :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
100 :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
101 render_multipart('document_added', body)
101 render_multipart('document_added', body)
102 end
102 end
103
103
104 # Builds a tmail object used to email recipients of a project when an attachements are added.
104 # Builds a tmail object used to email recipients of a project when an attachements are added.
105 #
105 #
106 # Example:
106 # Example:
107 # attachments_added(attachments) => tmail object
107 # attachments_added(attachments) => tmail object
108 # Mailer.deliver_attachments_added(attachments) => sends an email to the project's recipients
108 # Mailer.deliver_attachments_added(attachments) => sends an email to the project's recipients
109 def attachments_added(attachments)
109 def attachments_added(attachments)
110 container = attachments.first.container
110 container = attachments.first.container
111 added_to = ''
111 added_to = ''
112 added_to_url = ''
112 added_to_url = ''
113 case container.class.name
113 case container.class.name
114 when 'Project'
114 when 'Project'
115 added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container)
115 added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container)
116 added_to = "#{l(:label_project)}: #{container}"
116 added_to = "#{l(:label_project)}: #{container}"
117 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
117 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
118 when 'Version'
118 when 'Version'
119 added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
119 added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
120 added_to = "#{l(:label_version)}: #{container.name}"
120 added_to = "#{l(:label_version)}: #{container.name}"
121 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
121 recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}
122 when 'Document'
122 when 'Document'
123 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
123 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
124 added_to = "#{l(:label_document)}: #{container.title}"
124 added_to = "#{l(:label_document)}: #{container.title}"
125 recipients container.recipients
125 recipients container.recipients
126 end
126 end
127 redmine_headers 'Project' => container.project.identifier
127 redmine_headers 'Project' => container.project.identifier
128 subject "[#{container.project.name}] #{l(:label_attachment_new)}"
128 subject "[#{container.project.name}] #{l(:label_attachment_new)}"
129 body :attachments => attachments,
129 body :attachments => attachments,
130 :added_to => added_to,
130 :added_to => added_to,
131 :added_to_url => added_to_url
131 :added_to_url => added_to_url
132 render_multipart('attachments_added', body)
132 render_multipart('attachments_added', body)
133 end
133 end
134
134
135 # Builds a tmail object used to email recipients of a news' project when a news item is added.
135 # Builds a tmail object used to email recipients of a news' project when a news item is added.
136 #
136 #
137 # Example:
137 # Example:
138 # news_added(news) => tmail object
138 # news_added(news) => tmail object
139 # Mailer.deliver_news_added(news) => sends an email to the news' project recipients
139 # Mailer.deliver_news_added(news) => sends an email to the news' project recipients
140 def news_added(news)
140 def news_added(news)
141 redmine_headers 'Project' => news.project.identifier
141 redmine_headers 'Project' => news.project.identifier
142 message_id news
142 message_id news
143 recipients news.recipients
143 recipients news.recipients
144 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
144 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
145 body :news => news,
145 body :news => news,
146 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
146 :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
147 render_multipart('news_added', body)
147 render_multipart('news_added', body)
148 end
148 end
149
149
150 # Builds a tmail object used to email the recipients of the specified message that was posted.
150 # Builds a tmail object used to email the recipients of the specified message that was posted.
151 #
151 #
152 # Example:
152 # Example:
153 # message_posted(message) => tmail object
153 # message_posted(message) => tmail object
154 # Mailer.deliver_message_posted(message) => sends an email to the recipients
154 # Mailer.deliver_message_posted(message) => sends an email to the recipients
155 def message_posted(message)
155 def message_posted(message)
156 redmine_headers 'Project' => message.project.identifier,
156 redmine_headers 'Project' => message.project.identifier,
157 'Topic-Id' => (message.parent_id || message.id)
157 'Topic-Id' => (message.parent_id || message.id)
158 message_id message
158 message_id message
159 references message.parent unless message.parent.nil?
159 references message.parent unless message.parent.nil?
160 recipients(message.recipients)
160 recipients(message.recipients)
161 cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
161 cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
162 subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
162 subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
163 body :message => message,
163 body :message => message,
164 :message_url => url_for(:controller => 'messages', :action => 'show', :board_id => message.board_id, :id => message.root)
164 :message_url => url_for(message.event_url)
165 render_multipart('message_posted', body)
165 render_multipart('message_posted', body)
166 end
166 end
167
167
168 # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
168 # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
169 #
169 #
170 # Example:
170 # Example:
171 # wiki_content_added(wiki_content) => tmail object
171 # wiki_content_added(wiki_content) => tmail object
172 # Mailer.deliver_wiki_content_added(wiki_content) => sends an email to the project's recipients
172 # Mailer.deliver_wiki_content_added(wiki_content) => sends an email to the project's recipients
173 def wiki_content_added(wiki_content)
173 def wiki_content_added(wiki_content)
174 redmine_headers 'Project' => wiki_content.project.identifier,
174 redmine_headers 'Project' => wiki_content.project.identifier,
175 'Wiki-Page-Id' => wiki_content.page.id
175 'Wiki-Page-Id' => wiki_content.page.id
176 message_id wiki_content
176 message_id wiki_content
177 recipients wiki_content.recipients
177 recipients wiki_content.recipients
178 cc(wiki_content.page.wiki.watcher_recipients - recipients)
178 cc(wiki_content.page.wiki.watcher_recipients - recipients)
179 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :page => wiki_content.page.pretty_title)}"
179 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :page => wiki_content.page.pretty_title)}"
180 body :wiki_content => wiki_content,
180 body :wiki_content => wiki_content,
181 :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title)
181 :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title)
182 render_multipart('wiki_content_added', body)
182 render_multipart('wiki_content_added', body)
183 end
183 end
184
184
185 # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
185 # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
186 #
186 #
187 # Example:
187 # Example:
188 # wiki_content_updated(wiki_content) => tmail object
188 # wiki_content_updated(wiki_content) => tmail object
189 # Mailer.deliver_wiki_content_updated(wiki_content) => sends an email to the project's recipients
189 # Mailer.deliver_wiki_content_updated(wiki_content) => sends an email to the project's recipients
190 def wiki_content_updated(wiki_content)
190 def wiki_content_updated(wiki_content)
191 redmine_headers 'Project' => wiki_content.project.identifier,
191 redmine_headers 'Project' => wiki_content.project.identifier,
192 'Wiki-Page-Id' => wiki_content.page.id
192 'Wiki-Page-Id' => wiki_content.page.id
193 message_id wiki_content
193 message_id wiki_content
194 recipients wiki_content.recipients
194 recipients wiki_content.recipients
195 cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients)
195 cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients)
196 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :page => wiki_content.page.pretty_title)}"
196 subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :page => wiki_content.page.pretty_title)}"
197 body :wiki_content => wiki_content,
197 body :wiki_content => wiki_content,
198 :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title),
198 :wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title),
199 :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :id => wiki_content.project, :page => wiki_content.page.title, :version => wiki_content.version)
199 :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :id => wiki_content.project, :page => wiki_content.page.title, :version => wiki_content.version)
200 render_multipart('wiki_content_updated', body)
200 render_multipart('wiki_content_updated', body)
201 end
201 end
202
202
203 # Builds a tmail object used to email the specified user their account information.
203 # Builds a tmail object used to email the specified user their account information.
204 #
204 #
205 # Example:
205 # Example:
206 # account_information(user, password) => tmail object
206 # account_information(user, password) => tmail object
207 # Mailer.deliver_account_information(user, password) => sends account information to the user
207 # Mailer.deliver_account_information(user, password) => sends account information to the user
208 def account_information(user, password)
208 def account_information(user, password)
209 set_language_if_valid user.language
209 set_language_if_valid user.language
210 recipients user.mail
210 recipients user.mail
211 subject l(:mail_subject_register, Setting.app_title)
211 subject l(:mail_subject_register, Setting.app_title)
212 body :user => user,
212 body :user => user,
213 :password => password,
213 :password => password,
214 :login_url => url_for(:controller => 'account', :action => 'login')
214 :login_url => url_for(:controller => 'account', :action => 'login')
215 render_multipart('account_information', body)
215 render_multipart('account_information', body)
216 end
216 end
217
217
218 # Builds a tmail object used to email all active administrators of an account activation request.
218 # Builds a tmail object used to email all active administrators of an account activation request.
219 #
219 #
220 # Example:
220 # Example:
221 # account_activation_request(user) => tmail object
221 # account_activation_request(user) => tmail object
222 # Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators
222 # Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators
223 def account_activation_request(user)
223 def account_activation_request(user)
224 # Send the email to all active administrators
224 # Send the email to all active administrators
225 recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
225 recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
226 subject l(:mail_subject_account_activation_request, Setting.app_title)
226 subject l(:mail_subject_account_activation_request, Setting.app_title)
227 body :user => user,
227 body :user => user,
228 :url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
228 :url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
229 render_multipart('account_activation_request', body)
229 render_multipart('account_activation_request', body)
230 end
230 end
231
231
232 # Builds a tmail object used to email the specified user that their account was activated by an administrator.
232 # Builds a tmail object used to email the specified user that their account was activated by an administrator.
233 #
233 #
234 # Example:
234 # Example:
235 # account_activated(user) => tmail object
235 # account_activated(user) => tmail object
236 # Mailer.deliver_account_activated(user) => sends an email to the registered user
236 # Mailer.deliver_account_activated(user) => sends an email to the registered user
237 def account_activated(user)
237 def account_activated(user)
238 set_language_if_valid user.language
238 set_language_if_valid user.language
239 recipients user.mail
239 recipients user.mail
240 subject l(:mail_subject_register, Setting.app_title)
240 subject l(:mail_subject_register, Setting.app_title)
241 body :user => user,
241 body :user => user,
242 :login_url => url_for(:controller => 'account', :action => 'login')
242 :login_url => url_for(:controller => 'account', :action => 'login')
243 render_multipart('account_activated', body)
243 render_multipart('account_activated', body)
244 end
244 end
245
245
246 def lost_password(token)
246 def lost_password(token)
247 set_language_if_valid(token.user.language)
247 set_language_if_valid(token.user.language)
248 recipients token.user.mail
248 recipients token.user.mail
249 subject l(:mail_subject_lost_password, Setting.app_title)
249 subject l(:mail_subject_lost_password, Setting.app_title)
250 body :token => token,
250 body :token => token,
251 :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
251 :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
252 render_multipart('lost_password', body)
252 render_multipart('lost_password', body)
253 end
253 end
254
254
255 def register(token)
255 def register(token)
256 set_language_if_valid(token.user.language)
256 set_language_if_valid(token.user.language)
257 recipients token.user.mail
257 recipients token.user.mail
258 subject l(:mail_subject_register, Setting.app_title)
258 subject l(:mail_subject_register, Setting.app_title)
259 body :token => token,
259 body :token => token,
260 :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
260 :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
261 render_multipart('register', body)
261 render_multipart('register', body)
262 end
262 end
263
263
264 def test(user)
264 def test(user)
265 set_language_if_valid(user.language)
265 set_language_if_valid(user.language)
266 recipients user.mail
266 recipients user.mail
267 subject 'Redmine test'
267 subject 'Redmine test'
268 body :url => url_for(:controller => 'welcome')
268 body :url => url_for(:controller => 'welcome')
269 render_multipart('test', body)
269 render_multipart('test', body)
270 end
270 end
271
271
272 # Overrides default deliver! method to prevent from sending an email
272 # Overrides default deliver! method to prevent from sending an email
273 # with no recipient, cc or bcc
273 # with no recipient, cc or bcc
274 def deliver!(mail = @mail)
274 def deliver!(mail = @mail)
275 set_language_if_valid @initial_language
275 set_language_if_valid @initial_language
276 return false if (recipients.nil? || recipients.empty?) &&
276 return false if (recipients.nil? || recipients.empty?) &&
277 (cc.nil? || cc.empty?) &&
277 (cc.nil? || cc.empty?) &&
278 (bcc.nil? || bcc.empty?)
278 (bcc.nil? || bcc.empty?)
279
279
280 # Set Message-Id and References
280 # Set Message-Id and References
281 if @message_id_object
281 if @message_id_object
282 mail.message_id = self.class.message_id_for(@message_id_object)
282 mail.message_id = self.class.message_id_for(@message_id_object)
283 end
283 end
284 if @references_objects
284 if @references_objects
285 mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
285 mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
286 end
286 end
287
287
288 # Log errors when raise_delivery_errors is set to false, Rails does not
288 # Log errors when raise_delivery_errors is set to false, Rails does not
289 raise_errors = self.class.raise_delivery_errors
289 raise_errors = self.class.raise_delivery_errors
290 self.class.raise_delivery_errors = true
290 self.class.raise_delivery_errors = true
291 begin
291 begin
292 return super(mail)
292 return super(mail)
293 rescue Exception => e
293 rescue Exception => e
294 if raise_errors
294 if raise_errors
295 raise e
295 raise e
296 elsif mylogger
296 elsif mylogger
297 mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/email.yml."
297 mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/email.yml."
298 end
298 end
299 ensure
299 ensure
300 self.class.raise_delivery_errors = raise_errors
300 self.class.raise_delivery_errors = raise_errors
301 end
301 end
302 end
302 end
303
303
304 # Sends reminders to issue assignees
304 # Sends reminders to issue assignees
305 # Available options:
305 # Available options:
306 # * :days => how many days in the future to remind about (defaults to 7)
306 # * :days => how many days in the future to remind about (defaults to 7)
307 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
307 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
308 # * :project => id or identifier of project to process (defaults to all projects)
308 # * :project => id or identifier of project to process (defaults to all projects)
309 def self.reminders(options={})
309 def self.reminders(options={})
310 days = options[:days] || 7
310 days = options[:days] || 7
311 project = options[:project] ? Project.find(options[:project]) : nil
311 project = options[:project] ? Project.find(options[:project]) : nil
312 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
312 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
313
313
314 s = ARCondition.new ["#{IssueStatus.table_name}.is_closed = ? AND #{Issue.table_name}.due_date <= ?", false, days.day.from_now.to_date]
314 s = ARCondition.new ["#{IssueStatus.table_name}.is_closed = ? AND #{Issue.table_name}.due_date <= ?", false, days.day.from_now.to_date]
315 s << "#{Issue.table_name}.assigned_to_id IS NOT NULL"
315 s << "#{Issue.table_name}.assigned_to_id IS NOT NULL"
316 s << "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}"
316 s << "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}"
317 s << "#{Issue.table_name}.project_id = #{project.id}" if project
317 s << "#{Issue.table_name}.project_id = #{project.id}" if project
318 s << "#{Issue.table_name}.tracker_id = #{tracker.id}" if tracker
318 s << "#{Issue.table_name}.tracker_id = #{tracker.id}" if tracker
319
319
320 issues_by_assignee = Issue.find(:all, :include => [:status, :assigned_to, :project, :tracker],
320 issues_by_assignee = Issue.find(:all, :include => [:status, :assigned_to, :project, :tracker],
321 :conditions => s.conditions
321 :conditions => s.conditions
322 ).group_by(&:assigned_to)
322 ).group_by(&:assigned_to)
323 issues_by_assignee.each do |assignee, issues|
323 issues_by_assignee.each do |assignee, issues|
324 deliver_reminder(assignee, issues, days) unless assignee.nil?
324 deliver_reminder(assignee, issues, days) unless assignee.nil?
325 end
325 end
326 end
326 end
327
327
328 private
328 private
329 def initialize_defaults(method_name)
329 def initialize_defaults(method_name)
330 super
330 super
331 @initial_language = current_language
331 @initial_language = current_language
332 set_language_if_valid Setting.default_language
332 set_language_if_valid Setting.default_language
333 from Setting.mail_from
333 from Setting.mail_from
334
334
335 # Common headers
335 # Common headers
336 headers 'X-Mailer' => 'Redmine',
336 headers 'X-Mailer' => 'Redmine',
337 'X-Redmine-Host' => Setting.host_name,
337 'X-Redmine-Host' => Setting.host_name,
338 'X-Redmine-Site' => Setting.app_title,
338 'X-Redmine-Site' => Setting.app_title,
339 'Precedence' => 'bulk',
339 'Precedence' => 'bulk',
340 'Auto-Submitted' => 'auto-generated'
340 'Auto-Submitted' => 'auto-generated'
341 end
341 end
342
342
343 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
343 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
344 def redmine_headers(h)
344 def redmine_headers(h)
345 h.each { |k,v| headers["X-Redmine-#{k}"] = v }
345 h.each { |k,v| headers["X-Redmine-#{k}"] = v }
346 end
346 end
347
347
348 # Overrides the create_mail method
348 # Overrides the create_mail method
349 def create_mail
349 def create_mail
350 # Removes the current user from the recipients and cc
350 # Removes the current user from the recipients and cc
351 # if he doesn't want to receive notifications about what he does
351 # if he doesn't want to receive notifications about what he does
352 @author ||= User.current
352 @author ||= User.current
353 if @author.pref[:no_self_notified]
353 if @author.pref[:no_self_notified]
354 recipients.delete(@author.mail) if recipients
354 recipients.delete(@author.mail) if recipients
355 cc.delete(@author.mail) if cc
355 cc.delete(@author.mail) if cc
356 end
356 end
357
357
358 notified_users = [recipients, cc].flatten.compact.uniq
358 notified_users = [recipients, cc].flatten.compact.uniq
359 # Rails would log recipients only, not cc and bcc
359 # Rails would log recipients only, not cc and bcc
360 mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
360 mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
361
361
362 # Blind carbon copy recipients
362 # Blind carbon copy recipients
363 if Setting.bcc_recipients?
363 if Setting.bcc_recipients?
364 bcc(notified_users)
364 bcc(notified_users)
365 recipients []
365 recipients []
366 cc []
366 cc []
367 end
367 end
368 super
368 super
369 end
369 end
370
370
371 # Rails 2.3 has problems rendering implicit multipart messages with
371 # Rails 2.3 has problems rendering implicit multipart messages with
372 # layouts so this method will wrap an multipart messages with
372 # layouts so this method will wrap an multipart messages with
373 # explicit parts.
373 # explicit parts.
374 #
374 #
375 # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
375 # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
376 # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
376 # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
377
377
378 def render_multipart(method_name, body)
378 def render_multipart(method_name, body)
379 if Setting.plain_text_mail?
379 if Setting.plain_text_mail?
380 content_type "text/plain"
380 content_type "text/plain"
381 body render(:file => "#{method_name}.text.plain.rhtml", :body => body, :layout => 'mailer.text.plain.erb')
381 body render(:file => "#{method_name}.text.plain.rhtml", :body => body, :layout => 'mailer.text.plain.erb')
382 else
382 else
383 content_type "multipart/alternative"
383 content_type "multipart/alternative"
384 part :content_type => "text/plain", :body => render(:file => "#{method_name}.text.plain.rhtml", :body => body, :layout => 'mailer.text.plain.erb')
384 part :content_type => "text/plain", :body => render(:file => "#{method_name}.text.plain.rhtml", :body => body, :layout => 'mailer.text.plain.erb')
385 part :content_type => "text/html", :body => render_message("#{method_name}.text.html.rhtml", body)
385 part :content_type => "text/html", :body => render_message("#{method_name}.text.html.rhtml", body)
386 end
386 end
387 end
387 end
388
388
389 # Makes partial rendering work with Rails 1.2 (retro-compatibility)
389 # Makes partial rendering work with Rails 1.2 (retro-compatibility)
390 def self.controller_path
390 def self.controller_path
391 ''
391 ''
392 end unless respond_to?('controller_path')
392 end unless respond_to?('controller_path')
393
393
394 # Returns a predictable Message-Id for the given object
394 # Returns a predictable Message-Id for the given object
395 def self.message_id_for(object)
395 def self.message_id_for(object)
396 # id + timestamp should reduce the odds of a collision
396 # id + timestamp should reduce the odds of a collision
397 # as far as we don't send multiple emails for the same object
397 # as far as we don't send multiple emails for the same object
398 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
398 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
399 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
399 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
400 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
400 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
401 host = "#{::Socket.gethostname}.redmine" if host.empty?
401 host = "#{::Socket.gethostname}.redmine" if host.empty?
402 "<#{hash}@#{host}>"
402 "<#{hash}@#{host}>"
403 end
403 end
404
404
405 private
405 private
406
406
407 def message_id(object)
407 def message_id(object)
408 @message_id_object = object
408 @message_id_object = object
409 end
409 end
410
410
411 def references(object)
411 def references(object)
412 @references_objects ||= []
412 @references_objects ||= []
413 @references_objects << object
413 @references_objects << object
414 end
414 end
415
415
416 def mylogger
416 def mylogger
417 RAILS_DEFAULT_LOGGER
417 RAILS_DEFAULT_LOGGER
418 end
418 end
419 end
419 end
420
420
421 # Patch TMail so that message_id is not overwritten
421 # Patch TMail so that message_id is not overwritten
422 module TMail
422 module TMail
423 class Mail
423 class Mail
424 def add_message_id( fqdn = nil )
424 def add_message_id( fqdn = nil )
425 self.message_id ||= ::TMail::new_message_id(fqdn)
425 self.message_id ||= ::TMail::new_message_id(fqdn)
426 end
426 end
427 end
427 end
428 end
428 end
@@ -1,329 +1,341
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 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.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
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, :member_roles, :roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories
23 fixtures :projects, :enabled_modules, :issues, :users, :members, :member_roles, :roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories
24
24
25 def setup
26 ActionMailer::Base.deliveries.clear
27 Setting.host_name = 'mydomain.foo'
28 Setting.protocol = 'http'
29 end
30
25 def test_generated_links_in_emails
31 def test_generated_links_in_emails
26 ActionMailer::Base.deliveries.clear
32 ActionMailer::Base.deliveries.clear
27 Setting.host_name = 'mydomain.foo'
33 Setting.host_name = 'mydomain.foo'
28 Setting.protocol = 'https'
34 Setting.protocol = 'https'
29
35
30 journal = Journal.find(2)
36 journal = Journal.find(2)
31 assert Mailer.deliver_issue_edit(journal)
37 assert Mailer.deliver_issue_edit(journal)
32
38
33 mail = ActionMailer::Base.deliveries.last
39 mail = ActionMailer::Base.deliveries.last
34 assert_kind_of TMail::Mail, mail
40 assert_kind_of TMail::Mail, mail
35
41
36 assert_select_email do
42 assert_select_email do
37 # link to the main ticket
43 # link to the main ticket
38 assert_select "a[href=?]", "https://mydomain.foo/issues/1", :text => "Bug #1: Can't print recipes"
44 assert_select "a[href=?]", "https://mydomain.foo/issues/1", :text => "Bug #1: Can't print recipes"
39 # link to a referenced ticket
45 # link to a referenced ticket
40 assert_select "a[href=?][title=?]", "https://mydomain.foo/issues/2", "Add ingredients categories (Assigned)", :text => "#2"
46 assert_select "a[href=?][title=?]", "https://mydomain.foo/issues/2", "Add ingredients categories (Assigned)", :text => "#2"
41 # link to a changeset
47 # link to a changeset
42 assert_select "a[href=?][title=?]", "https://mydomain.foo/projects/ecookbook/repository/revisions/2", "This commit fixes #1, #2 and references #1 &amp; #3", :text => "r2"
48 assert_select "a[href=?][title=?]", "https://mydomain.foo/projects/ecookbook/repository/revisions/2", "This commit fixes #1, #2 and references #1 &amp; #3", :text => "r2"
43 end
49 end
44 end
50 end
45
51
46 def test_generated_links_with_prefix
52 def test_generated_links_with_prefix
47 relative_url_root = Redmine::Utils.relative_url_root
53 relative_url_root = Redmine::Utils.relative_url_root
48 ActionMailer::Base.deliveries.clear
54 ActionMailer::Base.deliveries.clear
49 Setting.host_name = 'mydomain.foo/rdm'
55 Setting.host_name = 'mydomain.foo/rdm'
50 Setting.protocol = 'http'
56 Setting.protocol = 'http'
51 Redmine::Utils.relative_url_root = '/rdm'
57 Redmine::Utils.relative_url_root = '/rdm'
52
58
53 journal = Journal.find(2)
59 journal = Journal.find(2)
54 assert Mailer.deliver_issue_edit(journal)
60 assert Mailer.deliver_issue_edit(journal)
55
61
56 mail = ActionMailer::Base.deliveries.last
62 mail = ActionMailer::Base.deliveries.last
57 assert_kind_of TMail::Mail, mail
63 assert_kind_of TMail::Mail, mail
58
64
59 assert_select_email do
65 assert_select_email do
60 # link to the main ticket
66 # link to the main ticket
61 assert_select "a[href=?]", "http://mydomain.foo/rdm/issues/1", :text => "Bug #1: Can't print recipes"
67 assert_select "a[href=?]", "http://mydomain.foo/rdm/issues/1", :text => "Bug #1: Can't print recipes"
62 # link to a referenced ticket
68 # link to a referenced ticket
63 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/issues/2", "Add ingredients categories (Assigned)", :text => "#2"
69 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/issues/2", "Add ingredients categories (Assigned)", :text => "#2"
64 # link to a changeset
70 # link to a changeset
65 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2", "This commit fixes #1, #2 and references #1 &amp; #3", :text => "r2"
71 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2", "This commit fixes #1, #2 and references #1 &amp; #3", :text => "r2"
66 end
72 end
67 ensure
73 ensure
68 # restore it
74 # restore it
69 Redmine::Utils.relative_url_root = relative_url_root
75 Redmine::Utils.relative_url_root = relative_url_root
70 end
76 end
71
77
72 def test_generated_links_with_prefix_and_no_relative_url_root
78 def test_generated_links_with_prefix_and_no_relative_url_root
73 relative_url_root = Redmine::Utils.relative_url_root
79 relative_url_root = Redmine::Utils.relative_url_root
74 ActionMailer::Base.deliveries.clear
80 ActionMailer::Base.deliveries.clear
75 Setting.host_name = 'mydomain.foo/rdm'
81 Setting.host_name = 'mydomain.foo/rdm'
76 Setting.protocol = 'http'
82 Setting.protocol = 'http'
77 Redmine::Utils.relative_url_root = nil
83 Redmine::Utils.relative_url_root = nil
78
84
79 journal = Journal.find(2)
85 journal = Journal.find(2)
80 assert Mailer.deliver_issue_edit(journal)
86 assert Mailer.deliver_issue_edit(journal)
81
87
82 mail = ActionMailer::Base.deliveries.last
88 mail = ActionMailer::Base.deliveries.last
83 assert_kind_of TMail::Mail, mail
89 assert_kind_of TMail::Mail, mail
84
90
85 assert_select_email do
91 assert_select_email do
86 # link to the main ticket
92 # link to the main ticket
87 assert_select "a[href=?]", "http://mydomain.foo/rdm/issues/1", :text => "Bug #1: Can't print recipes"
93 assert_select "a[href=?]", "http://mydomain.foo/rdm/issues/1", :text => "Bug #1: Can't print recipes"
88 # link to a referenced ticket
94 # link to a referenced ticket
89 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/issues/2", "Add ingredients categories (Assigned)", :text => "#2"
95 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/issues/2", "Add ingredients categories (Assigned)", :text => "#2"
90 # link to a changeset
96 # link to a changeset
91 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2", "This commit fixes #1, #2 and references #1 &amp; #3", :text => "r2"
97 assert_select "a[href=?][title=?]", "http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2", "This commit fixes #1, #2 and references #1 &amp; #3", :text => "r2"
92 end
98 end
93 ensure
99 ensure
94 # restore it
100 # restore it
95 Redmine::Utils.relative_url_root = relative_url_root
101 Redmine::Utils.relative_url_root = relative_url_root
96 end
102 end
97
103
98 def test_email_headers
104 def test_email_headers
99 ActionMailer::Base.deliveries.clear
105 ActionMailer::Base.deliveries.clear
100 issue = Issue.find(1)
106 issue = Issue.find(1)
101 Mailer.deliver_issue_add(issue)
107 Mailer.deliver_issue_add(issue)
102 mail = ActionMailer::Base.deliveries.last
108 mail = ActionMailer::Base.deliveries.last
103 assert_not_nil mail
109 assert_not_nil mail
104 assert_equal 'bulk', mail.header_string('Precedence')
110 assert_equal 'bulk', mail.header_string('Precedence')
105 assert_equal 'auto-generated', mail.header_string('Auto-Submitted')
111 assert_equal 'auto-generated', mail.header_string('Auto-Submitted')
106 end
112 end
107
113
108 def test_plain_text_mail
114 def test_plain_text_mail
109 Setting.plain_text_mail = 1
115 Setting.plain_text_mail = 1
110 journal = Journal.find(2)
116 journal = Journal.find(2)
111 Mailer.deliver_issue_edit(journal)
117 Mailer.deliver_issue_edit(journal)
112 mail = ActionMailer::Base.deliveries.last
118 mail = ActionMailer::Base.deliveries.last
113 assert_equal "text/plain", mail.content_type
119 assert_equal "text/plain", mail.content_type
114 assert_equal 0, mail.parts.size
120 assert_equal 0, mail.parts.size
115 assert !mail.encoded.include?('href')
121 assert !mail.encoded.include?('href')
116 end
122 end
117
123
118 def test_html_mail
124 def test_html_mail
119 Setting.plain_text_mail = 0
125 Setting.plain_text_mail = 0
120 journal = Journal.find(2)
126 journal = Journal.find(2)
121 Mailer.deliver_issue_edit(journal)
127 Mailer.deliver_issue_edit(journal)
122 mail = ActionMailer::Base.deliveries.last
128 mail = ActionMailer::Base.deliveries.last
123 assert_equal 2, mail.parts.size
129 assert_equal 2, mail.parts.size
124 assert mail.encoded.include?('href')
130 assert mail.encoded.include?('href')
125 end
131 end
126
132
127 def test_mail_from_with_phrase
133 def test_mail_from_with_phrase
128 ActionMailer::Base.deliveries.clear
134 ActionMailer::Base.deliveries.clear
129 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
135 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
130 Mailer.deliver_test(User.find(1))
136 Mailer.deliver_test(User.find(1))
131 end
137 end
132 mail = ActionMailer::Base.deliveries.last
138 mail = ActionMailer::Base.deliveries.last
133 assert_not_nil mail
139 assert_not_nil mail
134 assert_equal 'Redmine app', mail.from_addrs.first.name
140 assert_equal 'Redmine app', mail.from_addrs.first.name
135 end
141 end
136
142
137 def test_issue_add_message_id
143 def test_issue_add_message_id
138 ActionMailer::Base.deliveries.clear
144 ActionMailer::Base.deliveries.clear
139 issue = Issue.find(1)
145 issue = Issue.find(1)
140 Mailer.deliver_issue_add(issue)
146 Mailer.deliver_issue_add(issue)
141 mail = ActionMailer::Base.deliveries.last
147 mail = ActionMailer::Base.deliveries.last
142 assert_not_nil mail
148 assert_not_nil mail
143 assert_equal Mailer.message_id_for(issue), mail.message_id
149 assert_equal Mailer.message_id_for(issue), mail.message_id
144 assert_nil mail.references
150 assert_nil mail.references
145 end
151 end
146
152
147 def test_issue_edit_message_id
153 def test_issue_edit_message_id
148 ActionMailer::Base.deliveries.clear
154 ActionMailer::Base.deliveries.clear
149 journal = Journal.find(1)
155 journal = Journal.find(1)
150 Mailer.deliver_issue_edit(journal)
156 Mailer.deliver_issue_edit(journal)
151 mail = ActionMailer::Base.deliveries.last
157 mail = ActionMailer::Base.deliveries.last
152 assert_not_nil mail
158 assert_not_nil mail
153 assert_equal Mailer.message_id_for(journal), mail.message_id
159 assert_equal Mailer.message_id_for(journal), mail.message_id
154 assert_equal Mailer.message_id_for(journal.issue), mail.references.first.to_s
160 assert_equal Mailer.message_id_for(journal.issue), mail.references.first.to_s
155 end
161 end
156
162
157 def test_message_posted_message_id
163 def test_message_posted_message_id
158 ActionMailer::Base.deliveries.clear
159 message = Message.find(1)
164 message = Message.find(1)
160 Mailer.deliver_message_posted(message)
165 Mailer.deliver_message_posted(message)
161 mail = ActionMailer::Base.deliveries.last
166 mail = ActionMailer::Base.deliveries.last
162 assert_not_nil mail
167 assert_not_nil mail
163 assert_equal Mailer.message_id_for(message), mail.message_id
168 assert_equal Mailer.message_id_for(message), mail.message_id
164 assert_nil mail.references
169 assert_nil mail.references
170 assert_select_email do
171 # link to the message
172 assert_select "a[href=?]", "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}", :text => message.subject
173 end
165 end
174 end
166
175
167 def test_reply_posted_message_id
176 def test_reply_posted_message_id
168 ActionMailer::Base.deliveries.clear
169 message = Message.find(3)
177 message = Message.find(3)
170 Mailer.deliver_message_posted(message)
178 Mailer.deliver_message_posted(message)
171 mail = ActionMailer::Base.deliveries.last
179 mail = ActionMailer::Base.deliveries.last
172 assert_not_nil mail
180 assert_not_nil mail
173 assert_equal Mailer.message_id_for(message), mail.message_id
181 assert_equal Mailer.message_id_for(message), mail.message_id
174 assert_equal Mailer.message_id_for(message.parent), mail.references.first.to_s
182 assert_equal Mailer.message_id_for(message.parent), mail.references.first.to_s
183 assert_select_email do
184 # link to the reply
185 assert_select "a[href=?]", "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}", :text => message.subject
186 end
175 end
187 end
176
188
177 context("#issue_add") do
189 context("#issue_add") do
178 setup do
190 setup do
179 ActionMailer::Base.deliveries.clear
191 ActionMailer::Base.deliveries.clear
180 Setting.bcc_recipients = '1'
192 Setting.bcc_recipients = '1'
181 @issue = Issue.find(1)
193 @issue = Issue.find(1)
182 end
194 end
183
195
184 should "notify project members" do
196 should "notify project members" do
185 assert Mailer.deliver_issue_add(@issue)
197 assert Mailer.deliver_issue_add(@issue)
186 assert last_email.bcc.include?('dlopper@somenet.foo')
198 assert last_email.bcc.include?('dlopper@somenet.foo')
187 end
199 end
188
200
189 should "not notify project members that are not allow to view the issue" do
201 should "not notify project members that are not allow to view the issue" do
190 Role.find(2).remove_permission!(:view_issues)
202 Role.find(2).remove_permission!(:view_issues)
191 assert Mailer.deliver_issue_add(@issue)
203 assert Mailer.deliver_issue_add(@issue)
192 assert !last_email.bcc.include?('dlopper@somenet.foo')
204 assert !last_email.bcc.include?('dlopper@somenet.foo')
193 end
205 end
194
206
195 should "notify issue watchers" do
207 should "notify issue watchers" do
196 user = User.find(9)
208 user = User.find(9)
197 # minimal email notification options
209 # minimal email notification options
198 user.pref[:no_self_notified] = '1'
210 user.pref[:no_self_notified] = '1'
199 user.pref.save
211 user.pref.save
200 user.mail_notification = false
212 user.mail_notification = false
201 user.save
213 user.save
202
214
203 Watcher.create!(:watchable => @issue, :user => user)
215 Watcher.create!(:watchable => @issue, :user => user)
204 assert Mailer.deliver_issue_add(@issue)
216 assert Mailer.deliver_issue_add(@issue)
205 assert last_email.bcc.include?(user.mail)
217 assert last_email.bcc.include?(user.mail)
206 end
218 end
207
219
208 should "not notify watchers not allowed to view the issue" do
220 should "not notify watchers not allowed to view the issue" do
209 user = User.find(9)
221 user = User.find(9)
210 Watcher.create!(:watchable => @issue, :user => user)
222 Watcher.create!(:watchable => @issue, :user => user)
211 Role.non_member.remove_permission!(:view_issues)
223 Role.non_member.remove_permission!(:view_issues)
212 assert Mailer.deliver_issue_add(@issue)
224 assert Mailer.deliver_issue_add(@issue)
213 assert !last_email.bcc.include?(user.mail)
225 assert !last_email.bcc.include?(user.mail)
214 end
226 end
215 end
227 end
216
228
217 # test mailer methods for each language
229 # test mailer methods for each language
218 def test_issue_add
230 def test_issue_add
219 issue = Issue.find(1)
231 issue = Issue.find(1)
220 valid_languages.each do |lang|
232 valid_languages.each do |lang|
221 Setting.default_language = lang.to_s
233 Setting.default_language = lang.to_s
222 assert Mailer.deliver_issue_add(issue)
234 assert Mailer.deliver_issue_add(issue)
223 end
235 end
224 end
236 end
225
237
226 def test_issue_edit
238 def test_issue_edit
227 journal = Journal.find(1)
239 journal = Journal.find(1)
228 valid_languages.each do |lang|
240 valid_languages.each do |lang|
229 Setting.default_language = lang.to_s
241 Setting.default_language = lang.to_s
230 assert Mailer.deliver_issue_edit(journal)
242 assert Mailer.deliver_issue_edit(journal)
231 end
243 end
232 end
244 end
233
245
234 def test_document_added
246 def test_document_added
235 document = Document.find(1)
247 document = Document.find(1)
236 valid_languages.each do |lang|
248 valid_languages.each do |lang|
237 Setting.default_language = lang.to_s
249 Setting.default_language = lang.to_s
238 assert Mailer.deliver_document_added(document)
250 assert Mailer.deliver_document_added(document)
239 end
251 end
240 end
252 end
241
253
242 def test_attachments_added
254 def test_attachments_added
243 attachements = [ Attachment.find_by_container_type('Document') ]
255 attachements = [ Attachment.find_by_container_type('Document') ]
244 valid_languages.each do |lang|
256 valid_languages.each do |lang|
245 Setting.default_language = lang.to_s
257 Setting.default_language = lang.to_s
246 assert Mailer.deliver_attachments_added(attachements)
258 assert Mailer.deliver_attachments_added(attachements)
247 end
259 end
248 end
260 end
249
261
250 def test_news_added
262 def test_news_added
251 news = News.find(:first)
263 news = News.find(:first)
252 valid_languages.each do |lang|
264 valid_languages.each do |lang|
253 Setting.default_language = lang.to_s
265 Setting.default_language = lang.to_s
254 assert Mailer.deliver_news_added(news)
266 assert Mailer.deliver_news_added(news)
255 end
267 end
256 end
268 end
257
269
258 def test_message_posted
270 def test_message_posted
259 message = Message.find(:first)
271 message = Message.find(:first)
260 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
272 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
261 recipients = recipients.compact.uniq
273 recipients = recipients.compact.uniq
262 valid_languages.each do |lang|
274 valid_languages.each do |lang|
263 Setting.default_language = lang.to_s
275 Setting.default_language = lang.to_s
264 assert Mailer.deliver_message_posted(message)
276 assert Mailer.deliver_message_posted(message)
265 end
277 end
266 end
278 end
267
279
268 def test_account_information
280 def test_account_information
269 user = User.find(:first)
281 user = User.find(:first)
270 valid_languages.each do |lang|
282 valid_languages.each do |lang|
271 user.update_attribute :language, lang.to_s
283 user.update_attribute :language, lang.to_s
272 user.reload
284 user.reload
273 assert Mailer.deliver_account_information(user, 'pAsswORd')
285 assert Mailer.deliver_account_information(user, 'pAsswORd')
274 end
286 end
275 end
287 end
276
288
277 def test_lost_password
289 def test_lost_password
278 token = Token.find(2)
290 token = Token.find(2)
279 valid_languages.each do |lang|
291 valid_languages.each do |lang|
280 token.user.update_attribute :language, lang.to_s
292 token.user.update_attribute :language, lang.to_s
281 token.reload
293 token.reload
282 assert Mailer.deliver_lost_password(token)
294 assert Mailer.deliver_lost_password(token)
283 end
295 end
284 end
296 end
285
297
286 def test_register
298 def test_register
287 token = Token.find(1)
299 token = Token.find(1)
288 Setting.host_name = 'redmine.foo'
300 Setting.host_name = 'redmine.foo'
289 Setting.protocol = 'https'
301 Setting.protocol = 'https'
290
302
291 valid_languages.each do |lang|
303 valid_languages.each do |lang|
292 token.user.update_attribute :language, lang.to_s
304 token.user.update_attribute :language, lang.to_s
293 token.reload
305 token.reload
294 ActionMailer::Base.deliveries.clear
306 ActionMailer::Base.deliveries.clear
295 assert Mailer.deliver_register(token)
307 assert Mailer.deliver_register(token)
296 mail = ActionMailer::Base.deliveries.last
308 mail = ActionMailer::Base.deliveries.last
297 assert mail.body.include?("https://redmine.foo/account/activate?token=#{token.value}")
309 assert mail.body.include?("https://redmine.foo/account/activate?token=#{token.value}")
298 end
310 end
299 end
311 end
300
312
301 def test_reminders
313 def test_reminders
302 ActionMailer::Base.deliveries.clear
314 ActionMailer::Base.deliveries.clear
303 Mailer.reminders(:days => 42)
315 Mailer.reminders(:days => 42)
304 assert_equal 1, ActionMailer::Base.deliveries.size
316 assert_equal 1, ActionMailer::Base.deliveries.size
305 mail = ActionMailer::Base.deliveries.last
317 mail = ActionMailer::Base.deliveries.last
306 assert mail.bcc.include?('dlopper@somenet.foo')
318 assert mail.bcc.include?('dlopper@somenet.foo')
307 assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
319 assert mail.body.include?('Bug #3: Error 281 when updating a recipe')
308 end
320 end
309
321
310 def last_email
322 def last_email
311 mail = ActionMailer::Base.deliveries.last
323 mail = ActionMailer::Base.deliveries.last
312 assert_not_nil mail
324 assert_not_nil mail
313 mail
325 mail
314 end
326 end
315
327
316 def test_mailer_should_not_change_locale
328 def test_mailer_should_not_change_locale
317 Setting.default_language = 'en'
329 Setting.default_language = 'en'
318 # Set current language to italian
330 # Set current language to italian
319 set_language_if_valid 'it'
331 set_language_if_valid 'it'
320 # Send an email to a french user
332 # Send an email to a french user
321 user = User.find(1)
333 user = User.find(1)
322 user.language = 'fr'
334 user.language = 'fr'
323 Mailer.deliver_account_activated(user)
335 Mailer.deliver_account_activated(user)
324 mail = ActionMailer::Base.deliveries.last
336 mail = ActionMailer::Base.deliveries.last
325 assert mail.body.include?('Votre compte')
337 assert mail.body.include?('Votre compte')
326
338
327 assert_equal :it, current_language
339 assert_equal :it, current_language
328 end
340 end
329 end
341 end
General Comments 0
You need to be logged in to leave comments. Login now