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