Skip to content

Commit a0ff0d7

Browse files
committed
fix: do not include CRLF before MIME boundary in the part body
This change adds a test and updates mailparse from 0.15.0 to 0.16.0. mailparse 0.16.0 includes a fix for the bug that resulted in CRLF being included at the end of the body. Workaround for the bug in the `pk_validate` function is also removed.
1 parent 0687264 commit a0ff0d7

File tree

5 files changed

+78
-13
lines changed

5 files changed

+78
-13
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ iroh = { version = "0.32", default-features = false }
6969
kamadak-exif = "0.6.1"
7070
lettre_email = { git = "https://github.com/deltachat/lettre", branch = "master" }
7171
libc = { workspace = true }
72-
mailparse = "0.15"
72+
mailparse = "0.16"
7373
mime = "0.3.17"
7474
num_cpus = "1.16"
7575
num-derive = "0.4"

src/html.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,6 @@ and will be wrapped as usual.<br/>
371371
mime-modified should not be set set as there is no html and no special stuff;<br/>
372372
although not being a delta-message.<br/>
373373
test some special html-characters as &lt; &gt; and &amp; but also &quot; and &#x27; :)<br/>
374-
<br/>
375374
</body></html>
376375
"#
377376
);
@@ -405,7 +404,6 @@ test some special html-characters as &lt; &gt; and &amp; but also &quot; and &#x
405404
r##"<html>
406405
<p>mime-modified <b>set</b>; simplify is always regarded as lossy.</p>
407406
</html>
408-
409407
"##
410408
);
411409
}
@@ -422,7 +420,6 @@ test some special html-characters as &lt; &gt; and &amp; but also &quot; and &#x
422420
this is <b>html</b>
423421
</p>
424422
</html>
425-
426423
"##
427424
);
428425
}

src/mimeparser/mimeparser_tests.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,3 +1817,78 @@ async fn test_protect_autocrypt() -> Result<()> {
18171817

18181818
Ok(())
18191819
}
1820+
1821+
/// Tests that CRLF before MIME boundary
1822+
/// is not treated as the part body.
1823+
///
1824+
/// RFC 2046 explicitly says that
1825+
/// "The CRLF preceding the boundary delimiter line is conceptually attached
1826+
/// to the boundary so that it is possible to have a part that does not end
1827+
/// with a CRLF (line break). Body parts that must be considered to end with
1828+
/// line breaks, therefore, must have two CRLFs preceding the boundary delimiter
1829+
/// line, the first of which is part of the preceding body part,
1830+
/// and the second of which is part of the encapsulation boundary."
1831+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
1832+
async fn test_mimeparser_trailing_newlines() {
1833+
let context = TestContext::new_alice().await;
1834+
1835+
// Example from <https://www.rfc-editor.org/rfc/rfc2046#section-5.1.1>
1836+
// with a `Content-Disposition` headers added to turn files
1837+
// into attachments.
1838+
let raw = b"From: Nathaniel Borenstein <nsb@bellcore.com>\r
1839+
To: Ned Freed <ned@innosoft.com>\r
1840+
Date: Sun, 21 Mar 1993 23:56:48 -0800 (PST)\r
1841+
Subject: Sample message\r
1842+
MIME-Version: 1.0\r
1843+
Content-type: multipart/mixed; boundary=\"simple boundary\"\r
1844+
\r
1845+
This is the preamble. It is to be ignored, though it\r
1846+
is a handy place for composition agents to include an\r
1847+
explanatory note to non-MIME conformant readers.\r
1848+
\r
1849+
--simple boundary\r
1850+
Content-Disposition: attachment; filename=\"file1.txt\"\r
1851+
\r
1852+
This is implicitly typed plain US-ASCII text.\r
1853+
It does NOT end with a linebreak.\r
1854+
--simple boundary\r
1855+
Content-type: text/plain; charset=us-ascii\r
1856+
Content-Disposition: attachment; filename=\"file2.txt\"\r
1857+
\r
1858+
This is explicitly typed plain US-ASCII text.\r
1859+
It DOES end with a linebreak.\r
1860+
\r
1861+
--simple boundary--\r
1862+
\r
1863+
This is the epilogue. It is also to be ignored.";
1864+
1865+
let mimeparser = MimeMessage::from_bytes(&context, &raw[..], None)
1866+
.await
1867+
.unwrap();
1868+
1869+
assert_eq!(mimeparser.parts.len(), 2);
1870+
1871+
assert_eq!(mimeparser.parts[0].typ, Viewtype::File);
1872+
let blob: BlobObject = mimeparser.parts[0]
1873+
.param
1874+
.get_blob(Param::File, &context)
1875+
.await
1876+
.unwrap()
1877+
.unwrap();
1878+
assert_eq!(
1879+
tokio::fs::read_to_string(blob.to_abs_path()).await.unwrap(),
1880+
"This is implicitly typed plain US-ASCII text.\r\nIt does NOT end with a linebreak."
1881+
);
1882+
1883+
assert_eq!(mimeparser.parts[1].typ, Viewtype::File);
1884+
let blob: BlobObject = mimeparser.parts[1]
1885+
.param
1886+
.get_blob(Param::File, &context)
1887+
.await
1888+
.unwrap()
1889+
.unwrap();
1890+
assert_eq!(
1891+
tokio::fs::read_to_string(blob.to_abs_path()).await.unwrap(),
1892+
"This is explicitly typed plain US-ASCII text.\r\nIt DOES end with a linebreak.\r\n"
1893+
);
1894+
}

src/pgp.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,6 @@ pub fn pk_validate(
379379

380380
let standalone_signature = StandaloneSignature::from_armor_single(Cursor::new(signature))?.0;
381381

382-
// Remove trailing CRLF before the delimiter.
383-
// According to RFC 3156 it is considered to be part of the MIME delimiter for the purpose of
384-
// OpenPGP signature calculation.
385-
let content = content
386-
.get(..content.len().saturating_sub(2))
387-
.context("index is out of range")?;
388-
389382
for pkey in public_keys_for_validation {
390383
if standalone_signature.verify(pkey, content).is_ok() {
391384
let fp = pkey.dc_fingerprint();

0 commit comments

Comments
 (0)