Skip to content

Commit da11542

Browse files
committed
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.
1 parent 3bcdd17 commit da11542

File tree

3 files changed

+103
-1
lines changed

3 files changed

+103
-1
lines changed

src/headerdef.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ pub enum HeaderDef {
3838
/// Mailing list ID defined in [RFC 2919](https://tools.ietf.org/html/rfc2919).
3939
ListId,
4040
ListPost,
41+
42+
/// List-Help header defined in [RFC 2369](https://datatracker.ietf.org/doc/html/rfc2369).
43+
ListHelp,
4144
References,
4245

4346
/// In-Reply-To header containing Message-ID of the parent message.

src/mimeparser.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,15 @@ impl MimeMessage {
13651365
self.get_mailinglist_header().is_some()
13661366
}
13671367

1368+
/// Detects Schleuder mailing list by List-Help header.
1369+
pub(crate) fn is_schleuder_message(&self) -> bool {
1370+
if let Some(list_help) = self.get_header(HeaderDef::ListHelp) {
1371+
list_help == "<https://schleuder.org/>"
1372+
} else {
1373+
false
1374+
}
1375+
}
1376+
13681377
pub fn replace_msg_by_error(&mut self, error_msg: &str) {
13691378
self.is_system_message = SystemMessage::Unknown;
13701379
if let Some(part) = self.parts.first_mut() {
@@ -1593,8 +1602,12 @@ impl MimeMessage {
15931602
/// eg. when the user-edited-content is html.
15941603
/// As these footers would appear as repeated, separate text-bubbles,
15951604
/// we remove them.
1605+
///
1606+
/// We make an exception for Schleuder mailing lists
1607+
/// because they typically create messages with two text parts,
1608+
/// one for headers and one for the actual contents.
15961609
fn maybe_remove_inline_mailinglist_footer(&mut self) {
1597-
if self.is_mailinglist_message() {
1610+
if self.is_mailinglist_message() && !self.is_schleuder_message() {
15981611
let text_part_cnt = self
15991612
.parts
16001613
.iter()
@@ -3786,4 +3799,24 @@ Content-Disposition: reaction\n\
37863799

37873800
Ok(())
37883801
}
3802+
3803+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
3804+
async fn test_schleuder() -> Result<()> {
3805+
let context = TestContext::new_alice().await;
3806+
let raw = include_bytes!("../test-data/message/schleuder.eml");
3807+
3808+
let msg = MimeMessage::from_bytes(&context.ctx, &raw[..], None)
3809+
.await
3810+
.unwrap();
3811+
assert_eq!(msg.parts.len(), 2);
3812+
3813+
// Header part.
3814+
assert_eq!(msg.parts[0].typ, Viewtype::Text);
3815+
3816+
// Actual contents part.
3817+
assert_eq!(msg.parts[1].typ, Viewtype::Text);
3818+
assert_eq!(msg.parts[1].msg, "hello,\nbye");
3819+
3820+
Ok(())
3821+
}
37893822
}

test-data/message/schleuder.eml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
Return-Path: <mailing-list-bounce@example.org>
2+
Delivered-To: alice@testrun.org
3+
Date: Tue, 02 Jan 2024 05:00:00 +0000
4+
From: mailing-list@example.org
5+
Sender: mailing-list-bounce@example.org
6+
To: alice@testrun.org
7+
Message-ID: <87wmss8juz.fsf@example.org>
8+
In-Reply-To:
9+
References:
10+
Subject: [REPOST] Some subject
11+
Mime-Version: 1.0
12+
Content-Type: multipart/signed;
13+
boundary="--==_mimepart_65938a80866e8_663a2abed9b585c064398";
14+
micalg=pgp-sha1;
15+
protocol="application/pgp-signature"
16+
Content-Transfer-Encoding: 7bit
17+
List-Id: <mailing-list.example.org>
18+
List-Owner: <mailto:mailing-list-owner@example.org> (Use list's public
19+
key)
20+
List-Help: <https://schleuder.org/>
21+
List-Post: <mailto:mailing-list@example.org>
22+
23+
This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
24+
----==_mimepart_65938a80866e8_663a2abed9b585c064398
25+
Content-Type: multipart/mixed;
26+
boundary="--==_mimepart_65938a8086476_663a2abed9b585c0642c7";
27+
charset=UTF-8
28+
Content-Transfer-Encoding: 7bit
29+
30+
31+
----==_mimepart_65938a8086476_663a2abed9b585c0642c7
32+
Content-Type: text/plain;
33+
charset=UTF-8
34+
Content-Transfer-Encoding: 7bit
35+
36+
From: bob@example.org
37+
To: mailing-list@example.org
38+
Cc:
39+
Date: Tue, 02 Jan 2024 05:00:00 +0000
40+
Sig: Unsigned
41+
Enc: Unencrypted
42+
43+
----==_mimepart_65938a8086476_663a2abed9b585c0642c7
44+
Content-Type: text/plain;
45+
charset=utf-8
46+
Content-Transfer-Encoding: quoted-printable
47+
48+
hello,
49+
bye
50+
51+
----==_mimepart_65938a8086476_663a2abed9b585c0642c7--
52+
53+
----==_mimepart_65938a80866e8_663a2abed9b585c064398
54+
Content-Type: application/pgp-signature;
55+
name=signature.asc
56+
Content-Transfer-Encoding: 7bit
57+
Content-Disposition: attachment;
58+
filename=signature.asc
59+
Content-Description: OpenPGP digital signature
60+
61+
-----BEGIN PGP SIGNATURE-----
62+
63+
REDACTED
64+
-----END PGP SIGNATURE-----
65+
66+
----==_mimepart_65938a80866e8_663a2abed9b585c064398--

0 commit comments

Comments
 (0)