Merge branch 'fix-email-threading' into 'master'
Fix broken email threading The email threading support introduced in GitLab CE 6.9 is broken on several popular email clients (including Mail.app and Airmail on Mac OS X). This MR makes the following changes to improve email threading compatibility: * Subject of answers to an existing thread begins with `Re: ` (required by Mail.app) * The recipient of every email in a thread is stable (required by Mail.app ; otherwise it groups emails by sender) * Send a ‘In-Reply-To’ header along the ‘References’ header (for compatibility with the spec) In order to do this, these commits: * Change the `To:` field to `namespace/project` ; the actual receiver is now in the `Cc:` field. * Introduce the `mail_new_thread` and `mail_answer_thread` methods ; they format the message correctly for threading, and can generate the `Message-ID` automatically from a model instance. * Refactor the tests to shared behaviors for email threading. We've been using these patches at @capitainetrain for a few months now ; I just ported them to work nicely with the recent threading commits.
This commit is contained in:
commit
97fd990ecd
11 changed files with 143 additions and 81 deletions
|
@ -4,7 +4,7 @@ module Emails
|
||||||
@membership = UsersGroup.find(user_group_id)
|
@membership = UsersGroup.find(user_group_id)
|
||||||
@group = @membership.group
|
@group = @membership.group
|
||||||
@target_url = group_url(@group)
|
@target_url = group_url(@group)
|
||||||
mail(to: @membership.user.email,
|
mail(cc: @membership.user.email,
|
||||||
subject: subject("Access to group was granted"))
|
subject: subject("Access to group was granted"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,9 @@ module Emails
|
||||||
@issue = Issue.find(issue_id)
|
@issue = Issue.find(issue_id)
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
@target_url = project_issue_url(@project, @issue)
|
@target_url = project_issue_url(@project, @issue)
|
||||||
set_message_id("issue_#{issue_id}")
|
mail_new_thread(@issue,
|
||||||
mail(from: sender(@issue.author_id),
|
from: sender(@issue.author_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@ module Emails
|
||||||
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
@target_url = project_issue_url(@project, @issue)
|
@target_url = project_issue_url(@project, @issue)
|
||||||
set_reference("issue_#{issue_id}")
|
mail_answer_thread(@issue,
|
||||||
mail(from: sender(updated_by_user_id),
|
from: sender(updated_by_user_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@ module Emails
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
@updated_by = User.find updated_by_user_id
|
@updated_by = User.find updated_by_user_id
|
||||||
@target_url = project_issue_url(@project, @issue)
|
@target_url = project_issue_url(@project, @issue)
|
||||||
set_reference("issue_#{issue_id}")
|
mail_answer_thread(@issue,
|
||||||
mail(from: sender(updated_by_user_id),
|
from: sender(updated_by_user_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,9 +38,9 @@ module Emails
|
||||||
@project = @issue.project
|
@project = @issue.project
|
||||||
@updated_by = User.find updated_by_user_id
|
@updated_by = User.find updated_by_user_id
|
||||||
@target_url = project_issue_url(@project, @issue)
|
@target_url = project_issue_url(@project, @issue)
|
||||||
set_reference("issue_#{issue_id}")
|
mail_answer_thread(@issue,
|
||||||
mail(from: sender(updated_by_user_id),
|
from: sender(updated_by_user_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,9 +4,9 @@ module Emails
|
||||||
@merge_request = MergeRequest.find(merge_request_id)
|
@merge_request = MergeRequest.find(merge_request_id)
|
||||||
@project = @merge_request.project
|
@project = @merge_request.project
|
||||||
@target_url = project_merge_request_url(@project, @merge_request)
|
@target_url = project_merge_request_url(@project, @merge_request)
|
||||||
set_message_id("merge_request_#{merge_request_id}")
|
mail_new_thread(@merge_request,
|
||||||
mail(from: sender(@merge_request.author_id),
|
from: sender(@merge_request.author_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@ module Emails
|
||||||
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
||||||
@project = @merge_request.project
|
@project = @merge_request.project
|
||||||
@target_url = project_merge_request_url(@project, @merge_request)
|
@target_url = project_merge_request_url(@project, @merge_request)
|
||||||
set_reference("merge_request_#{merge_request_id}")
|
mail_answer_thread(@merge_request,
|
||||||
mail(from: sender(updated_by_user_id),
|
from: sender(updated_by_user_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@ module Emails
|
||||||
@updated_by = User.find updated_by_user_id
|
@updated_by = User.find updated_by_user_id
|
||||||
@project = @merge_request.project
|
@project = @merge_request.project
|
||||||
@target_url = project_merge_request_url(@project, @merge_request)
|
@target_url = project_merge_request_url(@project, @merge_request)
|
||||||
set_reference("merge_request_#{merge_request_id}")
|
mail_answer_thread(@merge_request,
|
||||||
mail(from: sender(updated_by_user_id),
|
from: sender(updated_by_user_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ module Emails
|
||||||
@merge_request = MergeRequest.find(merge_request_id)
|
@merge_request = MergeRequest.find(merge_request_id)
|
||||||
@project = @merge_request.project
|
@project = @merge_request.project
|
||||||
@target_url = project_merge_request_url(@project, @merge_request)
|
@target_url = project_merge_request_url(@project, @merge_request)
|
||||||
set_reference("merge_request_#{merge_request_id}")
|
mail_answer_thread(@merge_request,
|
||||||
mail(from: sender(updated_by_user_id),
|
from: sender(updated_by_user_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,8 +5,9 @@ module Emails
|
||||||
@commit = @note.noteable
|
@commit = @note.noteable
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
@target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}")
|
@target_url = project_commit_url(@project, @commit, anchor: "note_#{@note.id}")
|
||||||
mail(from: sender(@note.author_id),
|
mail_answer_thread(@commit,
|
||||||
to: recipient(recipient_id),
|
from: sender(@note.author_id),
|
||||||
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@commit.title} (#{@commit.short_id})"))
|
subject: subject("#{@commit.title} (#{@commit.short_id})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,9 +16,9 @@ module Emails
|
||||||
@issue = @note.noteable
|
@issue = @note.noteable
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
@target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
|
@target_url = project_issue_url(@project, @issue, anchor: "note_#{@note.id}")
|
||||||
set_reference("issue_#{@issue.id}")
|
mail_answer_thread(@issue,
|
||||||
mail(from: sender(@note.author_id),
|
from: sender(@note.author_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
subject: subject("#{@issue.title} (##{@issue.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,9 +27,9 @@ module Emails
|
||||||
@merge_request = @note.noteable
|
@merge_request = @note.noteable
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
@target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
|
@target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{@note.id}")
|
||||||
set_reference("merge_request_#{@merge_request.id}")
|
mail_answer_thread(@merge_request,
|
||||||
mail(from: sender(@note.author_id),
|
from: sender(@note.author_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ module Emails
|
||||||
@project = @note.project
|
@project = @note.project
|
||||||
@target_url = project_wall_url(@note.project, anchor: "note_#{@note.id}")
|
@target_url = project_wall_url(@note.project, anchor: "note_#{@note.id}")
|
||||||
mail(from: sender(@note.author_id),
|
mail(from: sender(@note.author_id),
|
||||||
to: recipient(recipient_id),
|
cc: recipient(recipient_id),
|
||||||
subject: subject("Note on wall"))
|
subject: subject("Note on wall"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Emails
|
||||||
@users_project = UsersProject.find user_project_id
|
@users_project = UsersProject.find user_project_id
|
||||||
@project = @users_project.project
|
@project = @users_project.project
|
||||||
@target_url = project_url(@project)
|
@target_url = project_url(@project)
|
||||||
mail(to: @users_project.user.email,
|
mail(cc: @users_project.user.email,
|
||||||
subject: subject("Access to project was granted"))
|
subject: subject("Access to project was granted"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ module Emails
|
||||||
@user = User.find user_id
|
@user = User.find user_id
|
||||||
@project = Project.find project_id
|
@project = Project.find project_id
|
||||||
@target_url = project_url(@project)
|
@target_url = project_url(@project)
|
||||||
mail(to: @user.email,
|
mail(cc: @user.email,
|
||||||
subject: subject("Project was moved"))
|
subject: subject("Project was moved"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ module Emails
|
||||||
end
|
end
|
||||||
|
|
||||||
mail(from: sender(author_id),
|
mail(from: sender(author_id),
|
||||||
to: recipient,
|
cc: recipient,
|
||||||
subject: subject("New push to repository"))
|
subject: subject("New push to repository"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class Notify < ActionMailer::Base
|
class Notify < ActionMailer::Base
|
||||||
|
include ActionDispatch::Routing::PolymorphicRoutes
|
||||||
|
|
||||||
include Emails::Issues
|
include Emails::Issues
|
||||||
include Emails::MergeRequests
|
include Emails::MergeRequests
|
||||||
include Emails::Notes
|
include Emails::Notes
|
||||||
|
@ -16,6 +18,7 @@ class Notify < ActionMailer::Base
|
||||||
default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root
|
default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root
|
||||||
|
|
||||||
default from: Proc.new { default_sender_address.format }
|
default from: Proc.new { default_sender_address.format }
|
||||||
|
default to: Proc.new { project_sender_address.format }
|
||||||
default reply_to: "noreply@#{Gitlab.config.gitlab.host}"
|
default reply_to: "noreply@#{Gitlab.config.gitlab.host}"
|
||||||
|
|
||||||
# Just send email with 2 seconds delay
|
# Just send email with 2 seconds delay
|
||||||
|
@ -32,6 +35,17 @@ class Notify < ActionMailer::Base
|
||||||
address
|
address
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# The default email address to send emails to. Includes the project name if possible.
|
||||||
|
def project_sender_address
|
||||||
|
if @project
|
||||||
|
address = default_sender_address
|
||||||
|
address.display_name = @project.name_with_namespace
|
||||||
|
address
|
||||||
|
else
|
||||||
|
default_sender_address
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Return an email address that displays the name of the sender.
|
# Return an email address that displays the name of the sender.
|
||||||
# Only the displayed name changes; the actual email address is always the same.
|
# Only the displayed name changes; the actual email address is always the same.
|
||||||
def sender(sender_id)
|
def sender(sender_id)
|
||||||
|
@ -53,14 +67,6 @@ class Notify < ActionMailer::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set the Message-ID header field
|
|
||||||
#
|
|
||||||
# local_part - The local part of the message ID
|
|
||||||
#
|
|
||||||
def set_message_id(local_part)
|
|
||||||
headers["Message-ID"] = "<#{local_part}@#{Gitlab.config.gitlab.host}>"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set the References header field
|
# Set the References header field
|
||||||
#
|
#
|
||||||
# local_part - The local part of the referenced message ID
|
# local_part - The local part of the referenced message ID
|
||||||
|
@ -93,4 +99,48 @@ class Notify < ActionMailer::Base
|
||||||
subject << extra.join(' | ') if extra.present?
|
subject << extra.join(' | ') if extra.present?
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return a string suitable for inclusion in the 'Message-Id' mail header.
|
||||||
|
#
|
||||||
|
# The message-id is generated from the unique URL to a model object.
|
||||||
|
def message_id(model)
|
||||||
|
model_name = model.class.model_name.singular_route_key
|
||||||
|
"<#{model_name}_#{model.id}@#{Gitlab.config.gitlab.host}>"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Send an email that starts a new conversation thread,
|
||||||
|
# with headers suitable for grouping by thread in email clients.
|
||||||
|
#
|
||||||
|
# See: mail_answer_thread
|
||||||
|
def mail_new_thread(model, headers = {}, &block)
|
||||||
|
raise ArgumentError, '"To:" header will be overwritten; use "Cc:" or "Bcc:"' unless headers[:to].nil?
|
||||||
|
headers[:to] = project_sender_address.format
|
||||||
|
|
||||||
|
headers['Message-ID'] = message_id(model)
|
||||||
|
|
||||||
|
mail(headers, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Send an email that responds to an existing conversation thread,
|
||||||
|
# with headers suitable for grouping by thread in email clients.
|
||||||
|
#
|
||||||
|
# For grouping emails by thread, email clients heuristics require the answers to:
|
||||||
|
#
|
||||||
|
# * have a subject that begin by 'Re: '
|
||||||
|
# * have a 'In-Reply-To' or 'References' header that references the original 'Message-ID'
|
||||||
|
# * have stable 'From' and 'To' headers between messages of the same thread
|
||||||
|
#
|
||||||
|
def mail_answer_thread(model, headers = {}, &block)
|
||||||
|
raise ArgumentError, '"To:" header will be overwritten; use "Cc:" or "Bcc:"' unless headers[:to].nil?
|
||||||
|
headers[:to] = project_sender_address.format
|
||||||
|
|
||||||
|
headers['In-Reply-To'] = message_id(model)
|
||||||
|
headers['References'] = message_id(model)
|
||||||
|
|
||||||
|
if (headers[:subject])
|
||||||
|
headers[:subject].prepend('Re: ')
|
||||||
|
end
|
||||||
|
|
||||||
|
mail(headers, &block)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ describe Notify do
|
||||||
|
|
||||||
shared_examples 'a multiple recipients email' do
|
shared_examples 'a multiple recipients email' do
|
||||||
it 'is sent to the given recipient' do
|
it 'is sent to the given recipient' do
|
||||||
should deliver_to recipient.email
|
should cc_to recipient.email
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -22,6 +22,23 @@ describe Notify do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
shared_examples 'an email starting a new thread' do |message_id_prefix|
|
||||||
|
it 'has a discussion identifier' do
|
||||||
|
should have_header 'Message-ID', /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'an answer to an existing thread' do |thread_id_prefix|
|
||||||
|
it 'has a subject that begins with Re: ' do
|
||||||
|
should have_subject /^Re: /
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has headers that reference an existing thread' do
|
||||||
|
should have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
|
||||||
|
should have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'for new users, the email' do
|
describe 'for new users, the email' do
|
||||||
let(:example_site_path) { root_path }
|
let(:example_site_path) { root_path }
|
||||||
let(:new_user) { create(:user, email: 'newguy@example.com', created_by_id: 1) }
|
let(:new_user) { create(:user, email: 'newguy@example.com', created_by_id: 1) }
|
||||||
|
@ -141,7 +158,7 @@ describe Notify do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is sent to the assignee' do
|
it 'is sent to the assignee' do
|
||||||
should deliver_to assignee.email
|
should cc_to assignee.email
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -153,6 +170,7 @@ describe Notify do
|
||||||
subject { Notify.new_issue_email(issue.assignee_id, issue.id) }
|
subject { Notify.new_issue_email(issue.assignee_id, issue.id) }
|
||||||
|
|
||||||
it_behaves_like 'an assignee email'
|
it_behaves_like 'an assignee email'
|
||||||
|
it_behaves_like 'an email starting a new thread', 'issue'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
|
should have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
|
||||||
|
@ -161,10 +179,6 @@ describe Notify do
|
||||||
it 'contains a link to the new issue' do
|
it 'contains a link to the new issue' do
|
||||||
should have_body_text /#{project_issue_path project, issue}/
|
should have_body_text /#{project_issue_path project, issue}/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct message-id set' do
|
|
||||||
should have_header 'Message-ID', "<issue_#{issue.id}@#{Gitlab.config.gitlab.host}>"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'that are new with a description' do
|
describe 'that are new with a description' do
|
||||||
|
@ -179,6 +193,7 @@ describe Notify do
|
||||||
subject { Notify.reassigned_issue_email(recipient.id, issue.id, previous_assignee.id, current_user) }
|
subject { Notify.reassigned_issue_email(recipient.id, issue.id, previous_assignee.id, current_user) }
|
||||||
|
|
||||||
it_behaves_like 'a multiple recipients email'
|
it_behaves_like 'a multiple recipients email'
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'issue'
|
||||||
|
|
||||||
it 'is sent as the author' do
|
it 'is sent as the author' do
|
||||||
sender = subject.header[:from].addrs[0]
|
sender = subject.header[:from].addrs[0]
|
||||||
|
@ -201,16 +216,14 @@ describe Notify do
|
||||||
it 'contains a link to the issue' do
|
it 'contains a link to the issue' do
|
||||||
should have_body_text /#{project_issue_path project, issue}/
|
should have_body_text /#{project_issue_path project, issue}/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct reference set' do
|
|
||||||
should have_header 'References', "<issue_#{issue.id}@#{Gitlab.config.gitlab.host}>"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'status changed' do
|
describe 'status changed' do
|
||||||
let(:status) { 'closed' }
|
let(:status) { 'closed' }
|
||||||
subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
|
subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) }
|
||||||
|
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'issue'
|
||||||
|
|
||||||
it 'is sent as the author' do
|
it 'is sent as the author' do
|
||||||
sender = subject.header[:from].addrs[0]
|
sender = subject.header[:from].addrs[0]
|
||||||
sender.display_name.should eq(current_user.name)
|
sender.display_name.should eq(current_user.name)
|
||||||
|
@ -232,10 +245,6 @@ describe Notify do
|
||||||
it 'contains a link to the issue' do
|
it 'contains a link to the issue' do
|
||||||
should have_body_text /#{project_issue_path project, issue}/
|
should have_body_text /#{project_issue_path project, issue}/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct reference set' do
|
|
||||||
should have_header 'References', "<issue_#{issue.id}@#{Gitlab.config.gitlab.host}>"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -249,6 +258,7 @@ describe Notify do
|
||||||
subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) }
|
subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) }
|
||||||
|
|
||||||
it_behaves_like 'an assignee email'
|
it_behaves_like 'an assignee email'
|
||||||
|
it_behaves_like 'an email starting a new thread', 'merge_request'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
|
should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
|
||||||
|
@ -283,6 +293,7 @@ describe Notify do
|
||||||
subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id) }
|
subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id) }
|
||||||
|
|
||||||
it_behaves_like 'a multiple recipients email'
|
it_behaves_like 'a multiple recipients email'
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'merge_request'
|
||||||
|
|
||||||
it 'is sent as the author' do
|
it 'is sent as the author' do
|
||||||
sender = subject.header[:from].addrs[0]
|
sender = subject.header[:from].addrs[0]
|
||||||
|
@ -311,6 +322,7 @@ describe Notify do
|
||||||
subject { Notify.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }
|
subject { Notify.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }
|
||||||
|
|
||||||
it_behaves_like 'a multiple recipients email'
|
it_behaves_like 'a multiple recipients email'
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'merge_request'
|
||||||
|
|
||||||
it 'is sent as the merge author' do
|
it 'is sent as the merge author' do
|
||||||
sender = subject.header[:from].addrs[0]
|
sender = subject.header[:from].addrs[0]
|
||||||
|
@ -329,10 +341,6 @@ describe Notify do
|
||||||
it 'contains a link to the merge request' do
|
it 'contains a link to the merge request' do
|
||||||
should have_body_text /#{project_merge_request_path project, merge_request}/
|
should have_body_text /#{project_merge_request_path project, merge_request}/
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct reference set' do
|
|
||||||
should have_header 'References', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -394,7 +402,7 @@ describe Notify do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is sent to the given recipient' do
|
it 'is sent to the given recipient' do
|
||||||
should deliver_to recipient.email
|
should cc_to recipient.email
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'contains the message from the note' do
|
it 'contains the message from the note' do
|
||||||
|
@ -426,6 +434,7 @@ describe Notify do
|
||||||
subject { Notify.note_commit_email(recipient.id, note.id) }
|
subject { Notify.note_commit_email(recipient.id, note.id) }
|
||||||
|
|
||||||
it_behaves_like 'a note email'
|
it_behaves_like 'a note email'
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'commits'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /#{commit.title} \(#{commit.short_id}\)/
|
should have_subject /#{commit.title} \(#{commit.short_id}\)/
|
||||||
|
@ -444,6 +453,7 @@ describe Notify do
|
||||||
subject { Notify.note_merge_request_email(recipient.id, note.id) }
|
subject { Notify.note_merge_request_email(recipient.id, note.id) }
|
||||||
|
|
||||||
it_behaves_like 'a note email'
|
it_behaves_like 'a note email'
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'merge_request'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
|
should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/
|
||||||
|
@ -462,6 +472,7 @@ describe Notify do
|
||||||
subject { Notify.note_issue_email(recipient.id, note.id) }
|
subject { Notify.note_issue_email(recipient.id, note.id) }
|
||||||
|
|
||||||
it_behaves_like 'a note email'
|
it_behaves_like 'a note email'
|
||||||
|
it_behaves_like 'an answer to an existing thread', 'issue'
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
should have_subject /#{issue.title} \(##{issue.iid}\)/
|
should have_subject /#{issue.title} \(##{issue.iid}\)/
|
||||||
|
@ -538,7 +549,7 @@ describe Notify do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is sent to recipient' do
|
it 'is sent to recipient' do
|
||||||
should deliver_to 'devs@company.name'
|
should cc_to 'devs@company.name'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
|
@ -574,7 +585,7 @@ describe Notify do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is sent to recipient' do
|
it 'is sent to recipient' do
|
||||||
should deliver_to 'devs@company.name'
|
should cc_to 'devs@company.name'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'has the correct subject' do
|
it 'has the correct subject' do
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe Issues::CloseService do
|
||||||
|
|
||||||
it 'should send email to user2 about assign of new issue' do
|
it 'should send email to user2 about assign of new issue' do
|
||||||
email = ActionMailer::Base.deliveries.last
|
email = ActionMailer::Base.deliveries.last
|
||||||
email.to.first.should == user2.email
|
email.cc.first.should == user2.email
|
||||||
email.subject.should include(issue.title)
|
email.subject.should include(issue.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ describe Issues::UpdateService do
|
||||||
|
|
||||||
it 'should send email to user2 about assign of new issue' do
|
it 'should send email to user2 about assign of new issue' do
|
||||||
email = ActionMailer::Base.deliveries.last
|
email = ActionMailer::Base.deliveries.last
|
||||||
email.to.first.should == user2.email
|
email.cc.first.should == user2.email
|
||||||
email.subject.should include(issue.title)
|
email.subject.should include(issue.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe MergeRequests::CloseService do
|
||||||
|
|
||||||
it 'should send email to user2 about assign of new merge_request' do
|
it 'should send email to user2 about assign of new merge_request' do
|
||||||
email = ActionMailer::Base.deliveries.last
|
email = ActionMailer::Base.deliveries.last
|
||||||
email.to.first.should == user2.email
|
email.cc.first.should == user2.email
|
||||||
email.subject.should include(merge_request.title)
|
email.subject.should include(merge_request.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ describe MergeRequests::UpdateService do
|
||||||
|
|
||||||
it 'should send email to user2 about assign of new merge_request' do
|
it 'should send email to user2 about assign of new merge_request' do
|
||||||
email = ActionMailer::Base.deliveries.last
|
email = ActionMailer::Base.deliveries.last
|
||||||
email.to.first.should == user2.email
|
email.cc.first.should == user2.email
|
||||||
email.subject.should include(merge_request.title)
|
email.subject.should include(merge_request.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue