Skip to content

Commit

Permalink
feat: guessed mail don't go to holding pen
Browse files Browse the repository at this point in the history
Now, the 'Guessing' mechanism will be used when a mail is
received. If there is only one guess produced by this mechanism,
then the mail will go straight to that guess's IR
  • Loading branch information
alexander-griffen committed Jul 21, 2023
1 parent c41bf9c commit 7e67e21
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 45 deletions.
86 changes: 64 additions & 22 deletions app/mailers/request_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,21 @@ def comment_on_alert_plural(info_request, count, earliest_unalerted_comment)
)
end


def guess_email_request_address(email)
# Match the email address in the message without matching the hash
guess_addresses = MailHandler.get_all_addresses(email)
guessed_info_requests =
InfoRequest.guess_by_incoming_email(guess_addresses)

# Match the email subject in the message
guess_by_subject =
InfoRequest.guess_by_incoming_subject(email.subject)
(guessed_info_requests + guess_by_subject).
select(&:info_request).uniq(&:info_request).
map { |ir_guess| ir_guess.info_request }
end

# Class function, called by script/mailin with all incoming responses.
# [ This is a copy (Monkeypatch!) of function from action_mailer/base.rb,
# but which additionally passes the raw_email to the member function, as we
Expand All @@ -232,38 +247,65 @@ def self.receive(raw_email, source = :mailin)
# Find which info requests the email is for
def requests_matching_email(email)
addresses = MailHandler.get_all_addresses(email)
InfoRequest.matching_incoming_email(addresses)
addresses.concat MailHandler.get_emails_within_received_headers(email)
InfoRequest.matching_incoming_email(addresses.uniq)
end

def send_to_holding_pen(email, raw_email, opts)
opts[:rejected_reason] =
_("Could not identify the request from the email address")
request = InfoRequest.holding_pen_request
request.receive(email, raw_email, opts)
end

# Member function, called on the new class made in self.receive above
def receive(email, raw_email, source = :mailin)
opts = { source: source }
# Only check mail that doesn't have spam in the header
unless SpamAddress.spam?(MailHandler.get_all_addresses(email))
used_guesses = false
# Find exact matches for info requests
reply_info_requests = requests_matching_email(email)

# Find any guesses for info requests
guessed_info_requests = guess_email_request_address(email)
# If there are any guesses which aren't already in the reply_info_requests
# then add them, and set the 'used_guesses' flag to true for event logging
guessed_info_requests.each do |guess|
unless reply_info_requests.include?(guess)
reply_info_requests.append(guess)
used_guesses = true
end
end

# Find which info requests the email is for
reply_info_requests = requests_matching_email(email)

# Nothing found OR multiple different info requests, so save in holding pen
if reply_info_requests.empty? || reply_info_requests.count > 1
opts[:rejected_reason] =
_("Could not identify the request from the email address")
request = InfoRequest.holding_pen_request
# If there is only one info request matching mail, it gets attached to the
# request to be archived with it
if reply_info_requests.count == 1 and guessed_info_requests.count < 2
reply_info_request = reply_info_requests.first

unless SpamAddress.spam?(MailHandler.get_all_addresses(email))
request.receive(email, raw_email, opts)
end
return
end
# If environment variable STOP_DUPLICATES is set, don't send message
# with same id again
if ENV['STOP_DUPLICATES']
if reply_info_request.already_received?(email, raw_email)
raise "message #{ email.message_id } already received by request"
end
end

# Send the message to each request, to be archived with it
reply_info_requests.each do |reply_info_request|
# If environment variable STOP_DUPLICATES is set, don't send message with same id again
if ENV['STOP_DUPLICATES']
if reply_info_request.already_received?(email, raw_email)
raise "message #{ email.message_id } already received by request"
if used_guesses
reply_info_request.log_event(
'redeliver_incoming',
editor: 'automatic',
destination_request: reply_info_request,
)
end
end

reply_info_request.receive(email, raw_email, opts)
reply_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
send_to_holding_pen(email, raw_email, opts)
end
end
end

Expand Down
20 changes: 0 additions & 20 deletions spec/integration/admin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,6 @@
expect(page).to have_content "Only the authority can reply to this request"
end
end

it "guesses a misdirected request" do
info_request = FactoryBot.create(:info_request,
allow_new_responses_from: 'authority_only',
handle_rejected_responses: 'holding_pen')
mail_to = "request-#{info_request.id}[email protected]"
receive_incoming_mail('incoming-request-plain.email', email_to: mail_to)
interesting_email = last_holding_pen_mail

# now we add another message to the queue, which we're not interested in
receive_incoming_mail('incoming-request-plain.email',
email_to: info_request.incoming_email,
email_from: "")
expect(holding_pen_messages.length).to eq(2)
using_session(@admin) do
visit admin_raw_email_path interesting_email
expect(page).to have_content "Could not identify the request"
expect(page).to have_content info_request.title
end
end
end

describe 'generating an upload url' do
Expand Down
25 changes: 22 additions & 3 deletions spec/mailers/request_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,26 @@
deliveries = ActionMailer::Base.deliveries
expect(deliveries.size).to eq(1)
mail = deliveries[0]
expect(mail.to).to eq([ 'bob@localhost' ]) # to the user who sent fancy_dog_request
# to the user who sent fancy_dog_request
expect(mail.to).to eq(['bob@localhost'])
deliveries.clear
end

it "should append it to the appropriate request if there is only one guess of information request" do
ir = info_requests(:fancy_dog_request)
expect(ir.incoming_messages.count).to eq(1) # in the fixture
receive_incoming_mail(
'incoming-request-plain.email',
email_to: "request-#{ir.id}-#{ir.idhash}a@localhost"
)
expect(ir.incoming_messages.count).to eq(2) # one more arrives
expect(ir.info_request_events[-1].incoming_message_id).not_to be_nil

deliveries = ActionMailer::Base.deliveries
expect(deliveries.size).to eq(1)
mail = deliveries[0]
# to the user who sent fancy_dog_request
expect(mail.to).to eq(['bob@localhost'])
deliveries.clear
end

Expand Down Expand Up @@ -48,7 +67,6 @@
expect(InfoRequest.holding_pen_request.incoming_messages.count).to eq(1)
end


it "attaches messages with an info request address in the Received headers to the appropriate request" do
ir = info_requests(:fancy_dog_request)
expect(ir.incoming_messages.count).to eq(1) # in the fixture
Expand All @@ -69,7 +87,8 @@
deliveries = ActionMailer::Base.deliveries
expect(deliveries.size).to eq(1)
mail = deliveries[0]
expect(mail.to).to eq([ 'bob@localhost' ]) # to the user who sent fancy_dog_request
# to the user who sent fancy_dog_request
expect(mail.to).to eq(['bob@localhost'])
deliveries.clear
end

Expand Down

0 comments on commit 7e67e21

Please sign in to comment.