Skip to content

Commit

Permalink
Fix ingress controllers' ability to accept non UTF-8 encoded emails
Browse files Browse the repository at this point in the history
Since most of the ingress controllers receive raw MIME data in POST body,
it is impossible to guaratee that these are in UTF-8 as email comes in all
possible encodings.

This patch disables force transcoding to UTF-8 by ActionController params
processing for params that contain RAW MIME email bodies.

Fix #46297
  • Loading branch information
honzasterba committed Dec 30, 2022
1 parent e6f12f5 commit 4b85118
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 0 deletions.
6 changes: 6 additions & 0 deletions actionmailbox/CHANGELOG.md
@@ -1,3 +1,9 @@
* Fixed ingress controllers' ability to accept emails that contain no UTF-8 encoded parts.

Fixes #46297.

*Jan Honza Sterba*

* Add X-Forwarded-To addresses to recipients.

*Andrew Stewart*
Expand Down
Expand Up @@ -44,6 +44,7 @@ module ActionMailbox
# <tt>https://example.com/rails/action_mailbox/mailgun/inbound_emails/mime</tt>.
class Ingresses::Mailgun::InboundEmailsController < ActionMailbox::BaseController
before_action :authenticate
param_encoding :create, "body-mime", Encoding::ASCII_8BIT

def create
ActionMailbox::InboundEmail.create_and_extract_message_id! mail
Expand Down
Expand Up @@ -46,6 +46,7 @@ module ActionMailbox
# content in JSON payload"*. Action Mailbox needs the raw email content to work.
class Ingresses::Postmark::InboundEmailsController < ActionMailbox::BaseController
before_action :authenticate_by_password
param_encoding :create, "RawEmail", Encoding::ASCII_8BIT

def create
ActionMailbox::InboundEmail.create_and_extract_message_id! params.require("RawEmail")
Expand Down
Expand Up @@ -46,6 +46,7 @@ module ActionMailbox
# full MIME message."* Action Mailbox needs the raw MIME message to work.
class Ingresses::Sendgrid::InboundEmailsController < ActionMailbox::BaseController
before_action :authenticate_by_password
param_encoding :create, :email, Encoding::ASCII_8BIT

def create
ActionMailbox::InboundEmail.create_and_extract_message_id! mail
Expand Down
Expand Up @@ -25,6 +25,24 @@ class ActionMailbox::Ingresses::Mailgun::InboundEmailsControllerTest < ActionDis
assert_equal "0CB459E0-0336-41DA-BC88-E6E28C697DDB@37signals.com", inbound_email.message_id
end

test "receiving an inbound email from Mailgun with non UTF-8 characters" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
travel_to "2018-10-09 15:15:00 EDT"
post rails_mailgun_inbound_emails_url, params: {
timestamp: 1539112500,
token: "7VwW7k6Ak7zcTwoSoNm7aTtbk1g67MKAnsYLfUB7PdszbgR5Xi",
signature: "ef24c5225322217bb065b80bb54eb4f9206d764e3e16abab07f0a64d1cf477cc",
"body-mime" => file_fixture("../files/invalid_utf.eml").read
}
end

assert_response :no_content

inbound_email = ActionMailbox::InboundEmail.last
assert_equal file_fixture("../files/invalid_utf.eml").binread, inbound_email.raw_email.download
assert_equal "05988AA6EC0D44318855A5E39E3B6F9E@jansterba.com", inbound_email.message_id
end

test "add X-Original-To to email from Mailgun" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
travel_to "2018-10-09 15:15:00 EDT"
Expand Down
Expand Up @@ -18,6 +18,19 @@ class ActionMailbox::Ingresses::Postmark::InboundEmailsControllerTest < ActionDi
assert_equal "0CB459E0-0336-41DA-BC88-E6E28C697DDB@37signals.com", inbound_email.message_id
end

test "receiving an inbound email from Postmark with non UTF-8 characters" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
post rails_postmark_inbound_emails_url,
headers: { authorization: credentials }, params: { RawEmail: file_fixture("../files/invalid_utf.eml").read }
end

assert_response :no_content

