FIX: Handle incoming emails without email address in From header (#5177)
This commit is contained in:
parent
6831efe2e9
commit
31ecb4fecf
|
@ -36,6 +36,7 @@ module Email
|
||||||
def handle_failure(mail_string, e, incoming_email)
|
def handle_failure(mail_string, e, incoming_email)
|
||||||
message_template = case e
|
message_template = case e
|
||||||
when Email::Receiver::EmptyEmailError then :email_reject_empty
|
when Email::Receiver::EmptyEmailError then :email_reject_empty
|
||||||
|
when Email::Receiver::NoSenderDetectedError then :email_reject_empty
|
||||||
when Email::Receiver::NoBodyDetectedError then :email_reject_empty
|
when Email::Receiver::NoBodyDetectedError then :email_reject_empty
|
||||||
when Email::Receiver::UserNotFoundError then :email_reject_user_not_found
|
when Email::Receiver::UserNotFoundError then :email_reject_user_not_found
|
||||||
when Email::Receiver::ScreenedEmailError then :email_reject_screened_email
|
when Email::Receiver::ScreenedEmailError then :email_reject_screened_email
|
||||||
|
|
|
@ -16,6 +16,7 @@ module Email
|
||||||
class AutoGeneratedEmailError < ProcessingError; end
|
class AutoGeneratedEmailError < ProcessingError; end
|
||||||
class BouncedEmailError < ProcessingError; end
|
class BouncedEmailError < ProcessingError; end
|
||||||
class NoBodyDetectedError < ProcessingError; end
|
class NoBodyDetectedError < ProcessingError; end
|
||||||
|
class NoSenderDetectedError < ProcessingError; end
|
||||||
class InactiveUserError < ProcessingError; end
|
class InactiveUserError < ProcessingError; end
|
||||||
class BlockedUserError < ProcessingError; end
|
class BlockedUserError < ProcessingError; end
|
||||||
class BadDestinationAddress < ProcessingError; end
|
class BadDestinationAddress < ProcessingError; end
|
||||||
|
@ -75,6 +76,7 @@ module Email
|
||||||
|
|
||||||
def process_internal
|
def process_internal
|
||||||
raise BouncedEmailError if is_bounce?
|
raise BouncedEmailError if is_bounce?
|
||||||
|
raise NoSenderDetectedError if @from_email.blank?
|
||||||
raise ScreenedEmailError if ScreenedEmail.should_block?(@from_email)
|
raise ScreenedEmailError if ScreenedEmail.should_block?(@from_email)
|
||||||
|
|
||||||
user = find_or_create_user(@from_email, @from_display_name)
|
user = find_or_create_user(@from_email, @from_display_name)
|
||||||
|
@ -273,14 +275,27 @@ module Email
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if mail.from[/<[^>]+>/]
|
return extract_from_address_and_name(mail.from) if mail.from.is_a? String
|
||||||
from_address = mail.from[/<([^>]+)>/, 1]
|
|
||||||
from_display_name = mail.from[/^([^<]+)/, 1]
|
if mail.from.is_a? Mail::AddressContainer
|
||||||
|
mail.from.each do |from|
|
||||||
|
from_address, from_display_name = extract_from_address_and_name(from)
|
||||||
|
return [from_address, from_display_name] if from_address
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (from_address.blank? || !from_address["@"]) && mail.from[/\[mailto:[^\]]+\]/]
|
nil
|
||||||
from_address = mail.from[/\[mailto:([^\]]+)\]/, 1]
|
end
|
||||||
from_display_name = mail.from[/^([^\[]+)/, 1]
|
|
||||||
|
def extract_from_address_and_name(value)
|
||||||
|
if value[/<[^>]+>/]
|
||||||
|
from_address = value[/<([^>]+)>/, 1]
|
||||||
|
from_display_name = value[/^([^<]+)/, 1]
|
||||||
|
end
|
||||||
|
|
||||||
|
if (from_address.blank? || !from_address["@"]) && value[/\[mailto:[^\]]+\]/]
|
||||||
|
from_address = value[/\[mailto:([^\]]+)\]/, 1]
|
||||||
|
from_display_name = value[/^([^\[]+)/, 1]
|
||||||
end
|
end
|
||||||
|
|
||||||
[from_address&.downcase, from_display_name&.strip]
|
[from_address&.downcase, from_display_name&.strip]
|
||||||
|
|
|
@ -37,6 +37,10 @@ describe Email::Receiver do
|
||||||
expect { process(:no_body) }.to raise_error(Email::Receiver::NoBodyDetectedError)
|
expect { process(:no_body) }.to raise_error(Email::Receiver::NoBodyDetectedError)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "raises a NoSenderDetectedError when the From header is missing" do
|
||||||
|
expect { process(:no_from) }.to raise_error(Email::Receiver::NoSenderDetectedError)
|
||||||
|
end
|
||||||
|
|
||||||
it "raises an InactiveUserError when the sender is inactive" do
|
it "raises an InactiveUserError when the sender is inactive" do
|
||||||
Fabricate(:user, email: "inactive@bar.com", active: false)
|
Fabricate(:user, email: "inactive@bar.com", active: false)
|
||||||
expect { process(:inactive_sender) }.to raise_error(Email::Receiver::InactiveUserError)
|
expect { process(:inactive_sender) }.to raise_error(Email::Receiver::InactiveUserError)
|
||||||
|
@ -229,10 +233,14 @@ describe Email::Receiver do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "handles invalid from header" do
|
it "handles invalid from header" do
|
||||||
expect { process(:invalid_from) }.to change { topic.posts.count }
|
expect { process(:invalid_from_1) }.to change { topic.posts.count }
|
||||||
expect(topic.posts.last.raw).to eq("This email was sent with an invalid from header field.")
|
expect(topic.posts.last.raw).to eq("This email was sent with an invalid from header field.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "raises a NoSenderDetectedError when the From header doesn't contain an email address" do
|
||||||
|
expect { process(:invalid_from_2) }.to raise_error(Email::Receiver::NoSenderDetectedError)
|
||||||
|
end
|
||||||
|
|
||||||
it "doesn't raise an AutoGeneratedEmailError when the mail is auto generated but is whitelisted" do
|
it "doesn't raise an AutoGeneratedEmailError when the mail is auto generated but is whitelisted" do
|
||||||
SiteSetting.auto_generated_whitelist = "foo@bar.com|discourse@bar.com"
|
SiteSetting.auto_generated_whitelist = "foo@bar.com|discourse@bar.com"
|
||||||
expect { process(:auto_generated_whitelisted) }.to change { topic.posts.count }
|
expect { process(:auto_generated_whitelisted) }.to change { topic.posts.count }
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
Return-Path: <MAILER-DAEMON>
|
||||||
|
Date: Fri, 25 Aug 2017 21:25:34 +0000 (UTC)
|
||||||
|
From: MAILER-DAEMON (Mail Delivery System)
|
||||||
|
Subject: Undelivered Mail Returned to Sender
|
||||||
|
To: foo@example.com
|
||||||
|
Message-Id: <12345@foo.bar.mail>
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
|
||||||
|
This is a mail with an invalid from header that can't be fixed.
|
||||||
|
It's missing the sender's email address.
|
|
@ -0,0 +1,9 @@
|
||||||
|
To: meat@bar.com
|
||||||
|
Date: Mon, 1 Feb 2016 00:12:43 +0100
|
||||||
|
Message-ID: <40@foo.bar.mail>
|
||||||
|
Mime-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
Subject: Nobody sent this
|
||||||
|
|
||||||
|
This is an email without a FROM header.
|
Loading…
Reference in New Issue