Defect #17096 » 17096-fix-emails-threading.patch
app/models/mailer.rb | ||
---|---|---|
134 | 134 |
redmine_headers 'Project' => document.project.identifier |
135 | 135 |
@author = author |
136 | 136 |
@document = document |
137 |
@user = user |
|
137 | 138 |
@document_url = url_for(:controller => 'documents', :action => 'show', :id => document) |
138 | 139 |
mail :to => user, |
139 | 140 |
:subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}" |
... | ... | |
169 | 170 |
end |
170 | 171 |
redmine_headers 'Project' => container.project.identifier |
171 | 172 |
@attachments = attachments |
173 |
@user = user |
|
172 | 174 |
@added_to = added_to |
173 | 175 |
@added_to_url = added_to_url |
174 | 176 |
mail :to => user, |
... | ... | |
200 | 202 |
message_id news |
201 | 203 |
references news |
202 | 204 |
@news = news |
205 |
@user = user |
|
203 | 206 |
@news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
204 | 207 |
mail :to => user, |
205 | 208 |
:subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}" |
... | ... | |
225 | 228 |
references news |
226 | 229 |
@news = news |
227 | 230 |
@comment = comment |
231 |
@user = user |
|
228 | 232 |
@news_url = url_for(:controller => 'news', :action => 'show', :id => news) |
229 | 233 |
mail :to => user, |
230 | 234 |
:subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}" |
... | ... | |
250 | 254 |
message_id message |
251 | 255 |
references message.root |
252 | 256 |
@message = message |
257 |
@user = user |
|
253 | 258 |
@message_url = url_for(message.event_url) |
254 | 259 |
mail :to => user, |
255 | 260 |
:subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}" |
... | ... | |
276 | 281 |
@author = wiki_content.author |
277 | 282 |
message_id wiki_content |
278 | 283 |
@wiki_content = wiki_content |
284 |
@user = user |
|
279 | 285 |
@wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
280 | 286 |
:project_id => wiki_content.project, |
281 | 287 |
:id => wiki_content.page.title) |
... | ... | |
301 | 307 |
@author = wiki_content.author |
302 | 308 |
message_id wiki_content |
303 | 309 |
@wiki_content = wiki_content |
310 |
@user = user |
|
304 | 311 |
@wiki_content_url = url_for(:controller => 'wiki', :action => 'show', |
305 | 312 |
:project_id => wiki_content.project, |
306 | 313 |
:id => wiki_content.page.title) |
... | ... | |
659 | 666 |
end |
660 | 667 | |
661 | 668 |
if @message_id_object |
662 |
headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>" |
|
669 |
headers[:message_id] = "<#{self.class.message_id_for(@message_id_object, @user)}>"
|
|
663 | 670 |
end |
664 | 671 |
if @references_objects |
665 |
headers[:references] = @references_objects.collect {|o| "<#{self.class.references_for(o)}>"}.join(' ') |
|
672 |
headers[:references] = @references_objects.collect {|o| "<#{self.class.references_for(o, @user)}>"}.join(' ')
|
|
666 | 673 |
end |
667 | 674 | |
668 | 675 |
if block_given? |
... | ... | |
716 | 723 |
h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s } |
717 | 724 |
end |
718 | 725 | |
719 |
def self.token_for(object, rand=true)
|
|
726 |
def self.token_for(object, user)
|
|
720 | 727 |
timestamp = object.send(object.respond_to?(:created_on) ? :created_on : :updated_on) |
721 | 728 |
hash = [ |
722 | 729 |
"redmine", |
723 | 730 |
"#{object.class.name.demodulize.underscore}-#{object.id}", |
724 | 731 |
timestamp.strftime("%Y%m%d%H%M%S") |
725 | 732 |
] |
726 |
if rand |
|
727 |
hash << Redmine::Utils.random_hex(8) |
|
728 |
end |
|
733 |
hash << user.id if user |
|
729 | 734 |
host = Setting.mail_from.to_s.strip.gsub(%r{^.*@|>}, '') |
730 | 735 |
host = "#{::Socket.gethostname}.redmine" if host.empty? |
731 | 736 |
"#{hash.join('.')}@#{host}" |
732 | 737 |
end |
733 | 738 | |
734 | 739 |
# Returns a Message-Id for the given object |
735 |
def self.message_id_for(object) |
|
736 |
token_for(object, true)
|
|
740 |
def self.message_id_for(object, user)
|
|
741 |
token_for(object, user)
|
|
737 | 742 |
end |
738 | 743 | |
739 | 744 |
# Returns a uniq token for a given object referenced by all notifications |
740 | 745 |
# related to this object |
741 |
def self.references_for(object) |
|
742 |
token_for(object, false)
|
|
746 |
def self.references_for(object, user)
|
|
747 |
token_for(object, user)
|
|
743 | 748 |
end |
744 | 749 | |
745 | 750 |
def message_id(object) |
... | ... | |
751 | 756 |
@references_objects << object |
752 | 757 |
end |
753 | 758 |
end |
759 |
test/unit/mailer_test.rb | ||
---|---|---|
293 | 293 |
issue = Issue.find(2) |
294 | 294 |
Mailer.deliver_issue_add(issue) |
295 | 295 |
mail = last_email |
296 |
assert_match /^redmine\.issue-2\.20060719190421\.[a-f0-9]+@example\.net/, mail.message_id |
|
297 |
assert_include "redmine.issue-2.20060719190421@example.net", mail.references |
|
296 |
uid = destination_user(mail).id |
|
297 |
assert_include "redmine.issue-2.20060719190421.#{uid}@example.net", mail.message_id |
|
298 |
assert_include "redmine.issue-2.20060719190421.#{uid}@example.net", mail.references |
|
298 | 299 |
end |
299 | 300 | |
300 | 301 |
def test_issue_edit_message_id |
... | ... | |
303 | 304 | |
304 | 305 |
Mailer.deliver_issue_edit(journal) |
305 | 306 |
mail = last_email |
306 |
assert_match /^redmine\.journal-3\.\d+\.[a-f0-9]+@example\.net/, mail.message_id |
|
307 |
assert_include "redmine.issue-2.20060719190421@example.net", mail.references |
|
307 |
uid = destination_user(mail).id |
|
308 |
assert_match /^redmine\.journal-3\.\d+\.#{uid}@example\.net/, mail.message_id |
|
309 |
assert_include "redmine.issue-2.20060719190421.#{uid}@example.net", mail.references |
|
308 | 310 |
assert_select_email do |
309 | 311 |
# link to the update |
310 | 312 |
assert_select "a[href=?]", |
... | ... | |
316 | 318 |
message = Message.find(1) |
317 | 319 |
Mailer.deliver_message_posted(message) |
318 | 320 |
mail = last_email |
319 |
assert_match /^redmine\.message-1\.\d+\.[a-f0-9]+@example\.net/, mail.message_id |
|
320 |
assert_include "redmine.message-1.20070512151532@example.net", mail.references |
|
321 |
uid = destination_user(mail).id |
|
322 |
assert_include "redmine.message-1.20070512151532.#{uid}@example.net", mail.message_id |
|
323 |
assert_include "redmine.message-1.20070512151532.#{uid}@example.net", mail.references |
|
321 | 324 |
assert_select_email do |
322 | 325 |
# link to the message |
323 | 326 |
assert_select "a[href=?]", |
... | ... | |
330 | 333 |
message = Message.find(3) |
331 | 334 |
Mailer.deliver_message_posted(message) |
332 | 335 |
mail = last_email |
333 |
assert_match /^redmine\.message-3\.\d+\.[a-f0-9]+@example\.net/, mail.message_id |
|
334 |
assert_include "redmine.message-1.20070512151532@example.net", mail.references |
|
336 |
uid = destination_user(mail).id |
|
337 |
assert_include "redmine.message-3.20070512151802.#{uid}@example.net", mail.message_id |
|
338 |
assert_include "redmine.message-1.20070512151532.#{uid}@example.net", mail.references |
|
335 | 339 |
assert_select_email do |
336 | 340 |
# link to the reply |
337 | 341 |
assert_select "a[href=?]", |
... | ... | |
745 | 749 | |
746 | 750 |
def test_token_for_should_strip_trailing_gt_from_address_with_full_name |
747 | 751 |
with_settings :mail_from => "Redmine Mailer<no-reply@redmine.org>" do |
748 |
assert_match /\Aredmine.issue-\d+\.\d+\.[0-9a-f]+@redmine.org\z/, Mailer.token_for(Issue.generate!) |
|
752 |
assert_match /\Aredmine.issue-\d+\.\d+\.3@redmine.org\z/, |
|
753 |
Mailer.token_for(Issue.generate!, User.find(3)) |
|
749 | 754 |
end |
750 | 755 |
end |
751 | 756 | |
... | ... | |
897 | 902 |
def html_part |
898 | 903 |
last_email.parts.detect {|part| part.content_type.include?('text/html')} |
899 | 904 |
end |
905 | ||
906 |
def destination_user(mail) |
|
907 |
EmailAddress.where(:address => [mail.to, mail.cc, mail.bcc].flatten).map(&:user).first |
|
908 |
end |
|
900 | 909 |
end |