##// END OF EJS Templates
Log email delivery errors (#14403)....
Jean-Philippe Lang -
r11780:8ff33ac9f781
parent child
Show More
@@ -1,475 +1,485
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2013 Jean-Philippe Lang
2 # Copyright (C) 2006-2013 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 Redmine::I18n
24 include Redmine::I18n
25
25
26 def self.default_url_options
26 def self.default_url_options
27 { :host => Setting.host_name, :protocol => Setting.protocol }
27 { :host => Setting.host_name, :protocol => Setting.protocol }
28 end
28 end
29
29
30 # Builds a Mail::Message object used to email recipients of the added issue.
30 # Builds a Mail::Message object used to email recipients of the added issue.
31 #
31 #
32 # Example:
32 # Example:
33 # issue_add(issue) => Mail::Message object
33 # issue_add(issue) => Mail::Message object
34 # Mailer.issue_add(issue).deliver => sends an email to issue recipients
34 # Mailer.issue_add(issue).deliver => sends an email to issue recipients
35 def issue_add(issue)
35 def issue_add(issue)
36 redmine_headers 'Project' => issue.project.identifier,
36 redmine_headers 'Project' => issue.project.identifier,
37 'Issue-Id' => issue.id,
37 'Issue-Id' => issue.id,
38 'Issue-Author' => issue.author.login
38 'Issue-Author' => issue.author.login
39 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
39 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
40 message_id issue
40 message_id issue
41 @author = issue.author
41 @author = issue.author
42 @issue = issue
42 @issue = issue
43 @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
43 @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
44 recipients = issue.recipients
44 recipients = issue.recipients
45 cc = issue.watcher_recipients - recipients
45 cc = issue.watcher_recipients - recipients
46 mail :to => recipients,
46 mail :to => recipients,
47 :cc => cc,
47 :cc => cc,
48 :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
48 :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
49 end
49 end
50
50
51 # Builds a Mail::Message object used to email recipients of the edited issue.
51 # Builds a Mail::Message object used to email recipients of the edited issue.
52 #
52 #
53 # Example:
53 # Example:
54 # issue_edit(journal) => Mail::Message object
54 # issue_edit(journal) => Mail::Message object
55 # Mailer.issue_edit(journal).deliver => sends an email to issue recipients
55 # Mailer.issue_edit(journal).deliver => sends an email to issue recipients
56 def issue_edit(journal)
56 def issue_edit(journal)
57 issue = journal.journalized.reload
57 issue = journal.journalized.reload
58 redmine_headers 'Project' => issue.project.identifier,
58 redmine_headers 'Project' => issue.project.identifier,
59 'Issue-Id' => issue.id,
59 'Issue-Id' => issue.id,
60 'Issue-Author' => issue.author.login
60 'Issue-Author' => issue.author.login
61 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
61 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
62 message_id journal
62 message_id journal
63 references issue
63 references issue
64 @author = journal.user
64 @author = journal.user
65 recipients = journal.recipients
65 recipients = journal.recipients
66 # Watchers in cc
66 # Watchers in cc
67 cc = journal.watcher_recipients - recipients
67 cc = journal.watcher_recipients - recipients
68 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
68 s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
69 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
69 s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
70 s << issue.subject
70 s << issue.subject
71 @issue = issue
71 @issue = issue
72 @journal = journal
72 @journal = journal
73 @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
73 @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
74 mail :to => recipients,
74 mail :to => recipients,
75 :cc => cc,
75 :cc => cc,
76 :subject => s
76 :subject => s
77 end
77 end
78
78
79 def reminder(user, issues, days)
79 def reminder(user, issues, days)
80 set_language_if_valid user.language
80 set_language_if_valid user.language
81 @issues = issues
81 @issues = issues
82 @days = days
82 @days = days
83 @issues_url = url_for(:controller => 'issues', :action => 'index',
83 @issues_url = url_for(:controller => 'issues', :action => 'index',
84 :set_filter => 1, :assigned_to_id => user.id,
84 :set_filter => 1, :assigned_to_id => user.id,
85 :sort => 'due_date:asc')
85 :sort => 'due_date:asc')
86 mail :to => user.mail,
86 mail :to => user.mail,
87 :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
87 :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
88 end
88 end
89
89
90 # Builds a Mail::Message object used to email users belonging to the added document's project.
90 # Builds a Mail::Message object used to email users belonging to the added document's project.
91 #
91 #
92 # Example:
92 # Example:
93 # document_added(document) => Mail::Message object
93 # document_added(document) => Mail::Message object
94 # Mailer.document_added(document).deliver => sends an email to the document's project recipients
94 # Mailer.document_added(document).deliver => 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 @author = User.current
97 @author = User.current
98 @document = document
98 @document = document
99 @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
99 @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
100 mail :to => document.recipients,
100 mail :to => document.recipients,
101 :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
101 :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
102 end
102 end
103
103
104 # Builds a Mail::Message object used to email recipients of a project when an attachements are added.
104 # Builds a Mail::Message object used to email recipients of a project when an attachements are added.
105 #
105 #
106 # Example:
106 # Example:
107 # attachments_added(attachments) => Mail::Message object
107 # attachments_added(attachments) => Mail::Message object
108 # Mailer.attachments_added(attachments).deliver => sends an email to the project's recipients
108 # Mailer.attachments_added(attachments).deliver => 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 @author = attachments.first.author
113 @author = attachments.first.author
114 case container.class.name
114 case container.class.name
115 when 'Project'
115 when 'Project'
116 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
116 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
117 added_to = "#{l(:label_project)}: #{container}"
117 added_to = "#{l(:label_project)}: #{container}"
118 recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
118 recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
119 when 'Version'
119 when 'Version'
120 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
120 added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
121 added_to = "#{l(:label_version)}: #{container.name}"
121 added_to = "#{l(:label_version)}: #{container.name}"
122 recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
122 recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect {|u| u.mail}
123 when 'Document'
123 when 'Document'
124 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
124 added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
125 added_to = "#{l(:label_document)}: #{container.title}"
125 added_to = "#{l(:label_document)}: #{container.title}"
126 recipients = container.recipients
126 recipients = container.recipients
127 end
127 end
128 redmine_headers 'Project' => container.project.identifier
128 redmine_headers 'Project' => container.project.identifier
129 @attachments = attachments
129 @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 mail :to => recipients,
132 mail :to => recipients,
133 :subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
133 :subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
134 end
134 end
135
135
136 # Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
136 # Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
137 #
137 #
138 # Example:
138 # Example:
139 # news_added(news) => Mail::Message object
139 # news_added(news) => Mail::Message object
140 # Mailer.news_added(news).deliver => sends an email to the news' project recipients
140 # Mailer.news_added(news).deliver => sends an email to the news' project recipients
141 def news_added(news)
141 def news_added(news)
142 redmine_headers 'Project' => news.project.identifier
142 redmine_headers 'Project' => news.project.identifier
143 @author = news.author
143 @author = news.author
144 message_id news
144 message_id news
145 @news = news
145 @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 mail :to => news.recipients,
147 mail :to => news.recipients,
148 :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
148 :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
149 end
149 end
150
150
151 # Builds a Mail::Message object used to email recipients of a news' project when a news comment is added.
151 # Builds a Mail::Message object used to email recipients of a news' project when a news comment is added.
152 #
152 #
153 # Example:
153 # Example:
154 # news_comment_added(comment) => Mail::Message object
154 # news_comment_added(comment) => Mail::Message object
155 # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
155 # Mailer.news_comment_added(comment) => sends an email to the news' project recipients
156 def news_comment_added(comment)
156 def news_comment_added(comment)
157 news = comment.commented
157 news = comment.commented
158 redmine_headers 'Project' => news.project.identifier
158 redmine_headers 'Project' => news.project.identifier
159 @author = comment.author
159 @author = comment.author
160 message_id comment
160 message_id comment
161 @news = news
161 @news = news
162 @comment = comment
162 @comment = comment
163 @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
163 @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
164 mail :to => news.recipients,
164 mail :to => news.recipients,
165 :cc => news.watcher_recipients,
165 :cc => news.watcher_recipients,
166 :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
166 :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
167 end
167 end
168
168
169 # Builds a Mail::Message object used to email the recipients of the specified message that was posted.
169 # Builds a Mail::Message object used to email the recipients of the specified message that was posted.
170 #
170 #
171 # Example:
171 # Example:
172 # message_posted(message) => Mail::Message object
172 # message_posted(message) => Mail::Message object
173 # Mailer.message_posted(message).deliver => sends an email to the recipients
173 # Mailer.message_posted(message).deliver => sends an email to the recipients
174 def message_posted(message)
174 def message_posted(message)
175 redmine_headers 'Project' => message.project.identifier,
175 redmine_headers 'Project' => message.project.identifier,
176 'Topic-Id' => (message.parent_id || message.id)
176 'Topic-Id' => (message.parent_id || message.id)
177 @author = message.author
177 @author = message.author
178 message_id message
178 message_id message
179 references message.parent unless message.parent.nil?
179 references message.parent unless message.parent.nil?
180 recipients = message.recipients
180 recipients = message.recipients
181 cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
181 cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
182 @message = message
182 @message = message
183 @message_url = url_for(message.event_url)
183 @message_url = url_for(message.event_url)
184 mail :to => recipients,
184 mail :to => recipients,
185 :cc => cc,
185 :cc => cc,
186 :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
186 :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
187 end
187 end
188
188
189 # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
189 # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
190 #
190 #
191 # Example:
191 # Example:
192 # wiki_content_added(wiki_content) => Mail::Message object
192 # wiki_content_added(wiki_content) => Mail::Message object
193 # Mailer.wiki_content_added(wiki_content).deliver => sends an email to the project's recipients
193 # Mailer.wiki_content_added(wiki_content).deliver => sends an email to the project's recipients
194 def wiki_content_added(wiki_content)
194 def wiki_content_added(wiki_content)
195 redmine_headers 'Project' => wiki_content.project.identifier,
195 redmine_headers 'Project' => wiki_content.project.identifier,
196 'Wiki-Page-Id' => wiki_content.page.id
196 'Wiki-Page-Id' => wiki_content.page.id
197 @author = wiki_content.author
197 @author = wiki_content.author
198 message_id wiki_content
198 message_id wiki_content
199 recipients = wiki_content.recipients
199 recipients = wiki_content.recipients
200 cc = wiki_content.page.wiki.watcher_recipients - recipients
200 cc = wiki_content.page.wiki.watcher_recipients - recipients
201 @wiki_content = wiki_content
201 @wiki_content = wiki_content
202 @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
202 @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
203 :project_id => wiki_content.project,
203 :project_id => wiki_content.project,
204 :id => wiki_content.page.title)
204 :id => wiki_content.page.title)
205 mail :to => recipients,
205 mail :to => recipients,
206 :cc => cc,
206 :cc => cc,
207 :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
207 :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
208 end
208 end
209
209
210 # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was updated.
210 # Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was updated.
211 #
211 #
212 # Example:
212 # Example:
213 # wiki_content_updated(wiki_content) => Mail::Message object
213 # wiki_content_updated(wiki_content) => Mail::Message object
214 # Mailer.wiki_content_updated(wiki_content).deliver => sends an email to the project's recipients
214 # Mailer.wiki_content_updated(wiki_content).deliver => sends an email to the project's recipients
215 def wiki_content_updated(wiki_content)
215 def wiki_content_updated(wiki_content)
216 redmine_headers 'Project' => wiki_content.project.identifier,
216 redmine_headers 'Project' => wiki_content.project.identifier,
217 'Wiki-Page-Id' => wiki_content.page.id
217 'Wiki-Page-Id' => wiki_content.page.id
218 @author = wiki_content.author
218 @author = wiki_content.author
219 message_id wiki_content
219 message_id wiki_content
220 recipients = wiki_content.recipients
220 recipients = wiki_content.recipients
221 cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
221 cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
222 @wiki_content = wiki_content
222 @wiki_content = wiki_content
223 @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
223 @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
224 :project_id => wiki_content.project,
224 :project_id => wiki_content.project,
225 :id => wiki_content.page.title)
225 :id => wiki_content.page.title)
226 @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
226 @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
227 :project_id => wiki_content.project, :id => wiki_content.page.title,
227 :project_id => wiki_content.project, :id => wiki_content.page.title,
228 :version => wiki_content.version)
228 :version => wiki_content.version)
229 mail :to => recipients,
229 mail :to => recipients,
230 :cc => cc,
230 :cc => cc,
231 :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
231 :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
232 end
232 end
233
233
234 # Builds a Mail::Message object used to email the specified user their account information.
234 # Builds a Mail::Message object used to email the specified user their account information.
235 #
235 #
236 # Example:
236 # Example:
237 # account_information(user, password) => Mail::Message object
237 # account_information(user, password) => Mail::Message object
238 # Mailer.account_information(user, password).deliver => sends account information to the user
238 # Mailer.account_information(user, password).deliver => sends account information to the user
239 def account_information(user, password)
239 def account_information(user, password)
240 set_language_if_valid user.language
240 set_language_if_valid user.language
241 @user = user
241 @user = user
242 @password = password
242 @password = password
243 @login_url = url_for(:controller => 'account', :action => 'login')
243 @login_url = url_for(:controller => 'account', :action => 'login')
244 mail :to => user.mail,
244 mail :to => user.mail,
245 :subject => l(:mail_subject_register, Setting.app_title)
245 :subject => l(:mail_subject_register, Setting.app_title)
246 end
246 end
247
247
248 # Builds a Mail::Message object used to email all active administrators of an account activation request.
248 # Builds a Mail::Message object used to email all active administrators of an account activation request.
249 #
249 #
250 # Example:
250 # Example:
251 # account_activation_request(user) => Mail::Message object
251 # account_activation_request(user) => Mail::Message object
252 # Mailer.account_activation_request(user).deliver => sends an email to all active administrators
252 # Mailer.account_activation_request(user).deliver => sends an email to all active administrators
253 def account_activation_request(user)
253 def account_activation_request(user)
254 # Send the email to all active administrators
254 # Send the email to all active administrators
255 recipients = User.active.where(:admin => true).all.collect { |u| u.mail }.compact
255 recipients = User.active.where(:admin => true).all.collect { |u| u.mail }.compact
256 @user = user
256 @user = user
257 @url = url_for(:controller => 'users', :action => 'index',
257 @url = url_for(:controller => 'users', :action => 'index',
258 :status => User::STATUS_REGISTERED,
258 :status => User::STATUS_REGISTERED,
259 :sort_key => 'created_on', :sort_order => 'desc')
259 :sort_key => 'created_on', :sort_order => 'desc')
260 mail :to => recipients,
260 mail :to => recipients,
261 :subject => l(:mail_subject_account_activation_request, Setting.app_title)
261 :subject => l(:mail_subject_account_activation_request, Setting.app_title)
262 end
262 end
263
263
264 # Builds a Mail::Message object used to email the specified user that their account was activated by an administrator.
264 # Builds a Mail::Message object used to email the specified user that their account was activated by an administrator.
265 #
265 #
266 # Example:
266 # Example:
267 # account_activated(user) => Mail::Message object
267 # account_activated(user) => Mail::Message object
268 # Mailer.account_activated(user).deliver => sends an email to the registered user
268 # Mailer.account_activated(user).deliver => sends an email to the registered user
269 def account_activated(user)
269 def account_activated(user)
270 set_language_if_valid user.language
270 set_language_if_valid user.language
271 @user = user
271 @user = user
272 @login_url = url_for(:controller => 'account', :action => 'login')
272 @login_url = url_for(:controller => 'account', :action => 'login')
273 mail :to => user.mail,
273 mail :to => user.mail,
274 :subject => l(:mail_subject_register, Setting.app_title)
274 :subject => l(:mail_subject_register, Setting.app_title)
275 end
275 end
276
276
277 def lost_password(token)
277 def lost_password(token)
278 set_language_if_valid(token.user.language)
278 set_language_if_valid(token.user.language)
279 @token = token
279 @token = token
280 @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
280 @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
281 mail :to => token.user.mail,
281 mail :to => token.user.mail,
282 :subject => l(:mail_subject_lost_password, Setting.app_title)
282 :subject => l(:mail_subject_lost_password, Setting.app_title)
283 end
283 end
284
284
285 def register(token)
285 def register(token)
286 set_language_if_valid(token.user.language)
286 set_language_if_valid(token.user.language)
287 @token = token
287 @token = token
288 @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
288 @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
289 mail :to => token.user.mail,
289 mail :to => token.user.mail,
290 :subject => l(:mail_subject_register, Setting.app_title)
290 :subject => l(:mail_subject_register, Setting.app_title)
291 end
291 end
292
292
293 def test_email(user)
293 def test_email(user)
294 set_language_if_valid(user.language)
294 set_language_if_valid(user.language)
295 @url = url_for(:controller => 'welcome')
295 @url = url_for(:controller => 'welcome')
296 mail :to => user.mail,
296 mail :to => user.mail,
297 :subject => 'Redmine test'
297 :subject => 'Redmine test'
298 end
298 end
299
299
300 # Overrides default deliver! method to prevent from sending an email
300 # Overrides default deliver! method to prevent from sending an email
301 # with no recipient, cc or bcc
301 # with no recipient, cc or bcc
302 def deliver!(mail = @mail)
302 def deliver!(mail = @mail)
303 set_language_if_valid @initial_language
303 set_language_if_valid @initial_language
304 return false if (recipients.nil? || recipients.empty?) &&
304 return false if (recipients.nil? || recipients.empty?) &&
305 (cc.nil? || cc.empty?) &&
305 (cc.nil? || cc.empty?) &&
306 (bcc.nil? || bcc.empty?)
306 (bcc.nil? || bcc.empty?)
307
307
308
308
309 # Log errors when raise_delivery_errors is set to false, Rails does not
309 # Log errors when raise_delivery_errors is set to false, Rails does not
310 raise_errors = self.class.raise_delivery_errors
310 raise_errors = self.class.raise_delivery_errors
311 self.class.raise_delivery_errors = true
311 self.class.raise_delivery_errors = true
312 begin
312 begin
313 return super(mail)
313 return super(mail)
314 rescue Exception => e
314 rescue Exception => e
315 if raise_errors
315 if raise_errors
316 raise e
316 raise e
317 elsif mylogger
317 elsif mylogger
318 mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
318 mylogger.error "The following error occured while sending email notification: \"#{e.message}\". Check your configuration in config/configuration.yml."
319 end
319 end
320 ensure
320 ensure
321 self.class.raise_delivery_errors = raise_errors
321 self.class.raise_delivery_errors = raise_errors
322 end
322 end
323 end
323 end
324
324
325 # Sends reminders to issue assignees
325 # Sends reminders to issue assignees
326 # Available options:
326 # Available options:
327 # * :days => how many days in the future to remind about (defaults to 7)
327 # * :days => how many days in the future to remind about (defaults to 7)
328 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
328 # * :tracker => id of tracker for filtering issues (defaults to all trackers)
329 # * :project => id or identifier of project to process (defaults to all projects)
329 # * :project => id or identifier of project to process (defaults to all projects)
330 # * :users => array of user/group ids who should be reminded
330 # * :users => array of user/group ids who should be reminded
331 def self.reminders(options={})
331 def self.reminders(options={})
332 days = options[:days] || 7
332 days = options[:days] || 7
333 project = options[:project] ? Project.find(options[:project]) : nil
333 project = options[:project] ? Project.find(options[:project]) : nil
334 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
334 tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
335 user_ids = options[:users]
335 user_ids = options[:users]
336
336
337 scope = Issue.open.where("#{Issue.table_name}.assigned_to_id IS NOT NULL" +
337 scope = Issue.open.where("#{Issue.table_name}.assigned_to_id IS NOT NULL" +
338 " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
338 " AND #{Project.table_name}.status = #{Project::STATUS_ACTIVE}" +
339 " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date
339 " AND #{Issue.table_name}.due_date <= ?", days.day.from_now.to_date
340 )
340 )
341 scope = scope.where(:assigned_to_id => user_ids) if user_ids.present?
341 scope = scope.where(:assigned_to_id => user_ids) if user_ids.present?
342 scope = scope.where(:project_id => project.id) if project
342 scope = scope.where(:project_id => project.id) if project
343 scope = scope.where(:tracker_id => tracker.id) if tracker
343 scope = scope.where(:tracker_id => tracker.id) if tracker
344
344
345 issues_by_assignee = scope.includes(:status, :assigned_to, :project, :tracker).all.group_by(&:assigned_to)
345 issues_by_assignee = scope.includes(:status, :assigned_to, :project, :tracker).all.group_by(&:assigned_to)
346 issues_by_assignee.keys.each do |assignee|
346 issues_by_assignee.keys.each do |assignee|
347 if assignee.is_a?(Group)
347 if assignee.is_a?(Group)
348 assignee.users.each do |user|
348 assignee.users.each do |user|
349 issues_by_assignee[user] ||= []
349 issues_by_assignee[user] ||= []
350 issues_by_assignee[user] += issues_by_assignee[assignee]
350 issues_by_assignee[user] += issues_by_assignee[assignee]
351 end
351 end
352 end
352 end
353 end
353 end
354
354
355 issues_by_assignee.each do |assignee, issues|
355 issues_by_assignee.each do |assignee, issues|
356 reminder(assignee, issues, days).deliver if assignee.is_a?(User) && assignee.active?
356 reminder(assignee, issues, days).deliver if assignee.is_a?(User) && assignee.active?
357 end
357 end
358 end
358 end
359
359
360 # Activates/desactivates email deliveries during +block+
360 # Activates/desactivates email deliveries during +block+
361 def self.with_deliveries(enabled = true, &block)
361 def self.with_deliveries(enabled = true, &block)
362 was_enabled = ActionMailer::Base.perform_deliveries
362 was_enabled = ActionMailer::Base.perform_deliveries
363 ActionMailer::Base.perform_deliveries = !!enabled
363 ActionMailer::Base.perform_deliveries = !!enabled
364 yield
364 yield
365 ensure
365 ensure
366 ActionMailer::Base.perform_deliveries = was_enabled
366 ActionMailer::Base.perform_deliveries = was_enabled
367 end
367 end
368
368
369 # Sends emails synchronously in the given block
369 # Sends emails synchronously in the given block
370 def self.with_synched_deliveries(&block)
370 def self.with_synched_deliveries(&block)
371 saved_method = ActionMailer::Base.delivery_method
371 saved_method = ActionMailer::Base.delivery_method
372 if m = saved_method.to_s.match(%r{^async_(.+)$})
372 if m = saved_method.to_s.match(%r{^async_(.+)$})
373 synched_method = m[1]
373 synched_method = m[1]
374 ActionMailer::Base.delivery_method = synched_method.to_sym
374 ActionMailer::Base.delivery_method = synched_method.to_sym
375 ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
375 ActionMailer::Base.send "#{synched_method}_settings=", ActionMailer::Base.send("async_#{synched_method}_settings")
376 end
376 end
377 yield
377 yield
378 ensure
378 ensure
379 ActionMailer::Base.delivery_method = saved_method
379 ActionMailer::Base.delivery_method = saved_method
380 end
380 end
381
381
382 def mail(headers={})
382 def mail(headers={})
383 headers.merge! 'X-Mailer' => 'Redmine',
383 headers.merge! 'X-Mailer' => 'Redmine',
384 'X-Redmine-Host' => Setting.host_name,
384 'X-Redmine-Host' => Setting.host_name,
385 'X-Redmine-Site' => Setting.app_title,
385 'X-Redmine-Site' => Setting.app_title,
386 'X-Auto-Response-Suppress' => 'OOF',
386 'X-Auto-Response-Suppress' => 'OOF',
387 'Auto-Submitted' => 'auto-generated',
387 'Auto-Submitted' => 'auto-generated',
388 'From' => Setting.mail_from,
388 'From' => Setting.mail_from,
389 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
389 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
390
390
391 # Removes the author from the recipients and cc
391 # Removes the author from the recipients and cc
392 # if the author does not want to receive notifications
392 # if the author does not want to receive notifications
393 # about what the author do
393 # about what the author do
394 if @author && @author.logged? && @author.pref.no_self_notified
394 if @author && @author.logged? && @author.pref.no_self_notified
395 headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
395 headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
396 headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
396 headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
397 end
397 end
398
398
399 if @author && @author.logged?
399 if @author && @author.logged?
400 redmine_headers 'Sender' => @author.login
400 redmine_headers 'Sender' => @author.login
401 end
401 end
402
402
403 # Blind carbon copy recipients
403 # Blind carbon copy recipients
404 if Setting.bcc_recipients?
404 if Setting.bcc_recipients?
405 headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
405 headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
406 headers[:to] = nil
406 headers[:to] = nil
407 headers[:cc] = nil
407 headers[:cc] = nil
408 end
408 end
409
409
410 if @message_id_object
410 if @message_id_object
411 headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
411 headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
412 end
412 end
413 if @references_objects
413 if @references_objects
414 headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
414 headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
415 end
415 end
416
416
417 super headers do |format|
417 super headers do |format|
418 format.text
418 format.text
419 format.html unless Setting.plain_text_mail?
419 format.html unless Setting.plain_text_mail?
420 end
420 end
421
421
422 set_language_if_valid @initial_language
422 set_language_if_valid @initial_language
423 end
423 end
424
424
425 def initialize(*args)
425 def initialize(*args)
426 @initial_language = current_language
426 @initial_language = current_language
427 set_language_if_valid Setting.default_language
427 set_language_if_valid Setting.default_language
428 super
428 super
429 end
429 end
430
430
431 def self.deliver_mail(mail)
431 def self.deliver_mail(mail)
432 return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
432 return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
433 begin
434 # Log errors when raise_delivery_errors is set to false, Rails does not
435 mail.raise_delivery_errors = true
433 super
436 super
437 rescue Exception => e
438 if ActionMailer::Base.raise_delivery_errors
439 raise e
440 else
441 Rails.logger.error "Email delivery error: #{e.message}"
442 end
443 end
434 end
444 end
435
445
436 def self.method_missing(method, *args, &block)
446 def self.method_missing(method, *args, &block)
437 if m = method.to_s.match(%r{^deliver_(.+)$})
447 if m = method.to_s.match(%r{^deliver_(.+)$})
438 ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
448 ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
439 send(m[1], *args).deliver
449 send(m[1], *args).deliver
440 else
450 else
441 super
451 super
442 end
452 end
443 end
453 end
444
454
445 private
455 private
446
456
447 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
457 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
448 def redmine_headers(h)
458 def redmine_headers(h)
449 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
459 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
450 end
460 end
451
461
452 # Returns a predictable Message-Id for the given object
462 # Returns a predictable Message-Id for the given object
453 def self.message_id_for(object)
463 def self.message_id_for(object)
454 # id + timestamp should reduce the odds of a collision
464 # id + timestamp should reduce the odds of a collision
455 # as far as we don't send multiple emails for the same object
465 # as far as we don't send multiple emails for the same object
456 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
466 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
457 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
467 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
458 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
468 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
459 host = "#{::Socket.gethostname}.redmine" if host.empty?
469 host = "#{::Socket.gethostname}.redmine" if host.empty?
460 "#{hash}@#{host}"
470 "#{hash}@#{host}"
461 end
471 end
462
472
463 def message_id(object)
473 def message_id(object)
464 @message_id_object = object
474 @message_id_object = object
465 end
475 end
466
476
467 def references(object)
477 def references(object)
468 @references_objects ||= []
478 @references_objects ||= []
469 @references_objects << object
479 @references_objects << object
470 end
480 end
471
481
472 def mylogger
482 def mylogger
473 Rails.logger
483 Rails.logger
474 end
484 end
475 end
485 end
@@ -1,679 +1,702
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2013 Jean-Philippe Lang
2 # Copyright (C) 2006-2013 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 ActionDispatch::Assertions::SelectorAssertions
22 include ActionDispatch::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,
25 :tokens, :journals, :journal_details, :changesets,
26 :trackers, :projects_trackers,
26 :trackers, :projects_trackers,
27 :issue_statuses, :enumerations, :messages, :boards, :repositories,
27 :issue_statuses, :enumerations, :messages, :boards, :repositories,
28 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
28 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
29 :versions,
29 :versions,
30 :comments
30 :comments
31
31
32 def setup
32 def setup
33 ActionMailer::Base.deliveries.clear
33 ActionMailer::Base.deliveries.clear
34 Setting.host_name = 'mydomain.foo'
34 Setting.host_name = 'mydomain.foo'
35 Setting.protocol = 'http'
35 Setting.protocol = 'http'
36 Setting.plain_text_mail = '0'
36 Setting.plain_text_mail = '0'
37 end
37 end
38
38
39 def test_generated_links_in_emails
39 def test_generated_links_in_emails
40 Setting.default_language = 'en'
40 Setting.default_language = 'en'
41 Setting.host_name = 'mydomain.foo'
41 Setting.host_name = 'mydomain.foo'
42 Setting.protocol = 'https'
42 Setting.protocol = 'https'
43
43
44 journal = Journal.find(3)
44 journal = Journal.find(3)
45 assert Mailer.issue_edit(journal).deliver
45 assert Mailer.issue_edit(journal).deliver
46
46
47 mail = last_email
47 mail = last_email
48 assert_not_nil mail
48 assert_not_nil mail
49
49
50 assert_select_email do
50 assert_select_email do
51 # link to the main ticket
51 # link to the main ticket
52 assert_select 'a[href=?]',
52 assert_select 'a[href=?]',
53 'https://mydomain.foo/issues/2#change-3',
53 'https://mydomain.foo/issues/2#change-3',
54 :text => 'Feature request #2: Add ingredients categories'
54 :text => 'Feature request #2: Add ingredients categories'
55 # link to a referenced ticket
55 # link to a referenced ticket
56 assert_select 'a[href=?][title=?]',
56 assert_select 'a[href=?][title=?]',
57 'https://mydomain.foo/issues/1',
57 'https://mydomain.foo/issues/1',
58 'Can&#x27;t print recipes (New)',
58 'Can&#x27;t print recipes (New)',
59 :text => '#1'
59 :text => '#1'
60 # link to a changeset
60 # link to a changeset
61 assert_select 'a[href=?][title=?]',
61 assert_select 'a[href=?][title=?]',
62 'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
62 'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
63 'This commit fixes #1, #2 and references #1 &amp; #3',
63 'This commit fixes #1, #2 and references #1 &amp; #3',
64 :text => 'r2'
64 :text => 'r2'
65 # link to a description diff
65 # link to a description diff
66 assert_select 'a[href=?][title=?]',
66 assert_select 'a[href=?][title=?]',
67 'https://mydomain.foo/journals/diff/3?detail_id=4',
67 'https://mydomain.foo/journals/diff/3?detail_id=4',
68 'View differences',
68 'View differences',
69 :text => 'diff'
69 :text => 'diff'
70 # link to an attachment
70 # link to an attachment
71 assert_select 'a[href=?]',
71 assert_select 'a[href=?]',
72 'https://mydomain.foo/attachments/download/4/source.rb',
72 'https://mydomain.foo/attachments/download/4/source.rb',
73 :text => 'source.rb'
73 :text => 'source.rb'
74 end
74 end
75 end
75 end
76
76
77 def test_generated_links_with_prefix
77 def test_generated_links_with_prefix
78 Setting.default_language = 'en'
78 Setting.default_language = 'en'
79 relative_url_root = Redmine::Utils.relative_url_root
79 relative_url_root = Redmine::Utils.relative_url_root
80 Setting.host_name = 'mydomain.foo/rdm'
80 Setting.host_name = 'mydomain.foo/rdm'
81 Setting.protocol = 'http'
81 Setting.protocol = 'http'
82
82
83 journal = Journal.find(3)
83 journal = Journal.find(3)
84 assert Mailer.issue_edit(journal).deliver
84 assert Mailer.issue_edit(journal).deliver
85
85
86 mail = last_email
86 mail = last_email
87 assert_not_nil mail
87 assert_not_nil mail
88
88
89 assert_select_email do
89 assert_select_email do
90 # link to the main ticket
90 # link to the main ticket
91 assert_select 'a[href=?]',
91 assert_select 'a[href=?]',
92 'http://mydomain.foo/rdm/issues/2#change-3',
92 'http://mydomain.foo/rdm/issues/2#change-3',
93 :text => 'Feature request #2: Add ingredients categories'
93 :text => 'Feature request #2: Add ingredients categories'
94 # link to a referenced ticket
94 # link to a referenced ticket
95 assert_select 'a[href=?][title=?]',
95 assert_select 'a[href=?][title=?]',
96 'http://mydomain.foo/rdm/issues/1',
96 'http://mydomain.foo/rdm/issues/1',
97 'Can&#x27;t print recipes (New)',
97 'Can&#x27;t print recipes (New)',
98 :text => '#1'
98 :text => '#1'
99 # link to a changeset
99 # link to a changeset
100 assert_select 'a[href=?][title=?]',
100 assert_select 'a[href=?][title=?]',
101 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
101 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
102 'This commit fixes #1, #2 and references #1 &amp; #3',
102 'This commit fixes #1, #2 and references #1 &amp; #3',
103 :text => 'r2'
103 :text => 'r2'
104 # link to a description diff
104 # link to a description diff
105 assert_select 'a[href=?][title=?]',
105 assert_select 'a[href=?][title=?]',
106 'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
106 'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
107 'View differences',
107 'View differences',
108 :text => 'diff'
108 :text => 'diff'
109 # link to an attachment
109 # link to an attachment
110 assert_select 'a[href=?]',
110 assert_select 'a[href=?]',
111 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
111 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
112 :text => 'source.rb'
112 :text => 'source.rb'
113 end
113 end
114 end
114 end
115
115
116 def test_generated_links_with_prefix_and_no_relative_url_root
116 def test_generated_links_with_prefix_and_no_relative_url_root
117 Setting.default_language = 'en'
117 Setting.default_language = 'en'
118 relative_url_root = Redmine::Utils.relative_url_root
118 relative_url_root = Redmine::Utils.relative_url_root
119 Setting.host_name = 'mydomain.foo/rdm'
119 Setting.host_name = 'mydomain.foo/rdm'
120 Setting.protocol = 'http'
120 Setting.protocol = 'http'
121 Redmine::Utils.relative_url_root = nil
121 Redmine::Utils.relative_url_root = nil
122
122
123 journal = Journal.find(3)
123 journal = Journal.find(3)
124 assert Mailer.issue_edit(journal).deliver
124 assert Mailer.issue_edit(journal).deliver
125
125
126 mail = last_email
126 mail = last_email
127 assert_not_nil mail
127 assert_not_nil mail
128
128
129 assert_select_email do
129 assert_select_email do
130 # link to the main ticket
130 # link to the main ticket
131 assert_select 'a[href=?]',
131 assert_select 'a[href=?]',
132 'http://mydomain.foo/rdm/issues/2#change-3',
132 'http://mydomain.foo/rdm/issues/2#change-3',
133 :text => 'Feature request #2: Add ingredients categories'
133 :text => 'Feature request #2: Add ingredients categories'
134 # link to a referenced ticket
134 # link to a referenced ticket
135 assert_select 'a[href=?][title=?]',
135 assert_select 'a[href=?][title=?]',
136 'http://mydomain.foo/rdm/issues/1',
136 'http://mydomain.foo/rdm/issues/1',
137 'Can&#x27;t print recipes (New)',
137 'Can&#x27;t print recipes (New)',
138 :text => '#1'
138 :text => '#1'
139 # link to a changeset
139 # link to a changeset
140 assert_select 'a[href=?][title=?]',
140 assert_select 'a[href=?][title=?]',
141 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
141 'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
142 'This commit fixes #1, #2 and references #1 &amp; #3',
142 'This commit fixes #1, #2 and references #1 &amp; #3',
143 :text => 'r2'
143 :text => 'r2'
144 # link to a description diff
144 # link to a description diff
145 assert_select 'a[href=?][title=?]',
145 assert_select 'a[href=?][title=?]',
146 'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
146 'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
147 'View differences',
147 'View differences',
148 :text => 'diff'
148 :text => 'diff'
149 # link to an attachment
149 # link to an attachment
150 assert_select 'a[href=?]',
150 assert_select 'a[href=?]',
151 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
151 'http://mydomain.foo/rdm/attachments/download/4/source.rb',
152 :text => 'source.rb'
152 :text => 'source.rb'
153 end
153 end
154 ensure
154 ensure
155 # restore it
155 # restore it
156 Redmine::Utils.relative_url_root = relative_url_root
156 Redmine::Utils.relative_url_root = relative_url_root
157 end
157 end
158
158
159 def test_email_headers
159 def test_email_headers
160 issue = Issue.find(1)
160 issue = Issue.find(1)
161 Mailer.issue_add(issue).deliver
161 Mailer.issue_add(issue).deliver
162 mail = last_email
162 mail = last_email
163 assert_not_nil mail
163 assert_not_nil mail
164 assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
164 assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
165 assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
165 assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
166 assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s
166 assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s
167 end
167 end
168
168
169 def test_email_headers_should_include_sender
169 def test_email_headers_should_include_sender
170 issue = Issue.find(1)
170 issue = Issue.find(1)
171 Mailer.issue_add(issue).deliver
171 Mailer.issue_add(issue).deliver
172 mail = last_email
172 mail = last_email
173 assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
173 assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
174 end
174 end
175
175
176 def test_plain_text_mail
176 def test_plain_text_mail
177 Setting.plain_text_mail = 1
177 Setting.plain_text_mail = 1
178 journal = Journal.find(2)
178 journal = Journal.find(2)
179 Mailer.issue_edit(journal).deliver
179 Mailer.issue_edit(journal).deliver
180 mail = last_email
180 mail = last_email
181 assert_equal "text/plain; charset=UTF-8", mail.content_type
181 assert_equal "text/plain; charset=UTF-8", mail.content_type
182 assert_equal 0, mail.parts.size
182 assert_equal 0, mail.parts.size
183 assert !mail.encoded.include?('href')
183 assert !mail.encoded.include?('href')
184 end
184 end
185
185
186 def test_html_mail
186 def test_html_mail
187 Setting.plain_text_mail = 0
187 Setting.plain_text_mail = 0
188 journal = Journal.find(2)
188 journal = Journal.find(2)
189 Mailer.issue_edit(journal).deliver
189 Mailer.issue_edit(journal).deliver
190 mail = last_email
190 mail = last_email
191 assert_equal 2, mail.parts.size
191 assert_equal 2, mail.parts.size
192 assert mail.encoded.include?('href')
192 assert mail.encoded.include?('href')
193 end
193 end
194
194
195 def test_from_header
195 def test_from_header
196 with_settings :mail_from => 'redmine@example.net' do
196 with_settings :mail_from => 'redmine@example.net' do
197 Mailer.test_email(User.find(1)).deliver
197 Mailer.test_email(User.find(1)).deliver
198 end
198 end
199 mail = last_email
199 mail = last_email
200 assert_equal 'redmine@example.net', mail.from_addrs.first
200 assert_equal 'redmine@example.net', mail.from_addrs.first
201 end
201 end
202
202
203 def test_from_header_with_phrase
203 def test_from_header_with_phrase
204 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
204 with_settings :mail_from => 'Redmine app <redmine@example.net>' do
205 Mailer.test_email(User.find(1)).deliver
205 Mailer.test_email(User.find(1)).deliver
206 end
206 end
207 mail = last_email
207 mail = last_email
208 assert_equal 'redmine@example.net', mail.from_addrs.first
208 assert_equal 'redmine@example.net', mail.from_addrs.first
209 assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
209 assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
210 end
210 end
211
211
212 def test_should_not_send_email_without_recipient
212 def test_should_not_send_email_without_recipient
213 news = News.first
213 news = News.first
214 user = news.author
214 user = news.author
215 # Remove members except news author
215 # Remove members except news author
216 news.project.memberships.each {|m| m.destroy unless m.user == user}
216 news.project.memberships.each {|m| m.destroy unless m.user == user}
217
217
218 user.pref.no_self_notified = false
218 user.pref.no_self_notified = false
219 user.pref.save
219 user.pref.save
220 User.current = user
220 User.current = user
221 Mailer.news_added(news.reload).deliver
221 Mailer.news_added(news.reload).deliver
222 assert_equal 1, last_email.bcc.size
222 assert_equal 1, last_email.bcc.size
223
223
224 # nobody to notify
224 # nobody to notify
225 user.pref.no_self_notified = true
225 user.pref.no_self_notified = true
226 user.pref.save
226 user.pref.save
227 User.current = user
227 User.current = user
228 ActionMailer::Base.deliveries.clear
228 ActionMailer::Base.deliveries.clear
229 Mailer.news_added(news.reload).deliver
229 Mailer.news_added(news.reload).deliver
230 assert ActionMailer::Base.deliveries.empty?
230 assert ActionMailer::Base.deliveries.empty?
231 end
231 end
232
232
233 def test_issue_add_message_id
233 def test_issue_add_message_id
234 issue = Issue.find(1)
234 issue = Issue.find(1)
235 Mailer.issue_add(issue).deliver
235 Mailer.issue_add(issue).deliver
236 mail = last_email
236 mail = last_email
237 assert_equal Mailer.message_id_for(issue), mail.message_id
237 assert_equal Mailer.message_id_for(issue), mail.message_id
238 assert_nil mail.references
238 assert_nil mail.references
239 end
239 end
240
240
241 def test_issue_edit_message_id
241 def test_issue_edit_message_id
242 journal = Journal.find(1)
242 journal = Journal.find(1)
243 Mailer.issue_edit(journal).deliver
243 Mailer.issue_edit(journal).deliver
244 mail = last_email
244 mail = last_email
245 assert_equal Mailer.message_id_for(journal), mail.message_id
245 assert_equal Mailer.message_id_for(journal), mail.message_id
246 assert_include Mailer.message_id_for(journal.issue), mail.references
246 assert_include Mailer.message_id_for(journal.issue), mail.references
247 assert_select_email do
247 assert_select_email do
248 # link to the update
248 # link to the update
249 assert_select "a[href=?]",
249 assert_select "a[href=?]",
250 "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
250 "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
251 end
251 end
252 end
252 end
253
253
254 def test_message_posted_message_id
254 def test_message_posted_message_id
255 message = Message.find(1)
255 message = Message.find(1)
256 Mailer.message_posted(message).deliver
256 Mailer.message_posted(message).deliver
257 mail = last_email
257 mail = last_email
258 assert_equal Mailer.message_id_for(message), mail.message_id
258 assert_equal Mailer.message_id_for(message), mail.message_id
259 assert_nil mail.references
259 assert_nil mail.references
260 assert_select_email do
260 assert_select_email do
261 # link to the message
261 # link to the message
262 assert_select "a[href=?]",
262 assert_select "a[href=?]",
263 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
263 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
264 :text => message.subject
264 :text => message.subject
265 end
265 end
266 end
266 end
267
267
268 def test_reply_posted_message_id
268 def test_reply_posted_message_id
269 message = Message.find(3)
269 message = Message.find(3)
270 Mailer.message_posted(message).deliver
270 Mailer.message_posted(message).deliver
271 mail = last_email
271 mail = last_email
272 assert_equal Mailer.message_id_for(message), mail.message_id
272 assert_equal Mailer.message_id_for(message), mail.message_id
273 assert_include Mailer.message_id_for(message.parent), mail.references
273 assert_include Mailer.message_id_for(message.parent), mail.references
274 assert_select_email do
274 assert_select_email do
275 # link to the reply
275 # link to the reply
276 assert_select "a[href=?]",
276 assert_select "a[href=?]",
277 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
277 "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
278 :text => message.subject
278 :text => message.subject
279 end
279 end
280 end
280 end
281
281
282 test "#issue_add should notify project members" do
282 test "#issue_add should notify project members" do
283 issue = Issue.find(1)
283 issue = Issue.find(1)
284 assert Mailer.issue_add(issue).deliver
284 assert Mailer.issue_add(issue).deliver
285 assert last_email.bcc.include?('dlopper@somenet.foo')
285 assert last_email.bcc.include?('dlopper@somenet.foo')
286 end
286 end
287
287
288 test "#issue_add should not notify project members that are not allow to view the issue" do
288 test "#issue_add should not notify project members that are not allow to view the issue" do
289 issue = Issue.find(1)
289 issue = Issue.find(1)
290 Role.find(2).remove_permission!(:view_issues)
290 Role.find(2).remove_permission!(:view_issues)
291 assert Mailer.issue_add(issue).deliver
291 assert Mailer.issue_add(issue).deliver
292 assert !last_email.bcc.include?('dlopper@somenet.foo')
292 assert !last_email.bcc.include?('dlopper@somenet.foo')
293 end
293 end
294
294
295 test "#issue_add should notify issue watchers" do
295 test "#issue_add should notify issue watchers" do
296 issue = Issue.find(1)
296 issue = Issue.find(1)
297 user = User.find(9)
297 user = User.find(9)
298 # minimal email notification options
298 # minimal email notification options
299 user.pref.no_self_notified = '1'
299 user.pref.no_self_notified = '1'
300 user.pref.save
300 user.pref.save
301 user.mail_notification = false
301 user.mail_notification = false
302 user.save
302 user.save
303
303
304 Watcher.create!(:watchable => issue, :user => user)
304 Watcher.create!(:watchable => issue, :user => user)
305 assert Mailer.issue_add(issue).deliver
305 assert Mailer.issue_add(issue).deliver
306 assert last_email.bcc.include?(user.mail)
306 assert last_email.bcc.include?(user.mail)
307 end
307 end
308
308
309 test "#issue_add should not notify watchers not allowed to view the issue" do
309 test "#issue_add should not notify watchers not allowed to view the issue" do
310 issue = Issue.find(1)
310 issue = Issue.find(1)
311 user = User.find(9)
311 user = User.find(9)
312 Watcher.create!(:watchable => issue, :user => user)
312 Watcher.create!(:watchable => issue, :user => user)
313 Role.non_member.remove_permission!(:view_issues)
313 Role.non_member.remove_permission!(:view_issues)
314 assert Mailer.issue_add(issue).deliver
314 assert Mailer.issue_add(issue).deliver
315 assert !last_email.bcc.include?(user.mail)
315 assert !last_email.bcc.include?(user.mail)
316 end
316 end
317
317
318 # test mailer methods for each language
318 # test mailer methods for each language
319 def test_issue_add
319 def test_issue_add
320 issue = Issue.find(1)
320 issue = Issue.find(1)
321 valid_languages.each do |lang|
321 valid_languages.each do |lang|
322 Setting.default_language = lang.to_s
322 Setting.default_language = lang.to_s
323 assert Mailer.issue_add(issue).deliver
323 assert Mailer.issue_add(issue).deliver
324 end
324 end
325 end
325 end
326
326
327 def test_issue_edit
327 def test_issue_edit
328 journal = Journal.find(1)
328 journal = Journal.find(1)
329 valid_languages.each do |lang|
329 valid_languages.each do |lang|
330 Setting.default_language = lang.to_s
330 Setting.default_language = lang.to_s
331 assert Mailer.issue_edit(journal).deliver
331 assert Mailer.issue_edit(journal).deliver
332 end
332 end
333 end
333 end
334
334
335 def test_issue_edit_should_send_private_notes_to_users_with_permission_only
335 def test_issue_edit_should_send_private_notes_to_users_with_permission_only
336 journal = Journal.find(1)
336 journal = Journal.find(1)
337 journal.private_notes = true
337 journal.private_notes = true
338 journal.save!
338 journal.save!
339
339
340 Role.find(2).add_permission! :view_private_notes
340 Role.find(2).add_permission! :view_private_notes
341 Mailer.issue_edit(journal).deliver
341 Mailer.issue_edit(journal).deliver
342 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
342 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
343
343
344 Role.find(2).remove_permission! :view_private_notes
344 Role.find(2).remove_permission! :view_private_notes
345 Mailer.issue_edit(journal).deliver
345 Mailer.issue_edit(journal).deliver
346 assert_equal %w(jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
346 assert_equal %w(jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
347 end
347 end
348
348
349 def test_issue_edit_should_send_private_notes_to_watchers_with_permission_only
349 def test_issue_edit_should_send_private_notes_to_watchers_with_permission_only
350 Issue.find(1).set_watcher(User.find_by_login('someone'))
350 Issue.find(1).set_watcher(User.find_by_login('someone'))
351 journal = Journal.find(1)
351 journal = Journal.find(1)
352 journal.private_notes = true
352 journal.private_notes = true
353 journal.save!
353 journal.save!
354
354
355 Role.non_member.add_permission! :view_private_notes
355 Role.non_member.add_permission! :view_private_notes
356 Mailer.issue_edit(journal).deliver
356 Mailer.issue_edit(journal).deliver
357 assert_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
357 assert_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
358
358
359 Role.non_member.remove_permission! :view_private_notes
359 Role.non_member.remove_permission! :view_private_notes
360 Mailer.issue_edit(journal).deliver
360 Mailer.issue_edit(journal).deliver
361 assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
361 assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
362 end
362 end
363
363
364 def test_issue_edit_should_mark_private_notes
364 def test_issue_edit_should_mark_private_notes
365 journal = Journal.find(2)
365 journal = Journal.find(2)
366 journal.private_notes = true
366 journal.private_notes = true
367 journal.save!
367 journal.save!
368
368
369 with_settings :default_language => 'en' do
369 with_settings :default_language => 'en' do
370 Mailer.issue_edit(journal).deliver
370 Mailer.issue_edit(journal).deliver
371 end
371 end
372 assert_mail_body_match '(Private notes)', last_email
372 assert_mail_body_match '(Private notes)', last_email
373 end
373 end
374
374
375 def test_document_added
375 def test_document_added
376 document = Document.find(1)
376 document = Document.find(1)
377 valid_languages.each do |lang|
377 valid_languages.each do |lang|
378 Setting.default_language = lang.to_s
378 Setting.default_language = lang.to_s
379 assert Mailer.document_added(document).deliver
379 assert Mailer.document_added(document).deliver
380 end
380 end
381 end
381 end
382
382
383 def test_attachments_added
383 def test_attachments_added
384 attachements = [ Attachment.find_by_container_type('Document') ]
384 attachements = [ Attachment.find_by_container_type('Document') ]
385 valid_languages.each do |lang|
385 valid_languages.each do |lang|
386 Setting.default_language = lang.to_s
386 Setting.default_language = lang.to_s
387 assert Mailer.attachments_added(attachements).deliver
387 assert Mailer.attachments_added(attachements).deliver
388 end
388 end
389 end
389 end
390
390
391 def test_version_file_added
391 def test_version_file_added
392 attachements = [ Attachment.find_by_container_type('Version') ]
392 attachements = [ Attachment.find_by_container_type('Version') ]
393 assert Mailer.attachments_added(attachements).deliver
393 assert Mailer.attachments_added(attachements).deliver
394 assert_not_nil last_email.bcc
394 assert_not_nil last_email.bcc
395 assert last_email.bcc.any?
395 assert last_email.bcc.any?
396 assert_select_email do
396 assert_select_email do
397 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
397 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
398 end
398 end
399 end
399 end
400
400
401 def test_project_file_added
401 def test_project_file_added
402 attachements = [ Attachment.find_by_container_type('Project') ]
402 attachements = [ Attachment.find_by_container_type('Project') ]
403 assert Mailer.attachments_added(attachements).deliver
403 assert Mailer.attachments_added(attachements).deliver
404 assert_not_nil last_email.bcc
404 assert_not_nil last_email.bcc
405 assert last_email.bcc.any?
405 assert last_email.bcc.any?
406 assert_select_email do
406 assert_select_email do
407 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
407 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
408 end
408 end
409 end
409 end
410
410
411 def test_news_added
411 def test_news_added
412 news = News.first
412 news = News.first
413 valid_languages.each do |lang|
413 valid_languages.each do |lang|
414 Setting.default_language = lang.to_s
414 Setting.default_language = lang.to_s
415 assert Mailer.news_added(news).deliver
415 assert Mailer.news_added(news).deliver
416 end
416 end
417 end
417 end
418
418
419 def test_news_comment_added
419 def test_news_comment_added
420 comment = Comment.find(2)
420 comment = Comment.find(2)
421 valid_languages.each do |lang|
421 valid_languages.each do |lang|
422 Setting.default_language = lang.to_s
422 Setting.default_language = lang.to_s
423 assert Mailer.news_comment_added(comment).deliver
423 assert Mailer.news_comment_added(comment).deliver
424 end
424 end
425 end
425 end
426
426
427 def test_message_posted
427 def test_message_posted
428 message = Message.first
428 message = Message.first
429 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
429 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
430 recipients = recipients.compact.uniq
430 recipients = recipients.compact.uniq
431 valid_languages.each do |lang|
431 valid_languages.each do |lang|
432 Setting.default_language = lang.to_s
432 Setting.default_language = lang.to_s
433 assert Mailer.message_posted(message).deliver
433 assert Mailer.message_posted(message).deliver
434 end
434 end
435 end
435 end
436
436
437 def test_wiki_content_added
437 def test_wiki_content_added
438 content = WikiContent.find(1)
438 content = WikiContent.find(1)
439 valid_languages.each do |lang|
439 valid_languages.each do |lang|
440 Setting.default_language = lang.to_s
440 Setting.default_language = lang.to_s
441 assert_difference 'ActionMailer::Base.deliveries.size' do
441 assert_difference 'ActionMailer::Base.deliveries.size' do
442 assert Mailer.wiki_content_added(content).deliver
442 assert Mailer.wiki_content_added(content).deliver
443 assert_select_email do
443 assert_select_email do
444 assert_select 'a[href=?]',
444 assert_select 'a[href=?]',
445 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
445 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
446 :text => 'CookBook documentation'
446 :text => 'CookBook documentation'
447 end
447 end
448 end
448 end
449 end
449 end
450 end
450 end
451
451
452 def test_wiki_content_updated
452 def test_wiki_content_updated
453 content = WikiContent.find(1)
453 content = WikiContent.find(1)
454 valid_languages.each do |lang|
454 valid_languages.each do |lang|
455 Setting.default_language = lang.to_s
455 Setting.default_language = lang.to_s
456 assert_difference 'ActionMailer::Base.deliveries.size' do
456 assert_difference 'ActionMailer::Base.deliveries.size' do
457 assert Mailer.wiki_content_updated(content).deliver
457 assert Mailer.wiki_content_updated(content).deliver
458 assert_select_email do
458 assert_select_email do
459 assert_select 'a[href=?]',
459 assert_select 'a[href=?]',
460 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
460 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
461 :text => 'CookBook documentation'
461 :text => 'CookBook documentation'
462 end
462 end
463 end
463 end
464 end
464 end
465 end
465 end
466
466
467 def test_account_information
467 def test_account_information
468 user = User.find(2)
468 user = User.find(2)
469 valid_languages.each do |lang|
469 valid_languages.each do |lang|
470 user.update_attribute :language, lang.to_s
470 user.update_attribute :language, lang.to_s
471 user.reload
471 user.reload
472 assert Mailer.account_information(user, 'pAsswORd').deliver
472 assert Mailer.account_information(user, 'pAsswORd').deliver
473 end
473 end
474 end
474 end
475
475
476 def test_lost_password
476 def test_lost_password
477 token = Token.find(2)
477 token = Token.find(2)
478 valid_languages.each do |lang|
478 valid_languages.each do |lang|
479 token.user.update_attribute :language, lang.to_s
479 token.user.update_attribute :language, lang.to_s
480 token.reload
480 token.reload
481 assert Mailer.lost_password(token).deliver
481 assert Mailer.lost_password(token).deliver
482 end
482 end
483 end
483 end
484
484
485 def test_register
485 def test_register
486 token = Token.find(1)
486 token = Token.find(1)
487 Setting.host_name = 'redmine.foo'
487 Setting.host_name = 'redmine.foo'
488 Setting.protocol = 'https'
488 Setting.protocol = 'https'
489
489
490 valid_languages.each do |lang|
490 valid_languages.each do |lang|
491 token.user.update_attribute :language, lang.to_s
491 token.user.update_attribute :language, lang.to_s
492 token.reload
492 token.reload
493 ActionMailer::Base.deliveries.clear
493 ActionMailer::Base.deliveries.clear
494 assert Mailer.register(token).deliver
494 assert Mailer.register(token).deliver
495 mail = last_email
495 mail = last_email
496 assert_select_email do
496 assert_select_email do
497 assert_select "a[href=?]",
497 assert_select "a[href=?]",
498 "https://redmine.foo/account/activate?token=#{token.value}",
498 "https://redmine.foo/account/activate?token=#{token.value}",
499 :text => "https://redmine.foo/account/activate?token=#{token.value}"
499 :text => "https://redmine.foo/account/activate?token=#{token.value}"
500 end
500 end
501 end
501 end
502 end
502 end
503
503
504 def test_test
504 def test_test
505 user = User.find(1)
505 user = User.find(1)
506 valid_languages.each do |lang|
506 valid_languages.each do |lang|
507 user.update_attribute :language, lang.to_s
507 user.update_attribute :language, lang.to_s
508 assert Mailer.test_email(user).deliver
508 assert Mailer.test_email(user).deliver
509 end
509 end
510 end
510 end
511
511
512 def test_reminders
512 def test_reminders
513 Mailer.reminders(:days => 42)
513 Mailer.reminders(:days => 42)
514 assert_equal 1, ActionMailer::Base.deliveries.size
514 assert_equal 1, ActionMailer::Base.deliveries.size
515 mail = last_email
515 mail = last_email
516 assert mail.bcc.include?('dlopper@somenet.foo')
516 assert mail.bcc.include?('dlopper@somenet.foo')
517 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
517 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
518 assert_equal '1 issue(s) due in the next 42 days', mail.subject
518 assert_equal '1 issue(s) due in the next 42 days', mail.subject
519 end
519 end
520
520
521 def test_reminders_should_not_include_closed_issues
521 def test_reminders_should_not_include_closed_issues
522 with_settings :default_language => 'en' do
522 with_settings :default_language => 'en' do
523 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
523 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
524 :subject => 'Closed issue', :assigned_to_id => 3,
524 :subject => 'Closed issue', :assigned_to_id => 3,
525 :due_date => 5.days.from_now,
525 :due_date => 5.days.from_now,
526 :author_id => 2)
526 :author_id => 2)
527 ActionMailer::Base.deliveries.clear
527 ActionMailer::Base.deliveries.clear
528
528
529 Mailer.reminders(:days => 42)
529 Mailer.reminders(:days => 42)
530 assert_equal 1, ActionMailer::Base.deliveries.size
530 assert_equal 1, ActionMailer::Base.deliveries.size
531 mail = last_email
531 mail = last_email
532 assert mail.bcc.include?('dlopper@somenet.foo')
532 assert mail.bcc.include?('dlopper@somenet.foo')
533 assert_mail_body_no_match 'Closed issue', mail
533 assert_mail_body_no_match 'Closed issue', mail
534 end
534 end
535 end
535 end
536
536
537 def test_reminders_for_users
537 def test_reminders_for_users
538 Mailer.reminders(:days => 42, :users => ['5'])
538 Mailer.reminders(:days => 42, :users => ['5'])
539 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
539 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
540 Mailer.reminders(:days => 42, :users => ['3'])
540 Mailer.reminders(:days => 42, :users => ['3'])
541 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
541 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
542 mail = last_email
542 mail = last_email
543 assert mail.bcc.include?('dlopper@somenet.foo')
543 assert mail.bcc.include?('dlopper@somenet.foo')
544 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
544 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
545 end
545 end
546
546
547 def test_reminder_should_include_issues_assigned_to_groups
547 def test_reminder_should_include_issues_assigned_to_groups
548 with_settings :default_language => 'en' do
548 with_settings :default_language => 'en' do
549 group = Group.generate!
549 group = Group.generate!
550 group.users << User.find(2)
550 group.users << User.find(2)
551 group.users << User.find(3)
551 group.users << User.find(3)
552
552
553 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
553 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
554 :subject => 'Assigned to group', :assigned_to => group,
554 :subject => 'Assigned to group', :assigned_to => group,
555 :due_date => 5.days.from_now,
555 :due_date => 5.days.from_now,
556 :author_id => 2)
556 :author_id => 2)
557 ActionMailer::Base.deliveries.clear
557 ActionMailer::Base.deliveries.clear
558
558
559 Mailer.reminders(:days => 7)
559 Mailer.reminders(:days => 7)
560 assert_equal 2, ActionMailer::Base.deliveries.size
560 assert_equal 2, ActionMailer::Base.deliveries.size
561 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
561 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
562 ActionMailer::Base.deliveries.each do |mail|
562 ActionMailer::Base.deliveries.each do |mail|
563 assert_mail_body_match 'Assigned to group', mail
563 assert_mail_body_match 'Assigned to group', mail
564 end
564 end
565 end
565 end
566 end
566 end
567
567
568 def test_mailer_should_not_change_locale
568 def test_mailer_should_not_change_locale
569 Setting.default_language = 'en'
569 Setting.default_language = 'en'
570 # Set current language to italian
570 # Set current language to italian
571 set_language_if_valid 'it'
571 set_language_if_valid 'it'
572 # Send an email to a french user
572 # Send an email to a french user
573 user = User.find(1)
573 user = User.find(1)
574 user.language = 'fr'
574 user.language = 'fr'
575 Mailer.account_activated(user).deliver
575 Mailer.account_activated(user).deliver
576 mail = last_email
576 mail = last_email
577 assert_mail_body_match 'Votre compte', mail
577 assert_mail_body_match 'Votre compte', mail
578
578
579 assert_equal :it, current_language
579 assert_equal :it, current_language
580 end
580 end
581
581
582 def test_with_deliveries_off
582 def test_with_deliveries_off
583 Mailer.with_deliveries false do
583 Mailer.with_deliveries false do
584 Mailer.test_email(User.find(1)).deliver
584 Mailer.test_email(User.find(1)).deliver
585 end
585 end
586 assert ActionMailer::Base.deliveries.empty?
586 assert ActionMailer::Base.deliveries.empty?
587 # should restore perform_deliveries
587 # should restore perform_deliveries
588 assert ActionMailer::Base.perform_deliveries
588 assert ActionMailer::Base.perform_deliveries
589 end
589 end
590
590
591 def test_layout_should_include_the_emails_header
591 def test_layout_should_include_the_emails_header
592 with_settings :emails_header => "*Header content*" do
592 with_settings :emails_header => "*Header content*" do
593 with_settings :plain_text_mail => 0 do
593 with_settings :plain_text_mail => 0 do
594 assert Mailer.test_email(User.find(1)).deliver
594 assert Mailer.test_email(User.find(1)).deliver
595 assert_select_email do
595 assert_select_email do
596 assert_select ".header" do
596 assert_select ".header" do
597 assert_select "strong", :text => "Header content"
597 assert_select "strong", :text => "Header content"
598 end
598 end
599 end
599 end
600 end
600 end
601 with_settings :plain_text_mail => 1 do
601 with_settings :plain_text_mail => 1 do
602 assert Mailer.test_email(User.find(1)).deliver
602 assert Mailer.test_email(User.find(1)).deliver
603 mail = last_email
603 mail = last_email
604 assert_not_nil mail
604 assert_not_nil mail
605 assert_include "*Header content*", mail.body.decoded
605 assert_include "*Header content*", mail.body.decoded
606 end
606 end
607 end
607 end
608 end
608 end
609
609
610 def test_layout_should_not_include_empty_emails_header
610 def test_layout_should_not_include_empty_emails_header
611 with_settings :emails_header => "", :plain_text_mail => 0 do
611 with_settings :emails_header => "", :plain_text_mail => 0 do
612 assert Mailer.test_email(User.find(1)).deliver
612 assert Mailer.test_email(User.find(1)).deliver
613 assert_select_email do
613 assert_select_email do
614 assert_select ".header", false
614 assert_select ".header", false
615 end
615 end
616 end
616 end
617 end
617 end
618
618
619 def test_layout_should_include_the_emails_footer
619 def test_layout_should_include_the_emails_footer
620 with_settings :emails_footer => "*Footer content*" do
620 with_settings :emails_footer => "*Footer content*" do
621 with_settings :plain_text_mail => 0 do
621 with_settings :plain_text_mail => 0 do
622 assert Mailer.test_email(User.find(1)).deliver
622 assert Mailer.test_email(User.find(1)).deliver
623 assert_select_email do
623 assert_select_email do
624 assert_select ".footer" do
624 assert_select ".footer" do
625 assert_select "strong", :text => "Footer content"
625 assert_select "strong", :text => "Footer content"
626 end
626 end
627 end
627 end
628 end
628 end
629 with_settings :plain_text_mail => 1 do
629 with_settings :plain_text_mail => 1 do
630 assert Mailer.test_email(User.find(1)).deliver
630 assert Mailer.test_email(User.find(1)).deliver
631 mail = last_email
631 mail = last_email
632 assert_not_nil mail
632 assert_not_nil mail
633 assert_include "\n-- \n", mail.body.decoded
633 assert_include "\n-- \n", mail.body.decoded
634 assert_include "*Footer content*", mail.body.decoded
634 assert_include "*Footer content*", mail.body.decoded
635 end
635 end
636 end
636 end
637 end
637 end
638
638
639 def test_layout_should_not_include_empty_emails_footer
639 def test_layout_should_not_include_empty_emails_footer
640 with_settings :emails_footer => "" do
640 with_settings :emails_footer => "" do
641 with_settings :plain_text_mail => 0 do
641 with_settings :plain_text_mail => 0 do
642 assert Mailer.test_email(User.find(1)).deliver
642 assert Mailer.test_email(User.find(1)).deliver
643 assert_select_email do
643 assert_select_email do
644 assert_select ".footer", false
644 assert_select ".footer", false
645 end
645 end
646 end
646 end
647 with_settings :plain_text_mail => 1 do
647 with_settings :plain_text_mail => 1 do
648 assert Mailer.test_email(User.find(1)).deliver
648 assert Mailer.test_email(User.find(1)).deliver
649 mail = last_email
649 mail = last_email
650 assert_not_nil mail
650 assert_not_nil mail
651 assert_not_include "\n-- \n", mail.body.decoded
651 assert_not_include "\n-- \n", mail.body.decoded
652 end
652 end
653 end
653 end
654 end
654 end
655
655
656 def test_should_escape_html_templates_only
656 def test_should_escape_html_templates_only
657 Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
657 Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
658 mail = last_email
658 mail = last_email
659 assert_equal 2, mail.parts.size
659 assert_equal 2, mail.parts.size
660 assert_include '<tag>', text_part.body.encoded
660 assert_include '<tag>', text_part.body.encoded
661 assert_include '&lt;tag&gt;', html_part.body.encoded
661 assert_include '&lt;tag&gt;', html_part.body.encoded
662 end
662 end
663
663
664 def test_should_raise_delivery_errors_when_raise_delivery_errors_is_true
665 mail = Mailer.test_email(User.find(1))
666 mail.delivery_method.stubs(:deliver!).raises(Exception.new("delivery error"))
667
668 ActionMailer::Base.raise_delivery_errors = true
669 assert_raise Exception, "delivery error" do
670 mail.deliver
671 end
672 ensure
673 ActionMailer::Base.raise_delivery_errors = false
674 end
675
676 def test_should_log_delivery_errors_when_raise_delivery_errors_is_false
677 mail = Mailer.test_email(User.find(1))
678 mail.delivery_method.stubs(:deliver!).raises(Exception.new("delivery error"))
679
680 Rails.logger.expects(:error).with("Email delivery error: delivery error")
681 ActionMailer::Base.raise_delivery_errors = false
682 assert_nothing_raised do
683 mail.deliver
684 end
685 end
686
664 private
687 private
665
688
666 def last_email
689 def last_email
667 mail = ActionMailer::Base.deliveries.last
690 mail = ActionMailer::Base.deliveries.last
668 assert_not_nil mail
691 assert_not_nil mail
669 mail
692 mail
670 end
693 end
671
694
672 def text_part
695 def text_part
673 last_email.parts.detect {|part| part.content_type.include?('text/plain')}
696 last_email.parts.detect {|part| part.content_type.include?('text/plain')}
674 end
697 end
675
698
676 def html_part
699 def html_part
677 last_email.parts.detect {|part| part.content_type.include?('text/html')}
700 last_email.parts.detect {|part| part.content_type.include?('text/html')}
678 end
701 end
679 end
702 end
General Comments 0
You need to be logged in to leave comments. Login now