##// END OF EJS Templates
Adds Message-Id and References headers to email notifications so that issues and messages threads can be displayed by email clients (#1401)....
Jean-Philippe Lang -
r2279:1d783106a34b
parent child
Show More
@@ -27,6 +27,7 class Mailer < ActionMailer::Base
27 27 'Issue-Id' => issue.id,
28 28 'Issue-Author' => issue.author.login
29 29 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
30 message_id issue
30 31 recipients issue.recipients
31 32 cc(issue.watcher_recipients - @recipients)
32 33 subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
@@ -40,6 +41,8 class Mailer < ActionMailer::Base
40 41 'Issue-Id' => issue.id,
41 42 'Issue-Author' => issue.author.login
42 43 redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
44 message_id journal
45 references issue
43 46 @author = journal.user
44 47 recipients issue.recipients
45 48 # Watchers in cc
@@ -95,6 +98,7 class Mailer < ActionMailer::Base
95 98
96 99 def news_added(news)
97 100 redmine_headers 'Project' => news.project.identifier
101 message_id news
98 102 recipients news.project.recipients
99 103 subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
100 104 body :news => news,
@@ -104,6 +108,8 class Mailer < ActionMailer::Base
104 108 def message_posted(message, recipients)
105 109 redmine_headers 'Project' => message.project.identifier,
106 110 'Topic-Id' => (message.parent_id || message.id)
111 message_id message
112 references message.parent unless message.parent.nil?
107 113 recipients(recipients)
108 114 subject "[#{message.board.project.name} - #{message.board.name}] #{message.subject}"
109 115 body :message => message,
@@ -156,7 +162,15 class Mailer < ActionMailer::Base
156 162 return false if (recipients.nil? || recipients.empty?) &&
157 163 (cc.nil? || cc.empty?) &&
158 164 (bcc.nil? || bcc.empty?)
159 super
165
166 # Set Message-Id and References
167 if @message_id_object
168 mail.message_id = self.class.message_id_for(@message_id_object)
169 end
170 if @references_objects
171 mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
172 end
173 super(mail)
160 174 end
161 175
162 176 # Sends reminders to issue assignees
@@ -250,4 +264,34 class Mailer < ActionMailer::Base
250 264 def self.controller_path
251 265 ''
252 266 end unless respond_to?('controller_path')
267
268 # Returns a predictable Message-Id for the given object
269 def self.message_id_for(object)
270 # id + timestamp should reduce the odds of a collision
271 # as far as we don't send multiple emails for the same object
272 hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{object.created_on.strftime("%Y%m%d%H%M%S")}"
273 host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
274 host = "#{::Socket.gethostname}.redmine" if host.empty?
275 "<#{hash}@#{host}>"
276 end
277
278 private
279
280 def message_id(object)
281 @message_id_object = object
282 end
283
284 def references(object)
285 @references_objects ||= []
286 @references_objects << object
287 end
288 end
289
290 # Patch TMail so that message_id is not overwritten
291 module TMail
292 class Mail
293 def add_message_id( fqdn = nil )
294 self.message_id ||= ::TMail::new_message_id(fqdn)
295 end
296 end
253 297 end
@@ -30,7 +30,7 messages_003:
30 30 replies_count: 0
31 31 last_reply_id:
32 32 content: "An other reply"
33 author_id:
33 author_id: 2
34 34 parent_id: 1
35 35 board_id: 1
36 36 messages_004:
@@ -95,7 +95,45 class MailerTest < Test::Unit::TestCase
95 95 assert !mail.body.include?('<a href="https://mydomain.foo/issues/show/1">Bug #1: Can\'t print recipes</a>')
96 96 end
97 97
98
98 def test_issue_add_message_id
99 ActionMailer::Base.deliveries.clear
100 issue = Issue.find(1)
101 Mailer.deliver_issue_add(issue)
102 mail = ActionMailer::Base.deliveries.last
103 assert_not_nil mail
104 assert_equal Mailer.message_id_for(issue), mail.message_id
105 assert_nil mail.references
106 end
107
108 def test_issue_edit_message_id
109 ActionMailer::Base.deliveries.clear
110 journal = Journal.find(1)
111 Mailer.deliver_issue_edit(journal)
112 mail = ActionMailer::Base.deliveries.last
113 assert_not_nil mail
114 assert_equal Mailer.message_id_for(journal), mail.message_id
115 assert_equal Mailer.message_id_for(journal.issue), mail.references.to_s
116 end
117
118 def test_message_posted_message_id
119 ActionMailer::Base.deliveries.clear
120 message = Message.find(1)
121 Mailer.deliver_message_posted(message, message.author.mail)
122 mail = ActionMailer::Base.deliveries.last
123 assert_not_nil mail
124 assert_equal Mailer.message_id_for(message), mail.message_id
125 assert_nil mail.references
126 end
127
128 def test_reply_posted_message_id
129 ActionMailer::Base.deliveries.clear
130 message = Message.find(3)
131 Mailer.deliver_message_posted(message, message.author.mail)
132 mail = ActionMailer::Base.deliveries.last
133 assert_not_nil mail
134 assert_equal Mailer.message_id_for(message), mail.message_id
135 assert_equal Mailer.message_id_for(message.parent), mail.references.to_s
136 end
99 137
100 138 # test mailer methods for each language
101 139 def test_issue_add
General Comments 0
You need to be logged in to leave comments. Login now