##// END OF EJS Templates
Fixed that the reminder email excludes issues assigned to groups (#11723)....
Jean-Philippe Lang -
r10152:197a14a82e3e
parent child
Show More
@@ -1,465 +1,474
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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 = issue.recipients
65 recipients = issue.recipients
66 # Watchers in cc
66 # Watchers in cc
67 cc = issue.watcher_recipients - recipients
67 cc = issue.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.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
255 recipients = User.active.find(:all, :conditions => {:admin => true}).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 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.scoped(:conditions => ["#{Issue.table_name}.assigned_to_id IS NOT NULL" +
337 scope = Issue.open.scoped(:conditions => ["#{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.scoped(:conditions => {:assigned_to_id => user_ids}) if user_ids.present?
341 scope = scope.scoped(:conditions => {:assigned_to_id => user_ids}) if user_ids.present?
342 scope = scope.scoped(:conditions => {:project_id => project.id}) if project
342 scope = scope.scoped(:conditions => {:project_id => project.id}) if project
343 scope = scope.scoped(:conditions => {:tracker_id => tracker.id}) if tracker
343 scope = scope.scoped(:conditions => {:tracker_id => tracker.id}) if tracker
344
344
345 issues_by_assignee = scope.all(:include => [:status, :assigned_to, :project, :tracker]).group_by(&:assigned_to)
345 issues_by_assignee = scope.all(:include => [:status, :assigned_to, :project, :tracker]).group_by(&:assigned_to)
346 issues_by_assignee.keys.each do |assignee|
347 if assignee.is_a?(Group)
348 assignee.users.each do |user|
349 issues_by_assignee[user] ||= []
350 issues_by_assignee[user] += issues_by_assignee[assignee]
351 end
352 end
353 end
354
346 issues_by_assignee.each do |assignee, issues|
355 issues_by_assignee.each do |assignee, issues|
347 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?
348 end
357 end
349 end
358 end
350
359
351 # Activates/desactivates email deliveries during +block+
360 # Activates/desactivates email deliveries during +block+
352 def self.with_deliveries(enabled = true, &block)
361 def self.with_deliveries(enabled = true, &block)
353 was_enabled = ActionMailer::Base.perform_deliveries
362 was_enabled = ActionMailer::Base.perform_deliveries
354 ActionMailer::Base.perform_deliveries = !!enabled
363 ActionMailer::Base.perform_deliveries = !!enabled
355 yield
364 yield
356 ensure
365 ensure
357 ActionMailer::Base.perform_deliveries = was_enabled
366 ActionMailer::Base.perform_deliveries = was_enabled
358 end
367 end
359
368
360 # Sends emails synchronously in the given block
369 # Sends emails synchronously in the given block
361 def self.with_synched_deliveries(&block)
370 def self.with_synched_deliveries(&block)
362 saved_method = ActionMailer::Base.delivery_method
371 saved_method = ActionMailer::Base.delivery_method
363 if m = saved_method.to_s.match(%r{^async_(.+)$})
372 if m = saved_method.to_s.match(%r{^async_(.+)$})
364 synched_method = m[1]
373 synched_method = m[1]
365 ActionMailer::Base.delivery_method = synched_method.to_sym
374 ActionMailer::Base.delivery_method = synched_method.to_sym
366 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")
367 end
376 end
368 yield
377 yield
369 ensure
378 ensure
370 ActionMailer::Base.delivery_method = saved_method
379 ActionMailer::Base.delivery_method = saved_method
371 end
380 end
372
381
373 def mail(headers={})
382 def mail(headers={})
374 headers.merge! 'X-Mailer' => 'Redmine',
383 headers.merge! 'X-Mailer' => 'Redmine',
375 'X-Redmine-Host' => Setting.host_name,
384 'X-Redmine-Host' => Setting.host_name,
376 'X-Redmine-Site' => Setting.app_title,
385 'X-Redmine-Site' => Setting.app_title,
377 'X-Auto-Response-Suppress' => 'OOF',
386 'X-Auto-Response-Suppress' => 'OOF',
378 'Auto-Submitted' => 'auto-generated',
387 'Auto-Submitted' => 'auto-generated',
379 'From' => Setting.mail_from,
388 'From' => Setting.mail_from,
380 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
389 'List-Id' => "<#{Setting.mail_from.to_s.gsub('@', '.')}>"
381
390
382 # Removes the author from the recipients and cc
391 # Removes the author from the recipients and cc
383 # if he doesn't want to receive notifications about what he does
392 # if he doesn't want to receive notifications about what he does
384 if @author && @author.logged? && @author.pref[:no_self_notified]
393 if @author && @author.logged? && @author.pref[:no_self_notified]
385 headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
394 headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
386 headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
395 headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
387 end
396 end
388
397
389 if @author && @author.logged?
398 if @author && @author.logged?
390 redmine_headers 'Sender' => @author.login
399 redmine_headers 'Sender' => @author.login
391 end
400 end
392
401
393 # Blind carbon copy recipients
402 # Blind carbon copy recipients
394 if Setting.bcc_recipients?
403 if Setting.bcc_recipients?
395 headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
404 headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
396 headers[:to] = nil
405 headers[:to] = nil
397 headers[:cc] = nil
406 headers[:cc] = nil
398 end
407 end
399
408
400 if @message_id_object
409 if @message_id_object
401 headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
410 headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
402 end
411 end
403 if @references_objects
412 if @references_objects
404 headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
413 headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
405 end
414 end
406
415
407 super headers do |format|
416 super headers do |format|
408 format.text
417 format.text
409 format.html unless Setting.plain_text_mail?
418 format.html unless Setting.plain_text_mail?
410 end
419 end
411
420
412 set_language_if_valid @initial_language
421 set_language_if_valid @initial_language
413 end
422 end
414
423
415 def initialize(*args)
424 def initialize(*args)
416 @initial_language = current_language
425 @initial_language = current_language
417 set_language_if_valid Setting.default_language
426 set_language_if_valid Setting.default_language
418 super
427 super
419 end
428 end
420
429
421 def self.deliver_mail(mail)
430 def self.deliver_mail(mail)
422 return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
431 return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
423 super
432 super
424 end
433 end
425
434
426 def self.method_missing(method, *args, &block)
435 def self.method_missing(method, *args, &block)
427 if m = method.to_s.match(%r{^deliver_(.+)$})
436 if m = method.to_s.match(%r{^deliver_(.+)$})
428 ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
437 ActiveSupport::Deprecation.warn "Mailer.deliver_#{m[1]}(*args) is deprecated. Use Mailer.#{m[1]}(*args).deliver instead."
429 send(m[1], *args).deliver
438 send(m[1], *args).deliver
430 else
439 else
431 super
440 super
432 end
441 end
433 end
442 end
434
443
435 private
444 private
436
445
437 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
446 # Appends a Redmine header field (name is prepended with 'X-Redmine-')
438 def redmine_headers(h)
447 def redmine_headers(h)
439 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
448 h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
440 end
449 end
441
450
442 # Returns a predictable Message-Id for the given object
451 # Returns a predictable Message-Id for the given object
443 def self.message_id_for(object)
452 def self.message_id_for(object)
444 # id + timestamp should reduce the odds of a collision
453 # id + timestamp should reduce the odds of a collision
445 # as far as we don't send multiple emails for the same object
454 # as far as we don't send multiple emails for the same object
446 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
455 timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on)
447 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
456 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
448 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
457 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
449 host = "#{::Socket.gethostname}.redmine" if host.empty?
458 host = "#{::Socket.gethostname}.redmine" if host.empty?
450 "#{hash}@#{host}"
459 "#{hash}@#{host}"
451 end
460 end
452
461
453 def message_id(object)
462 def message_id(object)
454 @message_id_object = object
463 @message_id_object = object
455 end
464 end
456
465
457 def references(object)
466 def references(object)
458 @references_objects ||= []
467 @references_objects ||= []
459 @references_objects << object
468 @references_objects << object
460 end
469 end
461
470
462 def mylogger
471 def mylogger
463 Rails.logger
472 Rails.logger
464 end
473 end
465 end
474 end
@@ -1,43 +1,43
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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 desc <<-END_DESC
18 desc <<-END_DESC
19 Send reminders about issues due in the next days.
19 Send reminders about issues due in the next days.
20
20
21 Available options:
21 Available options:
22 * days => number of days to remind about (defaults to 7)
22 * days => number of days to remind about (defaults to 7)
23 * tracker => id of tracker (defaults to all trackers)
23 * tracker => id of tracker (defaults to all trackers)
24 * project => id or identifier of project (defaults to all projects)
24 * project => id or identifier of project (defaults to all projects)
25 * users => comma separated list of user ids who should be reminded
25 * users => comma separated list of user/group ids who should be reminded
26
26
27 Example:
27 Example:
28 rake redmine:send_reminders days=7 users="1,23, 56" RAILS_ENV="production"
28 rake redmine:send_reminders days=7 users="1,23, 56" RAILS_ENV="production"
29 END_DESC
29 END_DESC
30
30
31 namespace :redmine do
31 namespace :redmine do
32 task :send_reminders => :environment do
32 task :send_reminders => :environment do
33 options = {}
33 options = {}
34 options[:days] = ENV['days'].to_i if ENV['days']
34 options[:days] = ENV['days'].to_i if ENV['days']
35 options[:project] = ENV['project'] if ENV['project']
35 options[:project] = ENV['project'] if ENV['project']
36 options[:tracker] = ENV['tracker'].to_i if ENV['tracker']
36 options[:tracker] = ENV['tracker'].to_i if ENV['tracker']
37 options[:users] = (ENV['users'] || '').split(',').each(&:strip!)
37 options[:users] = (ENV['users'] || '').split(',').each(&:strip!)
38
38
39 Mailer.with_synched_deliveries do
39 Mailer.with_synched_deliveries do
40 Mailer.reminders(options)
40 Mailer.reminders(options)
41 end
41 end
42 end
42 end
43 end
43 end
@@ -1,568 +1,589
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang
2 # Copyright (C) 2006-2012 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.find(:first)
213 news = News.find(: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 context("#issue_add") do
282 context("#issue_add") do
283 setup do
283 setup do
284 ActionMailer::Base.deliveries.clear
284 ActionMailer::Base.deliveries.clear
285 Setting.bcc_recipients = '1'
285 Setting.bcc_recipients = '1'
286 @issue = Issue.find(1)
286 @issue = Issue.find(1)
287 end
287 end
288
288
289 should "notify project members" do
289 should "notify project members" do
290 assert Mailer.issue_add(@issue).deliver
290 assert Mailer.issue_add(@issue).deliver
291 assert last_email.bcc.include?('dlopper@somenet.foo')
291 assert last_email.bcc.include?('dlopper@somenet.foo')
292 end
292 end
293
293
294 should "not notify project members that are not allow to view the issue" do
294 should "not notify project members that are not allow to view the issue" do
295 Role.find(2).remove_permission!(:view_issues)
295 Role.find(2).remove_permission!(:view_issues)
296 assert Mailer.issue_add(@issue).deliver
296 assert Mailer.issue_add(@issue).deliver
297 assert !last_email.bcc.include?('dlopper@somenet.foo')
297 assert !last_email.bcc.include?('dlopper@somenet.foo')
298 end
298 end
299
299
300 should "notify issue watchers" do
300 should "notify issue watchers" do
301 user = User.find(9)
301 user = User.find(9)
302 # minimal email notification options
302 # minimal email notification options
303 user.pref[:no_self_notified] = '1'
303 user.pref[:no_self_notified] = '1'
304 user.pref.save
304 user.pref.save
305 user.mail_notification = false
305 user.mail_notification = false
306 user.save
306 user.save
307
307
308 Watcher.create!(:watchable => @issue, :user => user)
308 Watcher.create!(:watchable => @issue, :user => user)
309 assert Mailer.issue_add(@issue).deliver
309 assert Mailer.issue_add(@issue).deliver
310 assert last_email.bcc.include?(user.mail)
310 assert last_email.bcc.include?(user.mail)
311 end
311 end
312
312
313 should "not notify watchers not allowed to view the issue" do
313 should "not notify watchers not allowed to view the issue" do
314 user = User.find(9)
314 user = User.find(9)
315 Watcher.create!(:watchable => @issue, :user => user)
315 Watcher.create!(:watchable => @issue, :user => user)
316 Role.non_member.remove_permission!(:view_issues)
316 Role.non_member.remove_permission!(:view_issues)
317 assert Mailer.issue_add(@issue).deliver
317 assert Mailer.issue_add(@issue).deliver
318 assert !last_email.bcc.include?(user.mail)
318 assert !last_email.bcc.include?(user.mail)
319 end
319 end
320 end
320 end
321
321
322 # test mailer methods for each language
322 # test mailer methods for each language
323 def test_issue_add
323 def test_issue_add
324 issue = Issue.find(1)
324 issue = Issue.find(1)
325 valid_languages.each do |lang|
325 valid_languages.each do |lang|
326 Setting.default_language = lang.to_s
326 Setting.default_language = lang.to_s
327 assert Mailer.issue_add(issue).deliver
327 assert Mailer.issue_add(issue).deliver
328 end
328 end
329 end
329 end
330
330
331 def test_issue_edit
331 def test_issue_edit
332 journal = Journal.find(1)
332 journal = Journal.find(1)
333 valid_languages.each do |lang|
333 valid_languages.each do |lang|
334 Setting.default_language = lang.to_s
334 Setting.default_language = lang.to_s
335 assert Mailer.issue_edit(journal).deliver
335 assert Mailer.issue_edit(journal).deliver
336 end
336 end
337 end
337 end
338
338
339 def test_document_added
339 def test_document_added
340 document = Document.find(1)
340 document = Document.find(1)
341 valid_languages.each do |lang|
341 valid_languages.each do |lang|
342 Setting.default_language = lang.to_s
342 Setting.default_language = lang.to_s
343 assert Mailer.document_added(document).deliver
343 assert Mailer.document_added(document).deliver
344 end
344 end
345 end
345 end
346
346
347 def test_attachments_added
347 def test_attachments_added
348 attachements = [ Attachment.find_by_container_type('Document') ]
348 attachements = [ Attachment.find_by_container_type('Document') ]
349 valid_languages.each do |lang|
349 valid_languages.each do |lang|
350 Setting.default_language = lang.to_s
350 Setting.default_language = lang.to_s
351 assert Mailer.attachments_added(attachements).deliver
351 assert Mailer.attachments_added(attachements).deliver
352 end
352 end
353 end
353 end
354
354
355 def test_version_file_added
355 def test_version_file_added
356 attachements = [ Attachment.find_by_container_type('Version') ]
356 attachements = [ Attachment.find_by_container_type('Version') ]
357 assert Mailer.attachments_added(attachements).deliver
357 assert Mailer.attachments_added(attachements).deliver
358 assert_not_nil last_email.bcc
358 assert_not_nil last_email.bcc
359 assert last_email.bcc.any?
359 assert last_email.bcc.any?
360 assert_select_email do
360 assert_select_email do
361 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
361 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
362 end
362 end
363 end
363 end
364
364
365 def test_project_file_added
365 def test_project_file_added
366 attachements = [ Attachment.find_by_container_type('Project') ]
366 attachements = [ Attachment.find_by_container_type('Project') ]
367 assert Mailer.attachments_added(attachements).deliver
367 assert Mailer.attachments_added(attachements).deliver
368 assert_not_nil last_email.bcc
368 assert_not_nil last_email.bcc
369 assert last_email.bcc.any?
369 assert last_email.bcc.any?
370 assert_select_email do
370 assert_select_email do
371 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
371 assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
372 end
372 end
373 end
373 end
374
374
375 def test_news_added
375 def test_news_added
376 news = News.find(:first)
376 news = News.find(:first)
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.news_added(news).deliver
379 assert Mailer.news_added(news).deliver
380 end
380 end
381 end
381 end
382
382
383 def test_news_comment_added
383 def test_news_comment_added
384 comment = Comment.find(2)
384 comment = Comment.find(2)
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.news_comment_added(comment).deliver
387 assert Mailer.news_comment_added(comment).deliver
388 end
388 end
389 end
389 end
390
390
391 def test_message_posted
391 def test_message_posted
392 message = Message.find(:first)
392 message = Message.find(:first)
393 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
393 recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
394 recipients = recipients.compact.uniq
394 recipients = recipients.compact.uniq
395 valid_languages.each do |lang|
395 valid_languages.each do |lang|
396 Setting.default_language = lang.to_s
396 Setting.default_language = lang.to_s
397 assert Mailer.message_posted(message).deliver
397 assert Mailer.message_posted(message).deliver
398 end
398 end
399 end
399 end
400
400
401 def test_wiki_content_added
401 def test_wiki_content_added
402 content = WikiContent.find(1)
402 content = WikiContent.find(1)
403 valid_languages.each do |lang|
403 valid_languages.each do |lang|
404 Setting.default_language = lang.to_s
404 Setting.default_language = lang.to_s
405 assert_difference 'ActionMailer::Base.deliveries.size' do
405 assert_difference 'ActionMailer::Base.deliveries.size' do
406 assert Mailer.wiki_content_added(content).deliver
406 assert Mailer.wiki_content_added(content).deliver
407 assert_select_email do
407 assert_select_email do
408 assert_select 'a[href=?]',
408 assert_select 'a[href=?]',
409 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
409 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
410 :text => 'CookBook documentation'
410 :text => 'CookBook documentation'
411 end
411 end
412 end
412 end
413 end
413 end
414 end
414 end
415
415
416 def test_wiki_content_updated
416 def test_wiki_content_updated
417 content = WikiContent.find(1)
417 content = WikiContent.find(1)
418 valid_languages.each do |lang|
418 valid_languages.each do |lang|
419 Setting.default_language = lang.to_s
419 Setting.default_language = lang.to_s
420 assert_difference 'ActionMailer::Base.deliveries.size' do
420 assert_difference 'ActionMailer::Base.deliveries.size' do
421 assert Mailer.wiki_content_updated(content).deliver
421 assert Mailer.wiki_content_updated(content).deliver
422 assert_select_email do
422 assert_select_email do
423 assert_select 'a[href=?]',
423 assert_select 'a[href=?]',
424 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
424 'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
425 :text => 'CookBook documentation'
425 :text => 'CookBook documentation'
426 end
426 end
427 end
427 end
428 end
428 end
429 end
429 end
430
430
431 def test_account_information
431 def test_account_information
432 user = User.find(2)
432 user = User.find(2)
433 valid_languages.each do |lang|
433 valid_languages.each do |lang|
434 user.update_attribute :language, lang.to_s
434 user.update_attribute :language, lang.to_s
435 user.reload
435 user.reload
436 assert Mailer.account_information(user, 'pAsswORd').deliver
436 assert Mailer.account_information(user, 'pAsswORd').deliver
437 end
437 end
438 end
438 end
439
439
440 def test_lost_password
440 def test_lost_password
441 token = Token.find(2)
441 token = Token.find(2)
442 valid_languages.each do |lang|
442 valid_languages.each do |lang|
443 token.user.update_attribute :language, lang.to_s
443 token.user.update_attribute :language, lang.to_s
444 token.reload
444 token.reload
445 assert Mailer.lost_password(token).deliver
445 assert Mailer.lost_password(token).deliver
446 end
446 end
447 end
447 end
448
448
449 def test_register
449 def test_register
450 token = Token.find(1)
450 token = Token.find(1)
451 Setting.host_name = 'redmine.foo'
451 Setting.host_name = 'redmine.foo'
452 Setting.protocol = 'https'
452 Setting.protocol = 'https'
453
453
454 valid_languages.each do |lang|
454 valid_languages.each do |lang|
455 token.user.update_attribute :language, lang.to_s
455 token.user.update_attribute :language, lang.to_s
456 token.reload
456 token.reload
457 ActionMailer::Base.deliveries.clear
457 ActionMailer::Base.deliveries.clear
458 assert Mailer.register(token).deliver
458 assert Mailer.register(token).deliver
459 mail = last_email
459 mail = last_email
460 assert_select_email do
460 assert_select_email do
461 assert_select "a[href=?]",
461 assert_select "a[href=?]",
462 "https://redmine.foo/account/activate?token=#{token.value}",
462 "https://redmine.foo/account/activate?token=#{token.value}",
463 :text => "https://redmine.foo/account/activate?token=#{token.value}"
463 :text => "https://redmine.foo/account/activate?token=#{token.value}"
464 end
464 end
465 end
465 end
466 end
466 end
467
467
468 def test_test
468 def test_test
469 user = User.find(1)
469 user = User.find(1)
470 valid_languages.each do |lang|
470 valid_languages.each do |lang|
471 user.update_attribute :language, lang.to_s
471 user.update_attribute :language, lang.to_s
472 assert Mailer.test_email(user).deliver
472 assert Mailer.test_email(user).deliver
473 end
473 end
474 end
474 end
475
475
476 def test_reminders
476 def test_reminders
477 Mailer.reminders(:days => 42)
477 Mailer.reminders(:days => 42)
478 assert_equal 1, ActionMailer::Base.deliveries.size
478 assert_equal 1, ActionMailer::Base.deliveries.size
479 mail = last_email
479 mail = last_email
480 assert mail.bcc.include?('dlopper@somenet.foo')
480 assert mail.bcc.include?('dlopper@somenet.foo')
481 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
481 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
482 assert_equal '1 issue(s) due in the next 42 days', mail.subject
482 assert_equal '1 issue(s) due in the next 42 days', mail.subject
483 end
483 end
484
484
485 def test_reminders_should_not_include_closed_issues
485 def test_reminders_should_not_include_closed_issues
486 with_settings :default_language => 'en' do
486 with_settings :default_language => 'en' do
487 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
487 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
488 :subject => 'Closed issue', :assigned_to_id => 3,
488 :subject => 'Closed issue', :assigned_to_id => 3,
489 :due_date => 5.days.from_now,
489 :due_date => 5.days.from_now,
490 :author_id => 2)
490 :author_id => 2)
491 ActionMailer::Base.deliveries.clear
491 ActionMailer::Base.deliveries.clear
492
492
493 Mailer.reminders(:days => 42)
493 Mailer.reminders(:days => 42)
494 assert_equal 1, ActionMailer::Base.deliveries.size
494 assert_equal 1, ActionMailer::Base.deliveries.size
495 mail = last_email
495 mail = last_email
496 assert mail.bcc.include?('dlopper@somenet.foo')
496 assert mail.bcc.include?('dlopper@somenet.foo')
497 assert_mail_body_no_match 'Closed issue', mail
497 assert_mail_body_no_match 'Closed issue', mail
498 end
498 end
499 end
499 end
500
500
501 def test_reminders_for_users
501 def test_reminders_for_users
502 Mailer.reminders(:days => 42, :users => ['5'])
502 Mailer.reminders(:days => 42, :users => ['5'])
503 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
503 assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
504 Mailer.reminders(:days => 42, :users => ['3'])
504 Mailer.reminders(:days => 42, :users => ['3'])
505 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
505 assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
506 mail = last_email
506 mail = last_email
507 assert mail.bcc.include?('dlopper@somenet.foo')
507 assert mail.bcc.include?('dlopper@somenet.foo')
508 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
508 assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
509 end
509 end
510
510
511 def test_reminder_should_include_issues_assigned_to_groups
512 with_settings :default_language => 'en' do
513 group = Group.generate!
514 group.users << User.find(2)
515 group.users << User.find(3)
516
517 Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
518 :subject => 'Assigned to group', :assigned_to => group,
519 :due_date => 5.days.from_now,
520 :author_id => 2)
521 ActionMailer::Base.deliveries.clear
522
523 Mailer.reminders(:days => 7)
524 assert_equal 2, ActionMailer::Base.deliveries.size
525 assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
526 ActionMailer::Base.deliveries.each do |mail|
527 assert_mail_body_match 'Assigned to group', mail
528 end
529 end
530 end
531
511 def test_mailer_should_not_change_locale
532 def test_mailer_should_not_change_locale
512 Setting.default_language = 'en'
533 Setting.default_language = 'en'
513 # Set current language to italian
534 # Set current language to italian
514 set_language_if_valid 'it'
535 set_language_if_valid 'it'
515 # Send an email to a french user
536 # Send an email to a french user
516 user = User.find(1)
537 user = User.find(1)
517 user.language = 'fr'
538 user.language = 'fr'
518 Mailer.account_activated(user).deliver
539 Mailer.account_activated(user).deliver
519 mail = last_email
540 mail = last_email
520 assert_mail_body_match 'Votre compte', mail
541 assert_mail_body_match 'Votre compte', mail
521
542
522 assert_equal :it, current_language
543 assert_equal :it, current_language
523 end
544 end
524
545
525 def test_with_deliveries_off
546 def test_with_deliveries_off
526 Mailer.with_deliveries false do
547 Mailer.with_deliveries false do
527 Mailer.test_email(User.find(1)).deliver
548 Mailer.test_email(User.find(1)).deliver
528 end
549 end
529 assert ActionMailer::Base.deliveries.empty?
550 assert ActionMailer::Base.deliveries.empty?
530 # should restore perform_deliveries
551 # should restore perform_deliveries
531 assert ActionMailer::Base.perform_deliveries
552 assert ActionMailer::Base.perform_deliveries
532 end
553 end
533
554
534 def test_layout_should_include_the_emails_header
555 def test_layout_should_include_the_emails_header
535 with_settings :emails_header => "*Header content*" do
556 with_settings :emails_header => "*Header content*" do
536 assert Mailer.test_email(User.find(1)).deliver
557 assert Mailer.test_email(User.find(1)).deliver
537 assert_select_email do
558 assert_select_email do
538 assert_select ".header" do
559 assert_select ".header" do
539 assert_select "strong", :text => "Header content"
560 assert_select "strong", :text => "Header content"
540 end
561 end
541 end
562 end
542 end
563 end
543 end
564 end
544
565
545 def test_should_escape_html_templates_only
566 def test_should_escape_html_templates_only
546 Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
567 Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
547 mail = last_email
568 mail = last_email
548 assert_equal 2, mail.parts.size
569 assert_equal 2, mail.parts.size
549 assert_include '<tag>', text_part.body.encoded
570 assert_include '<tag>', text_part.body.encoded
550 assert_include '&lt;tag&gt;', html_part.body.encoded
571 assert_include '&lt;tag&gt;', html_part.body.encoded
551 end
572 end
552
573
553 private
574 private
554
575
555 def last_email
576 def last_email
556 mail = ActionMailer::Base.deliveries.last
577 mail = ActionMailer::Base.deliveries.last
557 assert_not_nil mail
578 assert_not_nil mail
558 mail
579 mail
559 end
580 end
560
581
561 def text_part
582 def text_part
562 last_email.parts.detect {|part| part.content_type.include?('text/plain')}
583 last_email.parts.detect {|part| part.content_type.include?('text/plain')}
563 end
584 end
564
585
565 def html_part
586 def html_part
566 last_email.parts.detect {|part| part.content_type.include?('text/html')}
587 last_email.parts.detect {|part| part.content_type.include?('text/html')}
567 end
588 end
568 end
589 end
General Comments 0
You need to be logged in to leave comments. Login now