inbound_email = ActionMailbox::InboundEmail.last
assert_equal file_fixture("../files/invalid_utf.eml").binread, inbound_email.raw_email.download
assert_equal "05988AA6EC0D44318855A5E39E3B6F9E@jansterba.com", inbound_email.message_id
end

test "rejecting when RawEmail param is missing" do
assert_no_difference -> { ActionMailbox::InboundEmail.count } do
post rails_postmark_inbound_emails_url,
Expand Down
Expand Up @@ -18,6 +18,19 @@ class ActionMailbox::Ingresses::Relay::InboundEmailsControllerTest < ActionDispa
assert_equal "0CB459E0-0336-41DA-BC88-E6E28C697DDB@37signals.com", inbound_email.message_id
end

test "receiving an inbound email relayed from an SMTP server with non UTF-8 characters" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
post rails_relay_inbound_emails_url, headers: { "Authorization" => credentials, "Content-Type" => "message/rfc822" },
params: file_fixture("../files/invalid_utf.eml").read
end

assert_response :no_content

inbound_email = ActionMailbox::InboundEmail.last
assert_equal file_fixture("../files/invalid_utf.eml").binread, inbound_email.raw_email.download
assert_equal "05988AA6EC0D44318855A5E39E3B6F9E@jansterba.com", inbound_email.message_id
end

test "rejecting an unauthorized inbound email" do
assert_no_difference -> { ActionMailbox::InboundEmail.count } do
post rails_relay_inbound_emails_url, headers: { "Content-Type" => "message/rfc822" },
Expand Down
Expand Up @@ -18,6 +18,19 @@ class ActionMailbox::Ingresses::Sendgrid::InboundEmailsControllerTest < ActionDi
assert_equal "0CB459E0-0336-41DA-BC88-E6E28C697DDB@37signals.com", inbound_email.message_id
end

test "receiving an inbound email from Sendgrid with non UTF-8 characters" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
post rails_sendgrid_inbound_emails_url,
headers: { authorization: credentials }, params: { email: file_fixture("../files/invalid_utf.eml").read }
end

assert_response :no_content

inbound_email = ActionMailbox::InboundEmail.last
assert_equal file_fixture("../files/invalid_utf.eml").binread, inbound_email.raw_email.download
assert_equal "05988AA6EC0D44318855A5E39E3B6F9E@jansterba.com", inbound_email.message_id
end

test "add X-Original-To to email from Sendgrid" do
assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do
post rails_sendgrid_inbound_emails_url,
Expand Down
39 changes: 39 additions & 0 deletions actionmailbox/test/fixtures/files/invalid_utf.eml
@@ -0,0 +1,39 @@
thread-index: Adjkg/rniynGRZvvRu2Ftd4zu7/YrA==
Thread-Topic: =?iso-8859-2?Q?Informace_o_skladov=FDch_z=E1sob=E1ch_Copmany?=
From: <info@sender.com>
To: <info@recipient.cz>,
Message-ID: <05988AA6EC0D44318855A5E39E3B6F9E@jansterba.com>
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_168F_01D8E494.BE7019A0"
Content-Class: urn:content-classes:message
Importance: normal
Priority: normal
X-MimeOLE: Produced By Microsoft MimeOLE V6.3.9600.20564
X-EOPAttributedMessage: 0
X-Spam-IndexStatus: 0

This is a multi-part message in MIME format.

------=_NextPart_000_168F_01D8E494.BE7019A0
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_1690_01D8E494.BE7019A0"
------=_NextPart_001_1690_01D8E494.BE7019A0
Content-Type: text/plain;
charset="iso-8859-2"
Content-Transfer-Encoding: quoted-printable
V=E1=BEen=FD z=E1kazn=EDku,
v p=F8=EDloze zas=EDl=E1me aktu=E1ln=ED informace o skladov=FDch =
z=E1sob=E1ch.
------=_NextPart_001_1690_01D8E494.BE7019A0
Content-Type: text/html;
charset="iso-8859-2"
Content-Transfer-Encoding: 8bit

Vá¾ený zákazníku,<p>v pøíloze zasíláme aktuální informace o skladových zásobách.

------=_NextPart_000_168F_01D8E494.BE7019A0--

0 comments on commit 4b85118

Please sign in to comment.