FIX: Use original from address when forwarding to group inbox (#14114)

FIX: Use original from address when forwarding to group inbox (#14114)

When emails were forwarded to a group inbox by the email address of the group, for example when an email ends up in spam and must be manually forwarded to the group+site@discoursemail.com address, the OP of the topic ended up being the group’s email address instead of the sender who originally sent the email to the group inbox.

This commit detects that an email has been forwarded using existing tools, and if the from address matches one of the group incoming email addresses, then we look at the forwarded email’s from address and use that instead for the incoming email from address as well as the staged/regular user used for the Topic.user.

This will make it much cleaner to forward emails into a group inbox, and will prevent issues with PostAlerter where the OP is double-notified for these emails.

diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb
index f513a37..cba2208 100644
--- a/lib/email/receiver.rb
+++ b/lib/email/receiver.rb
@@ -584,6 +584,20 @@ module Email
 
       return unless mail[:from]
 
+      # For forwarded emails, where the from address matches a group incoming
+      # email, we want to use the from address of the original email sender,
+      # which we can extract from embedded_email_raw.
+      if has_been_forwarded?
+        if mail[:from].to_s =~ group_incoming_emails_regex && embedded_email[:from].errors.blank?
+          embedded_email[:from].each do |address_field|
+            from_address = address_field.address
+            from_display_name = address_field.display_name&.to_s
+            next if !from_address&.include?("@")
+            return [from_address&.downcase, from_display_name&.strip]
+          end
+        end
+      end
+
       # For now we are only using the Reply-To header if the email has
       # been forwarded via Google Groups, which is why we are checking the
       # X-Original-From header too. In future we may want to use the Reply-To
@@ -885,6 +899,10 @@ module Email
       @embedded_email_raw
     end
 
+    def embedded_email
+      @embedded_email ||= embedded_email_raw.present? ? Mail.new(embedded_email_raw) : nil
+    end
+
     def process_forwarded_email(destination, user)
       user ||= stage_from_user
       case SiteSetting.forwarded_emails_behaviour
diff --git a/spec/components/email/receiver_spec.rb b/spec/components/email/receiver_spec.rb
index d14b01b..cef30c1 100644
--- a/spec/components/email/receiver_spec.rb
+++ b/spec/components/email/receiver_spec.rb
@@ -1032,10 +1032,31 @@ describe Email::Receiver do
       end
     end
 
+    context "when a group forwards an email to its inbox" do
+      let!(:topic) do
+        group.update!(
+          email_username: "team@somesmtpaddress.com",
+          incoming_email: "team@somesmtpaddress.com|support+team@bar.com",
+          smtp_server: "smtp.test.com",
+          smtp_port: 587,
+          smtp_ssl: true,
+          smtp_enabled: true
+        )
+        process(:forwarded_by_group_to_group)
+        Topic.last
+      end
+
+      it "does not use the team's address as the from_address; it uses the original sender address" do
+        expect(topic.incoming_email.first.to_addresses).to include("support+team@bar.com")
+        expect(topic.incoming_email.first.from_address).to eq("fred@bedrock.com")
+      end
+    end
+
     context "emailing a group by email_username and following reply flow" do
       let!(:original_inbound_email_topic) do
         group.update!(
           email_username: "team@somesmtpaddress.com",
+          incoming_email: "team@somesmtpaddress.com|suppor+team@bar.com",
           smtp_server: "smtp.test.com",
           smtp_port: 587,
           smtp_ssl: true,
diff --git a/spec/fixtures/emails/forwarded_by_group_to_group.eml b/spec/fixtures/emails/forwarded_by_group_to_group.eml
new file mode 100644
index 0000000..fe170e5
--- /dev/null
+++ b/spec/fixtures/emails/forwarded_by_group_to_group.eml
@@ -0,0 +1,34 @@
+Message-ID: <58@somesmtpaddress.mail>
+From: Discourse Team <team@somesmtpaddress.com>
+To: support+team@bar.com
+Date: Mon, 1 Dec 2016 13:37:42 +0100
+Subject: Fwd: Login problems
+Content-Type: multipart/related; boundary="00000000000072702105c89858de"
+
+--00000000000072702105c89858de
+Content-Type: multipart/alternative; boundary="00000000000072702005c89858dd"
+
+--00000000000072702005c89858dd
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+---------- Forwarded message ---------
+From: Fred Flintstone <fred@bedrock.com>
+Date: Mon, 1 Dec 2016 13:37:42 +0100
+Subject: Re: Login problems
+To: Discourse Team <team@somesmtpaddress.com>
+
+Hello I am having some issues with my forum.
+
+Fred
+
+--00000000000072702005c89858dd
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+<p>Hello I am having some issues with my forum.</p>
+
+<br>Fred<br>
+
+--00000000000072702005c89858dd--
+--00000000000072702105c89858de

GitHub sha: 2ac9fd9dff5a2a9210e2b1b765e1a324bbb4f421

This commit appears in #14114 which was approved by lis2. It was merged by martin.