From da115423221161ef39abf6d0b74f0a2d1c818182 Mon Sep 17 00:00:00 2001 From: link2xt Date: Thu, 4 Jan 2024 17:11:34 +0000 Subject: [PATCH] fix: do not remove contents from Schleuder ML messages Before this fix actual contents of the message reposted by Schleuder is considered a mailing list footer and removed, not visible even in the "Show Full Message..." view. With this change there will be two message bubbles, one for header and one for the contents, but it is still better than losing the contents completely. Attempting to parse header part is out of scope for this change. --- src/headerdef.rs | 3 ++ src/mimeparser.rs | 35 ++++++++++++++++- test-data/message/schleuder.eml | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 test-data/message/schleuder.eml diff --git a/src/headerdef.rs b/src/headerdef.rs index ca282a81b4..f65729c9a1 100644 --- a/src/headerdef.rs +++ b/src/headerdef.rs @@ -38,6 +38,9 @@ pub enum HeaderDef { /// Mailing list ID defined in [RFC 2919](https://tools.ietf.org/html/rfc2919). ListId, ListPost, + + /// List-Help header defined in [RFC 2369](https://datatracker.ietf.org/doc/html/rfc2369). + ListHelp, References, /// In-Reply-To header containing Message-ID of the parent message. diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 95aab357fa..0d1acef8fe 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -1365,6 +1365,15 @@ impl MimeMessage { self.get_mailinglist_header().is_some() } + /// Detects Schleuder mailing list by List-Help header. + pub(crate) fn is_schleuder_message(&self) -> bool { + if let Some(list_help) = self.get_header(HeaderDef::ListHelp) { + list_help == "" + } else { + false + } + } + pub fn replace_msg_by_error(&mut self, error_msg: &str) { self.is_system_message = SystemMessage::Unknown; if let Some(part) = self.parts.first_mut() { @@ -1593,8 +1602,12 @@ impl MimeMessage { /// eg. when the user-edited-content is html. /// As these footers would appear as repeated, separate text-bubbles, /// we remove them. + /// + /// We make an exception for Schleuder mailing lists + /// because they typically create messages with two text parts, + /// one for headers and one for the actual contents. fn maybe_remove_inline_mailinglist_footer(&mut self) { - if self.is_mailinglist_message() { + if self.is_mailinglist_message() && !self.is_schleuder_message() { let text_part_cnt = self .parts .iter() @@ -3786,4 +3799,24 @@ Content-Disposition: reaction\n\ Ok(()) } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_schleuder() -> Result<()> { + let context = TestContext::new_alice().await; + let raw = include_bytes!("../test-data/message/schleuder.eml"); + + let msg = MimeMessage::from_bytes(&context.ctx, &raw[..], None) + .await + .unwrap(); + assert_eq!(msg.parts.len(), 2); + + // Header part. + assert_eq!(msg.parts[0].typ, Viewtype::Text); + + // Actual contents part. + assert_eq!(msg.parts[1].typ, Viewtype::Text); + assert_eq!(msg.parts[1].msg, "hello,\nbye"); + + Ok(()) + } } diff --git a/test-data/message/schleuder.eml b/test-data/message/schleuder.eml new file mode 100644 index 0000000000..bdcbe492a7 --- /dev/null +++ b/test-data/message/schleuder.eml @@ -0,0 +1,66 @@ +Return-Path: +Delivered-To: alice@testrun.org +Date: Tue, 02 Jan 2024 05:00:00 +0000 +From: mailing-list@example.org +Sender: mailing-list-bounce@example.org +To: alice@testrun.org +Message-ID: <87wmss8juz.fsf@example.org> +In-Reply-To: +References: +Subject: [REPOST] Some subject +Mime-Version: 1.0 +Content-Type: multipart/signed; + boundary="--==_mimepart_65938a80866e8_663a2abed9b585c064398"; + micalg=pgp-sha1; + protocol="application/pgp-signature" +Content-Transfer-Encoding: 7bit +List-Id: +List-Owner: (Use list's public + key) +List-Help: +List-Post: + +This is an OpenPGP/MIME signed message (RFC 4880 and 3156) +----==_mimepart_65938a80866e8_663a2abed9b585c064398 +Content-Type: multipart/mixed; + boundary="--==_mimepart_65938a8086476_663a2abed9b585c0642c7"; + charset=UTF-8 +Content-Transfer-Encoding: 7bit + + +----==_mimepart_65938a8086476_663a2abed9b585c0642c7 +Content-Type: text/plain; + charset=UTF-8 +Content-Transfer-Encoding: 7bit + +From: bob@example.org +To: mailing-list@example.org +Cc: +Date: Tue, 02 Jan 2024 05:00:00 +0000 +Sig: Unsigned +Enc: Unencrypted + +----==_mimepart_65938a8086476_663a2abed9b585c0642c7 +Content-Type: text/plain; + charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +hello, +bye + +----==_mimepart_65938a8086476_663a2abed9b585c0642c7-- + +----==_mimepart_65938a80866e8_663a2abed9b585c064398 +Content-Type: application/pgp-signature; + name=signature.asc +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename=signature.asc +Content-Description: OpenPGP digital signature + +-----BEGIN PGP SIGNATURE----- + +REDACTED +-----END PGP SIGNATURE----- + +----==_mimepart_65938a80866e8_663a2abed9b585c064398--