Skip to content

Commit

Permalink
Refactor RequestMailer#receive
Browse files Browse the repository at this point in the history
Loop through exact matches and delivery emails to each info request.
This is now possible because we check `InfoRequest#already_received?`
when calling `InfoRequest#receive`.

Previously this could result in requests receiving an email multiple
times due to the same email coming in to the mail server multiple times,
once for each address in the `To` header.

Fixes #7913
  • Loading branch information
alexander-griffen authored and gbp committed Oct 20, 2023
1 parent d388347 commit 5a24157
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 18 deletions.
38 changes: 20 additions & 18 deletions app/mailers/request_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,29 +252,31 @@ def receive(email, raw_email, source = :mailin)
# Find exact matches for info requests
exact_info_requests = requests_matching_email(email)

# Find any guesses for info requests
unless exact_info_requests.count == 1
guessed_info_requests = Guess.guessed_info_requests(email)
end

# If there is only one info request matching mail, it gets attached to the
# request to be archived with it
if exact_info_requests.count == 1 || guessed_info_requests.count == 1
info_request = exact_info_requests.first || guessed_info_requests.first

if exact_info_requests.empty? && guessed_info_requests.count == 1
info_request.log_event(
'redeliver_incoming',
editor: 'automatic',
destination_request: info_request
)
if exact_info_requests.count > 0
# Go through each exact info request and deliver the email
exact_info_requests.each do |info_request|
info_request.receive(email, raw_email, opts)
end

return
end

# If there are no exact matches, find any guessed requests
guessed_info_requests = Guess.guessed_info_requests(email)

if guessed_info_requests.count == 1
# If there one guess automatically redeliver the email to that and log it
# as an event
info_request = guessed_info_requests.first
info_request.log_event(
'redeliver_incoming',
editor: 'automatic',
destination_request: info_request
)
info_request.receive(email, raw_email, opts)

else
# Otherwise, if there are no matching IRs, multiple IRs, or multiple IR
# guesses, we send the mail to the holding pen
# Otherwise we send the mail to the holding pen
send_to_holding_pen(email, raw_email, opts)
end
end
Expand Down
79 changes: 79 additions & 0 deletions spec/mailers/request_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,85 @@
deliveries.clear
end

it "should append the email to each exact request address, unless that request has already received the email" do
ir = info_requests(:fancy_dog_request)
raw_email_data = <<~EML
From: EMAIL_FROM
To: EMAIL_TO
Message-ID: [email protected]
Subject: Basic Email
Hello, World
EML
expect(ir.incoming_messages.count).to eq(1) # in the fixture
receive_incoming_mail(
raw_email_data,
email_to: ir.incoming_email
)
expect(ir.incoming_messages.count).to eq(2) # one more arrives
# send the email again
receive_incoming_mail(
raw_email_data,
email_to: ir.incoming_email
)
# this shouldn't add to the number of incoming mails
expect(ir.incoming_messages.count).to eq(2)
# send an email with a new Message-ID
raw_email_data = <<~EML
From: EMAIL_FROM
To: EMAIL_TO
Message-ID: [email protected]
Subject: Basic Email
Hello, World
EML
receive_incoming_mail(
raw_email_data,
email_to: ir.incoming_email
)
# this should add to the number of incoming mails
expect(ir.incoming_messages.count).to eq(3)
end

it 'should append the email to every request matches, unless the requests has already received the email' do
info_request_1 = FactoryBot.create(:info_request)
info_request_2 = FactoryBot.create(:info_request)

expect(info_request_1.incoming_messages.count).to eq(0)
expect(info_request_2.incoming_messages.count).to eq(0)

raw_email_data = <<~EML
From: EMAIL_FROM
To: EMAIL_TO
Message-ID: [email protected]
Subject: Basic Email
Hello, World
EML

# send email to one request
receive_incoming_mail(
raw_email_data,
email_to: info_request_1.incoming_email
)

expect(info_request_1.incoming_messages.count).to eq(1)
expect(info_request_2.incoming_messages.count).to eq(0)

# send same email to both requests, should only be delivered to the
# request which hasn't already received the email
receive_incoming_mail(
raw_email_data,
email_to: [
info_request_1.incoming_email,
info_request_2.incoming_email
].join(', ')
)

expect(info_request_1.incoming_messages.count).to eq(1)
expect(info_request_2.incoming_messages.count).to eq(1)
end

it "should store mail in holding pen and send to admin when the email is not to any information request" do
ir = info_requests(:fancy_dog_request)
expect(ir.incoming_messages.count).to eq(1)
Expand Down

0 comments on commit 5a24157

Please sign in to comment.