diff --git a/MimeKit/AsyncMimeReader.cs b/MimeKit/AsyncMimeReader.cs index 91e6b02c2e..3e484cfc88 100644 --- a/MimeKit/AsyncMimeReader.cs +++ b/MimeKit/AsyncMimeReader.cs @@ -178,7 +178,7 @@ async Task StepHeadersAsync (CancellationToken cancellationToken) if (await ReadAheadAsync (atleast, 0, cancellationToken).ConfigureAwait (false) < atleast) break; } while (true); - } else if (input[inputIndex] == (byte) 'F') { + } else if (input[inputIndex] == (byte) 'F' || input[inputIndex] == (byte) '>') { // Check for an mbox-style From-line. Again, if the message is properly formatted and not truncated, this will NEVER happen. do { unsafe { diff --git a/UnitTests/ExperimentalMimeParserTests.cs b/UnitTests/ExperimentalMimeParserTests.cs index 1f6c40ef2a..5e9cfca4c6 100644 --- a/UnitTests/ExperimentalMimeParserTests.cs +++ b/UnitTests/ExperimentalMimeParserTests.cs @@ -2571,6 +2571,80 @@ public async Task TestMimePartBasicAsync () } } + [Test] + public void TestGarbageBeforeMessageHeaders () + { + string text = @">F!&^#%&^ +From: mimekit@example.com +To: mimekit@example.com +Subject: This message has garbage before the headers +Date: Tue, 12 Nov 2013 09:12:42 -0500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 + +This is the message body. +".Replace ("\r\n", "\n"); + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseMessage ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseMessage ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseMessageAsync ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseMessageAsync ()); + } + } + + [Test] + public void TestGarbageBeforeEntityHeaders () + { + string text = @">F!&^#%&^ +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 + +This is the message body. +".Replace ("\r\n", "\n"); + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseEntity ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseEntity ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseEntityAsync ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseEntityAsync ()); + } + } + static void AssertSimpleMbox (Stream stream) { var parser = new ExperimentalMimeParser (stream, MimeFormat.Mbox); diff --git a/UnitTests/MimeParserTests.cs b/UnitTests/MimeParserTests.cs index 4d8c007b28..f72ef1ea9e 100644 --- a/UnitTests/MimeParserTests.cs +++ b/UnitTests/MimeParserTests.cs @@ -2555,6 +2555,80 @@ public async Task TestMimePartBasicAsync () } } + [Test] + public void TestGarbageBeforeMessageHeaders () + { + string text = @">F!&^#%&^ +From: mimekit@example.com +To: mimekit@example.com +Subject: This message has garbage before the headers +Date: Tue, 12 Nov 2013 09:12:42 -0500 +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 + +This is the message body. +".Replace ("\r\n", "\n"); + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseMessage ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseMessage ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseMessageAsync ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseMessageAsync ()); + } + } + + [Test] + public void TestGarbageBeforeEntityHeaders () + { + string text = @">F!&^#%&^ +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 + +This is the message body. +".Replace ("\r\n", "\n"); + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseEntity ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.Throws (() => parser.ParseEntity ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseEntityAsync ()); + } + + using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) { + var parser = new MimeParser (stream, MimeFormat.Entity); + + Assert.ThrowsAsync (async () => await parser.ParseEntityAsync ()); + } + } + static void AssertSimpleMbox (Stream stream) { var parser = new MimeParser (stream, MimeFormat.Mbox);