Skip to content

Commit

Permalink
Adds Message-Id and References headers to email notifications so that…
Browse files Browse the repository at this point in the history
… issues and messages threads can be displayed by email clients (#1401).

git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2281 e93f8b46-1217-0410-a6f0-8f06a7374b81
  • Loading branch information
jplang committed Jan 18, 2009
1 parent a488246 commit 1d78310
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
46 changes: 45 additions & 1 deletion app/models/mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def issue_add(issue)
'Issue-Id' => issue.id,
'Issue-Author' => issue.author.login
redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
message_id issue
recipients issue.recipients
cc(issue.watcher_recipients - @recipients)
subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
Expand All @@ -40,6 +41,8 @@ def issue_edit(journal)
'Issue-Id' => issue.id,
'Issue-Author' => issue.author.login
redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
message_id journal
references issue
@author = journal.user
recipients issue.recipients
# Watchers in cc
Expand Down Expand Up @@ -95,6 +98,7 @@ def attachments_added(attachments)

def news_added(news)
redmine_headers 'Project' => news.project.identifier
message_id news
recipients news.project.recipients
subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
body :news => news,
Expand All @@ -104,6 +108,8 @@ def news_added(news)
def message_posted(message, recipients)
redmine_headers 'Project' => message.project.identifier,
'Topic-Id' => (message.parent_id || message.id)
message_id message
references message.parent unless message.parent.nil?
recipients(recipients)
subject "[#{message.board.project.name} - #{message.board.name}] #{message.subject}"
body :message => message,
Expand Down Expand Up @@ -156,7 +162,15 @@ def deliver!(mail = @mail)
return false if (recipients.nil? || recipients.empty?) &&
(cc.nil? || cc.empty?) &&
(bcc.nil? || bcc.empty?)
super

# Set Message-Id and References
if @message_id_object
mail.message_id = self.class.message_id_for(@message_id_object)
end
if @references_objects
mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
end
super(mail)
end

# Sends reminders to issue assignees
Expand Down Expand Up @@ -250,4 +264,34 @@ def body(*params)
def self.controller_path
''
end unless respond_to?('controller_path')

# Returns a predictable Message-Id for the given object
def self.message_id_for(object)
# id + timestamp should reduce the odds of a collision
# as far as we don't send multiple emails for the same object
hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{object.created_on.strftime("%Y%m%d%H%M%S")}"
host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
host = "#{::Socket.gethostname}.redmine" if host.empty?
"<#{hash}@#{host}>"
end

private

def message_id(object)
@message_id_object = object
end

def references(object)
@references_objects ||= []
@references_objects << object
end
end

# Patch TMail so that message_id is not overwritten
module TMail
class Mail
def add_message_id( fqdn = nil )
self.message_id ||= ::TMail::new_message_id(fqdn)
end
end
end
2 changes: 1 addition & 1 deletion test/fixtures/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ messages_003:
replies_count: 0
last_reply_id:
content: "An other reply"
author_id:
author_id: 2
parent_id: 1
board_id: 1
messages_004:
Expand Down
40 changes: 39 additions & 1 deletion test/unit/mailer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,45 @@ def test_plain_text_mail
assert !mail.body.include?('<a href="https://mydomain.foo/issues/show/1">Bug #1: Can\'t print recipes</a>')
end


def test_issue_add_message_id
ActionMailer::Base.deliveries.clear
issue = Issue.find(1)
Mailer.deliver_issue_add(issue)
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail
assert_equal Mailer.message_id_for(issue), mail.message_id
assert_nil mail.references
end

def test_issue_edit_message_id
ActionMailer::Base.deliveries.clear
journal = Journal.find(1)
Mailer.deliver_issue_edit(journal)
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail
assert_equal Mailer.message_id_for(journal), mail.message_id
assert_equal Mailer.message_id_for(journal.issue), mail.references.to_s
end

def test_message_posted_message_id
ActionMailer::Base.deliveries.clear
message = Message.find(1)
Mailer.deliver_message_posted(message, message.author.mail)
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail
assert_equal Mailer.message_id_for(message), mail.message_id
assert_nil mail.references
end

def test_reply_posted_message_id
ActionMailer::Base.deliveries.clear
message = Message.find(3)
Mailer.deliver_message_posted(message, message.author.mail)
mail = ActionMailer::Base.deliveries.last
assert_not_nil mail
assert_equal Mailer.message_id_for(message), mail.message_id
assert_equal Mailer.message_id_for(message.parent), mail.references.to_s
end

# test mailer methods for each language
def test_issue_add
Expand Down

0 comments on commit 1d78310

Please sign in to comment.