public void TestParseShortDovecotExampleThread() { const string text = "((352)(381))\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { IList <MessageThread> threads; engine.SetStream(tokenizer); try { threads = ImapUtils.ParseThreadsAsync(engine, 0, false, CancellationToken.None).GetAwaiter().GetResult(); } catch (Exception ex) { Assert.Fail("Parsing THREAD response failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.AreEqual(1, threads.Count, "Expected 1 thread."); Assert.AreEqual((uint)0, threads[0].UniqueId.Value.Id); var children = threads[0].Children; Assert.AreEqual(2, children.Count, "Expected 2 children."); Assert.AreEqual((uint)352, children[0].UniqueId.Value.Id); Assert.AreEqual((uint)381, children[1].UniqueId.Value.Id); } } } }
public void TestParseDovcotEnvelopeWithGroupAddresses() { const string text = "(\"Mon, 13 Jul 2015 21:15:32 -0400\" \"Test message\" ((\"Example From\" NIL \"from\" \"example.com\")) ((\"Example Sender\" NIL \"sender\" \"example.com\")) ((\"Example Reply-To\" NIL \"reply-to\" \"example.com\")) ((NIL NIL \"boys\" NIL)(NIL NIL \"aaron\" \"MISSING_DOMAIN\")(NIL NIL \"jeff\" \"MISSING_DOMAIN\")(NIL NIL \"zach\" \"MISSING_DOMAIN\")(NIL NIL NIL NIL)(NIL NIL \"girls\" NIL)(NIL NIL \"alice\" \"MISSING_DOMAIN\")(NIL NIL \"hailey\" \"MISSING_DOMAIN\")(NIL NIL \"jenny\" \"MISSING_DOMAIN\")(NIL NIL NIL NIL)) NIL NIL NIL \"<*****@*****.**>\")"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { Envelope envelope; engine.SetStream(tokenizer); try { envelope = ImapUtils.ParseEnvelope(engine, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing ENVELOPE failed: {0}", ex); return; } Assert.AreEqual("\"Example Sender\" <*****@*****.**>", envelope.Sender.ToString()); Assert.AreEqual("\"Example From\" <*****@*****.**>", envelope.From.ToString()); Assert.AreEqual("\"Example Reply-To\" <*****@*****.**>", envelope.ReplyTo.ToString()); Assert.AreEqual("boys: aaron, jeff, zach;, girls: alice, hailey, jenny;", envelope.To.ToString()); } } } }
public void TestParseLongDovecotExampleThread() { const string text = "(3 4 5 6 7)(1)((2)(8)(15))(9)(16)(10)(11)(12 13)(14)(17)(18)(19)(20)(21)(22)(23)(24)(25 (26)(29 39)(31)(32))(27)(28)(38 35)(30 33 34)(37)(36)(40)(41)((42 43)(44)(48)(49)(50)(51 52))(45)((46)(55))(47)(53)(54)(56)(57 (58)(59)(60)(63))((61)(62))(64)(65)(70)((66)(67)(68)(69)(71))(72 73 (74)(75)(76 77))\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { IList <MessageThread> threads; engine.SetStream(tokenizer); try { threads = ImapUtils.ParseThreadsAsync(engine, 0, false, CancellationToken.None).GetAwaiter().GetResult(); } catch (Exception ex) { Assert.Fail("Parsing THREAD response failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.AreEqual(40, threads.Count, "Expected 40 threads."); Assert.AreEqual((uint)3, threads[0].UniqueId.Value.Id); Assert.AreEqual((uint)1, threads[1].UniqueId.Value.Id); Assert.AreEqual((uint)0, threads[2].UniqueId.Value.Id); var branches = threads[2].Children.ToArray(); Assert.AreEqual(3, branches.Length, "Expected 3 children."); } } } }
public void TestFormattingNonSequentialUids() { UniqueId[] uids = new UniqueId[] { new UniqueId(1), new UniqueId(3), new UniqueId(5), new UniqueId(7), new UniqueId(9) }; string expect = "1,3,5,7,9"; string actual; actual = ImapUtils.FormatUidSet(uids); Assert.AreEqual(expect, actual, "Formatting a non-sequential list of uids."); }
public void TestParseExampleThreads() { const string text = "(2)(3 6 (4 23)(44 7 96))\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { IList <MessageThread> threads; engine.SetStream(tokenizer); try { threads = ImapUtils.ParseThreads(engine, 0, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing THREAD response failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.AreEqual(2, threads.Count, "Expected 2 threads."); Assert.AreEqual((uint)2, threads[0].UniqueId.Value.Id); Assert.AreEqual((uint)3, threads[1].UniqueId.Value.Id); var branches = threads[1].Children.ToArray(); Assert.AreEqual(1, branches.Length, "Expected 1 child."); Assert.AreEqual((uint)6, branches[0].UniqueId.Value.Id); branches = branches[0].Children.ToArray(); Assert.AreEqual(2, branches.Length, "Expected 2 branches."); Assert.AreEqual((uint)4, branches[0].UniqueId.Value.Id); Assert.AreEqual((uint)44, branches[1].UniqueId.Value.Id); var children = branches[0].Children.ToArray(); Assert.AreEqual(1, children.Length, "Expected 1 child."); Assert.AreEqual((uint)23, children[0].UniqueId.Value.Id); Assert.AreEqual(0, children[0].Children.Count(), "Expected no children."); children = branches[1].Children.ToArray(); Assert.AreEqual(1, children.Length, "Expected 1 child."); Assert.AreEqual((uint)7, children[0].UniqueId.Value.Id); children = children[0].Children.ToArray(); Assert.AreEqual(1, children.Length, "Expected 1 child."); Assert.AreEqual((uint)96, children[0].UniqueId.Value.Id); Assert.AreEqual(0, children[0].Children.Count(), "Expected no children."); } } } }
public void TestFormattingSimpleUidRange() { UniqueId[] uids = new UniqueId[] { new UniqueId(1), new UniqueId(2), new UniqueId(3), new UniqueId(4), new UniqueId(5), new UniqueId(6), new UniqueId(7), new UniqueId(8), new UniqueId(9) }; string expect = "1:9"; string actual; actual = ImapUtils.FormatUidSet(uids); Assert.AreEqual(expect, actual, "Formatting a simple range of uids failed."); }
public void TestFormattingComplexSetOfUids() { UniqueId[] uids = new UniqueId[] { new UniqueId(1), new UniqueId(2), new UniqueId(3), new UniqueId(5), new UniqueId(6), new UniqueId(9), new UniqueId(10), new UniqueId(11), new UniqueId(12), new UniqueId(15), new UniqueId(19), new UniqueId(20) }; string expect = "1:3,5:6,9:12,15,19:20"; string actual; actual = ImapUtils.FormatUidSet(uids); Assert.AreEqual(expect, actual, "Formatting a complex list of uids."); }
public void TestParseMultipartBodyStructureWithoutBodyFldDsp() { // Test case from https://stackoverflow.com/questions/33481604/mailkit-fetch-unexpected-token-in-imap-response-qstring-multipart-message const string text = "((\"text\" \"plain\" (\"charset\" \"UTF-8\") NIL \"Message text\" \"Quoted-printable\" 209 6 NIL (\"inline\" NIL) NIL NIL)(\"text\" \"xml\" (\"name\" \"4441004299066.xml\") NIL \"4441004299066.xml\" \"Base64\" 10642 137 NIL (\"inline\" (\"filename\" \"4441004299066.xml\")) NIL NIL)(\"application\" \"pdf\" (\"name\" \"4441004299066.pdf\") NIL \"4441004299066.pdf\" \"Base64\" 48448 NIL (\"inline\" (\"filename\" \"4441004299066.pdf\")) NIL NIL) \"mixed\" (\"boundary\" \"6624CFB2_17170C36_Synapse_boundary\") \"Multipart message\" NIL)\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { BodyPartMultipart multipart; BodyPartBasic basic; BodyPart body; engine.SetStream(tokenizer); try { body = ImapUtils.ParseBodyAsync(engine, "Unexpected token: {0}", string.Empty, false, CancellationToken.None).GetAwaiter().GetResult(); } catch (Exception ex) { Assert.Fail("Parsing BODYSTRUCTURE failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.IsInstanceOf <BodyPartMultipart> (body, "Body types did not match."); multipart = (BodyPartMultipart)body; Assert.IsTrue(body.ContentType.IsMimeType("multipart", "mixed"), "Content-Type did not match."); Assert.AreEqual("6624CFB2_17170C36_Synapse_boundary", body.ContentType.Parameters ["boundary"], "boundary param did not match"); Assert.AreEqual(3, multipart.BodyParts.Count, "BodyParts count does not match."); Assert.IsInstanceOf <BodyPartText> (multipart.BodyParts[0], "The type of the first child does not match."); basic = (BodyPartBasic)multipart.BodyParts[0]; Assert.AreEqual("plain", basic.ContentType.MediaSubtype, "Content-Type did not match."); Assert.AreEqual("Message text", basic.ContentDescription, "Content-Description does not match."); Assert.IsInstanceOf <BodyPartText> (multipart.BodyParts[1], "The type of the second child does not match."); basic = (BodyPartBasic)multipart.BodyParts[1]; Assert.AreEqual("xml", basic.ContentType.MediaSubtype, "Content-Type did not match."); Assert.AreEqual("4441004299066.xml", basic.ContentDescription, "Content-Description does not match."); Assert.IsInstanceOf <BodyPartBasic> (multipart.BodyParts[2], "The type of the third child does not match."); basic = (BodyPartBasic)multipart.BodyParts[2]; Assert.AreEqual("application", basic.ContentType.MediaType, "Content-Type did not match."); Assert.AreEqual("pdf", basic.ContentType.MediaSubtype, "Content-Type did not match."); Assert.AreEqual("4441004299066.pdf", basic.ContentDescription, "Content-Description does not match."); } } } }
public void TestParseExampleEnvelopeRfc3501() { const string text = "(\"Wed, 17 Jul 1996 02:23:25 -0700 (PDT)\" \"IMAP4rev1 WG mtg summary and minutes\" ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((\"Terry Gray\" NIL \"gray\" \"cac.washington.edu\")) ((NIL NIL \"imap\" \"cac.washington.edu\")) ((NIL NIL \"minutes\" \"CNRI.Reston.VA.US\") (\"John Klensin\" NIL \"KLENSIN\" \"MIT.EDU\")) NIL NIL \"<*****@*****.**>\")\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { Envelope envelope; engine.SetStream(tokenizer); try { envelope = ImapUtils.ParseEnvelope(engine, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing ENVELOPE failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.IsTrue(envelope.Date.HasValue, "Parsed ENVELOPE date is null."); Assert.AreEqual("Wed, 17 Jul 1996 02:23:25 -0700", DateUtils.FormatDate(envelope.Date.Value), "Date does not match."); Assert.AreEqual("IMAP4rev1 WG mtg summary and minutes", envelope.Subject, "Subject does not match."); Assert.AreEqual(1, envelope.From.Count, "From counts do not match."); Assert.AreEqual("\"Terry Gray\" <*****@*****.**>", envelope.From.ToString(), "From does not match."); Assert.AreEqual(1, envelope.Sender.Count, "Sender counts do not match."); Assert.AreEqual("\"Terry Gray\" <*****@*****.**>", envelope.Sender.ToString(), "Sender does not match."); Assert.AreEqual(1, envelope.ReplyTo.Count, "Reply-To counts do not match."); Assert.AreEqual("\"Terry Gray\" <*****@*****.**>", envelope.ReplyTo.ToString(), "Reply-To does not match."); Assert.AreEqual(1, envelope.To.Count, "To counts do not match."); Assert.AreEqual("*****@*****.**", envelope.To.ToString(), "To does not match."); Assert.AreEqual(2, envelope.Cc.Count, "Cc counts do not match."); Assert.AreEqual("[email protected], \"John Klensin\" <*****@*****.**>", envelope.Cc.ToString(), "Cc does not match."); Assert.AreEqual(0, envelope.Bcc.Count, "Bcc counts do not match."); Assert.IsNull(envelope.InReplyTo, "In-Reply-To is not null."); Assert.AreEqual("*****@*****.**", envelope.MessageId, "Message-Id does not match."); } } } }
public void TestFormattingReversedUids() { UniqueId[] uids = { new UniqueId(20), new UniqueId(19), new UniqueId(15), new UniqueId(12), new UniqueId(11), new UniqueId(10), new UniqueId(9), new UniqueId(6), new UniqueId(5), new UniqueId(3), new UniqueId(2), new UniqueId(1) }; const string expect = "20:19,15,12:9,6:5,3:1"; string actual; actual = ImapUtils.FormatUidSet(uids); Assert.AreEqual(expect, actual, "Formatting a complex list of uids."); }
public void TestParseMalformedMailboxAddressInEnvelope() { const string text = "(\"Mon, 10 Apr 2017 06:04:00 -0700\" \"Session 2: Building the meditation habit\" ((\"Headspace\" NIL \"members\" \"headspace.com\")) ((NIL NIL \"<members=headspace.com\" \"members.headspace.com>\")) ((\"Headspace\" NIL \"members\" \"headspace.com\")) ((NIL NIL \"user\" \"gmail.com\")) NIL NIL NIL \"<*****@*****.**>\")"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { Envelope envelope; engine.SetStream(tokenizer); try { envelope = ImapUtils.ParseEnvelope(engine, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing ENVELOPE failed: {0}", ex); return; } Assert.IsTrue(envelope.Date.HasValue, "Parsed ENVELOPE date is null."); Assert.AreEqual("Mon, 10 Apr 2017 06:04:00 -0700", DateUtils.FormatDate(envelope.Date.Value), "Date does not match."); Assert.AreEqual("Session 2: Building the meditation habit", envelope.Subject, "Subject does not match."); Assert.AreEqual(1, envelope.From.Count, "From counts do not match."); Assert.AreEqual("\"Headspace\" <*****@*****.**>", envelope.From.ToString(), "From does not match."); Assert.AreEqual(1, envelope.Sender.Count, "Sender counts do not match."); Assert.AreEqual("[email protected]", envelope.Sender.ToString(), "Sender does not match."); Assert.AreEqual(1, envelope.ReplyTo.Count, "Reply-To counts do not match."); Assert.AreEqual("\"Headspace\" <*****@*****.**>", envelope.ReplyTo.ToString(), "Reply-To does not match."); Assert.AreEqual(1, envelope.To.Count, "To counts do not match."); Assert.AreEqual("*****@*****.**", envelope.To.ToString(), "To does not match."); Assert.AreEqual(0, envelope.Cc.Count, "Cc counts do not match."); Assert.AreEqual(0, envelope.Bcc.Count, "Bcc counts do not match."); Assert.IsNull(envelope.InReplyTo, "In-Reply-To is not null."); Assert.AreEqual("*****@*****.**", envelope.MessageId, "Message-Id does not match."); } } } }
public void TestParseMultipartBodyStructureWithNilBodyFldParam() { const string text = "(((\"text\" \"plain\" (\"charset\" \"UTF-8\") NIL NIL \"7bit\" 148 12 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"UTF-8\") NIL NIL \"quoted-printable\" 337 6 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"6c7f221bed92d80548353834d8e2\") NIL NIL NIL)((\"text\" \"plain\" (\"charset\" \"us-ascii\") NIL NIL \"7bit\" 0 0) \"x-zip\" NIL (\"attachment\" (\"filename\" \"YSOZ 265230.ZIP\")) NIL NIL) \"mixed\" (\"boundary\" \"c52bbfc0dd5365efa39b9f80eac3\") NIL NIL NIL)\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { BodyPartMultipart multipart, alternative, xzip; BodyPart body; engine.SetStream(tokenizer); try { body = ImapUtils.ParseBody(engine, "Unexpected token: {0}", string.Empty, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing BODYSTRUCTURE failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.IsInstanceOf <BodyPartMultipart> (body, "Body types did not match."); multipart = (BodyPartMultipart)body; Assert.IsTrue(body.ContentType.IsMimeType("multipart", "mixed"), "Content-Type did not match."); Assert.AreEqual("c52bbfc0dd5365efa39b9f80eac3", body.ContentType.Parameters["boundary"], "boundary param did not match"); Assert.AreEqual(2, multipart.BodyParts.Count, "BodyParts count does not match."); Assert.IsInstanceOf <BodyPartMultipart> (multipart.BodyParts[0], "The type of the first child does not match."); alternative = (BodyPartMultipart)multipart.BodyParts[0]; Assert.AreEqual("alternative", alternative.ContentType.MediaSubtype, "Content-Type did not match."); Assert.IsInstanceOf <BodyPartMultipart> (multipart.BodyParts[1], "The type of the second child does not match."); xzip = (BodyPartMultipart)multipart.BodyParts[1]; Assert.AreEqual("x-zip", xzip.ContentType.MediaSubtype, "Content-Type did not match."); Assert.AreEqual(0, xzip.ContentType.Parameters.Count, "Content-Type should not have params."); } } } }
public void TestParseBadlyQuotedBodyStructure() { const string text = "((\"MOUNDARY=\"_006_5DBB50A5A54730AD4A54730AD4A54730AD4A54730AD42KOS_\"\" \"OCTET-STREAM\" (\"name\" \"test.dat\") NIL NIL \"quoted-printable\" 383137 NIL (\"attachment\" (\"filename\" \"test.dat\")))(\"MOUNDARY=\"_006_5DBB50A5D3ABEC4E85A03EAD527CA5474B3D0AF9E6EXMBXSVR02KOS_\"\" \"OCTET-STREAM\" (\"name\" \"test.dat\") NIL NIL \"quoted-printable\" 383137 NIL (\"attachment\" (\"filename\" \"test.dat\"))) \"MIXED\" (\"boundary\" \"----=_NextPart_000_730AD4A547.730AD4A547F40\"))\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { BodyPartMultipart multipart; BodyPartBasic basic; BodyPart body; engine.SetStream(tokenizer); try { body = ImapUtils.ParseBody(engine, "Unexpected token: {0}", string.Empty, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing BODYSTRUCTURE failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.IsInstanceOf <BodyPartMultipart> (body, "Body types did not match."); multipart = (BodyPartMultipart)body; Assert.IsTrue(body.ContentType.IsMimeType("multipart", "mixed"), "Content-Type did not match."); Assert.AreEqual("----=_NextPart_000_730AD4A547.730AD4A547F40", body.ContentType.Parameters ["boundary"], "boundary param did not match"); Assert.AreEqual(2, multipart.BodyParts.Count, "BodyParts count does not match."); Assert.IsInstanceOf <BodyPartBasic> (multipart.BodyParts[0], "The type of the first child does not match."); basic = (BodyPartBasic)multipart.BodyParts[0]; Assert.AreEqual("MOUNDARY=\"_006_5DBB50A5A54730AD4A54730AD4A54730AD4A54730AD42KOS_\"", basic.ContentType.MediaType, "ContentType.MediaType does not match for first child."); Assert.IsInstanceOf <BodyPartBasic> (multipart.BodyParts[1], "The type of the second child does not match."); basic = (BodyPartBasic)multipart.BodyParts[1]; Assert.AreEqual("MOUNDARY=\"_006_5DBB50A5D3ABEC4E85A03EAD527CA5474B3D0AF9E6EXMBXSVR02KOS_\"", basic.ContentType.MediaType, "ContentType.MediaType does not match for second child."); } } } }
public void TestParseExampleMultiLevelDovecotBodyStructure() { const string text = "(((\"text\" \"plain\" (\"charset\" \"iso-8859-2\") NIL NIL \"quoted-printable\" 28 2 NIL NIL NIL NIL) (\"text\" \"html\" (\"charset\" \"iso-8859-2\") NIL NIL \"quoted-printable\" 1707 65 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"----=_NextPart_001_0078_01CBB179.57530990\") NIL NIL NIL) (\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 641 (\"Sat, 8 Jan 2011 14:16:36 +0100\" \"Subj 2\" ((\"Some Name, SOMECOMPANY\" NIL \"recipient\" \"example.com\")) ((\"Some Name, SOMECOMPANY\" NIL \"recipient\" \"example.com\")) ((\"Some Name, SOMECOMPANY\" NIL \"recipient\" \"example.com\")) ((\"Recipient\" NIL \"example\" \"gmail.com\")) NIL NIL NIL NIL) (\"text\" \"plain\" (\"charset\" \"iso-8859-2\") NIL NIL \"quoted-printable\" 185 18 NIL NIL (\"cs\") NIL) 31 NIL (\"attachment\" NIL) NIL NIL) (\"message\" \"rfc822\" NIL NIL NIL \"7bit\" 50592 (\"Sat, 8 Jan 2011 13:58:39 +0100\" \"Subj 1\" ((\"Some Name, SOMECOMPANY\" NIL \"recipient\" \"example.com\")) ((\"Some Name, SOMECOMPANY\" NIL \"recipient\" \"example.com\")) ((\"Some Name, SOMECOMPANY\" NIL \"recipient\" \"example.com\")) ((\"Recipient\" NIL \"example\" \"gmail.com\")) NIL NIL NIL NIL) ( (\"text\" \"plain\" (\"charset\" \"iso-8859-2\") NIL NIL \"quoted-printable\" 4296 345 NIL NIL NIL NIL) (\"text\" \"html\" (\"charset\" \"iso-8859-2\") NIL NIL \"quoted-printable\" 45069 1295 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"----=_NextPart_000_0073_01CBB179.57530990\") NIL (\"cs\") NIL) 1669 NIL (\"attachment\" NIL) NIL NIL) \"mixed\" (\"boundary\" \"----=_NextPart_000_0077_01CBB179.57530990\") NIL (\"cs\") NIL)\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { BodyPartMultipart multipart; BodyPart body; engine.SetStream(tokenizer); try { body = ImapUtils.ParseBody(engine, "Unexpected token: {0}", string.Empty, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing BODYSTRUCTURE failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.IsInstanceOf <BodyPartMultipart> (body, "Body types did not match."); multipart = (BodyPartMultipart)body; Assert.IsTrue(body.ContentType.IsMimeType("multipart", "mixed"), "Content-Type did not match."); Assert.AreEqual("----=_NextPart_000_0077_01CBB179.57530990", body.ContentType.Parameters["boundary"], "boundary param did not match"); Assert.AreEqual(3, multipart.BodyParts.Count, "BodyParts count does not match."); Assert.IsInstanceOf <BodyPartMultipart> (multipart.BodyParts[0], "The type of the first child does not match."); Assert.IsInstanceOf <BodyPartMessage> (multipart.BodyParts[1], "The type of the second child does not match."); Assert.IsInstanceOf <BodyPartMessage> (multipart.BodyParts[2], "The type of the third child does not match."); // FIXME: assert more stuff? } } } }
public void TestParseExampleBodyRfc3501() { const string text = "(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL \"7BIT\" 3028 92)\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { BodyPartText basic; BodyPart body; engine.SetStream(tokenizer); try { body = ImapUtils.ParseBody(engine, "Unexpected token: {0}", string.Empty, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing BODY failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); Assert.IsInstanceOf <BodyPartText> (body, "Body types did not match."); basic = (BodyPartText)body; Assert.IsTrue(body.ContentType.IsMimeType("text", "plain"), "Content-Type did not match."); Assert.AreEqual("US-ASCII", body.ContentType.Parameters["charset"], "charset param did not match"); Assert.IsNotNull(basic, "The parsed body is not BodyPartText."); Assert.AreEqual("7BIT", basic.ContentTransferEncoding, "Content-Transfer-Encoding did not match."); Assert.AreEqual(3028, basic.Octets, "Octet count did not match."); Assert.AreEqual(92, basic.Lines, "Line count did not match."); } } } }
public void TestParseLabelsListWithNIL() { const string text = "(atom-label \\flag-label \"quoted-label\" NIL)\r\n"; using (var memory = new MemoryStream(Encoding.ASCII.GetBytes(text), false)) { using (var tokenizer = new ImapStream(memory, null, new NullProtocolLogger())) { using (var engine = new ImapEngine(null)) { IList <string> labels; engine.SetStream(tokenizer); try { labels = ImapUtils.ParseLabelsList(engine, CancellationToken.None); } catch (Exception ex) { Assert.Fail("Parsing X-GM-LABELS failed: {0}", ex); return; } var token = engine.ReadToken(CancellationToken.None); Assert.AreEqual(ImapTokenType.Eoln, token.Type, "Expected new-line, but got: {0}", token); } } } }
public static Folder InitSubFolder(Folder subFolder, Folder parentFolder) { string full_path = Path.Combine(parentFolder.FullPath, ImapUtils.ToUtf7String(subFolder.Name)); return(new Folder(subFolder.ID, parentFolder.IDAcct, parentFolder.ID, subFolder.Name, full_path, subFolder.Type, subFolder.SyncType, subFolder.Hide, subFolder.FolderOrder)); }
IList <ImapReplayCommand> CreateAppendWithAnnotationsCommands(bool withInternalDates, out List <MimeMessage> messages, out List <MessageFlags> flags, out List <DateTimeOffset> internalDates, out List <Annotation> annotations) { var commands = new List <ImapReplayCommand> (); commands.Add(new ImapReplayCommand("", "dovecot.greeting.txt")); commands.Add(new ImapReplayCommand("A00000000 LOGIN username password\r\n", "dovecot.authenticate+annotate.txt")); commands.Add(new ImapReplayCommand("A00000001 NAMESPACE\r\n", "dovecot.namespace.txt")); commands.Add(new ImapReplayCommand("A00000002 LIST \"\" \"INBOX\" RETURN (SUBSCRIBED CHILDREN)\r\n", "dovecot.list-inbox.txt")); commands.Add(new ImapReplayCommand("A00000003 LIST (SPECIAL-USE) \"\" \"*\" RETURN (SUBSCRIBED CHILDREN)\r\n", "dovecot.list-special-use.txt")); internalDates = withInternalDates ? new List <DateTimeOffset> () : null; annotations = new List <Annotation> (); messages = new List <MimeMessage> (); flags = new List <MessageFlags> (); var command = new StringBuilder(); int id = 4; for (int i = 0; i < 8; i++) { MimeMessage message; string latin1; long length; using (var resource = GetResourceStream(string.Format("common.message.{0}.msg", i))) message = MimeMessage.Load(resource); messages.Add(message); flags.Add(MessageFlags.Seen); if (withInternalDates) { internalDates.Add(message.Date); } var annotation = new Annotation(AnnotationEntry.AltSubject); annotation.Properties[AnnotationAttribute.PrivateValue] = string.Format("Alternate subject {0}", i); annotations.Add(annotation); using (var stream = new MemoryStream()) { var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Dos; options.EnsureNewLine = true; message.WriteTo(options, stream); length = stream.Length; stream.Position = 0; using (var reader = new StreamReader(stream, Latin1)) latin1 = reader.ReadToEnd(); } var tag = string.Format("A{0:D8}", id++); command.Clear(); command.AppendFormat("{0} APPEND INBOX (\\Seen) ", tag); if (withInternalDates) { command.AppendFormat("\"{0}\" ", ImapUtils.FormatInternalDate(message.Date)); } command.AppendFormat("ANNOTATION (/altsubject (value.priv \"Alternate subject {0}\")) ", i); command.Append('{').Append(length.ToString()).Append("+}\r\n").Append(latin1).Append("\r\n"); commands.Add(new ImapReplayCommand(command.ToString(), string.Format("dovecot.append.{0}.txt", i + 1))); } commands.Add(new ImapReplayCommand(string.Format("A{0:D8} LOGOUT\r\n", id), "gmail.logout.txt")); return(commands); }
public void TestNonAuthCommand() { string command = string.Format("A00000000 APPEND INBOX (\\Seen) \"{0}\" {{4096}}\r\n", ImapUtils.FormatInternalDate(DateTimeOffset.Now)); var detector = new ImapAuthenticationSecretDetector(); var buffer = Encoding.ASCII.GetBytes(command); detector.IsAuthenticating = true; var secrets = detector.DetectSecrets(buffer, 0, buffer.Length); Assert.AreEqual(0, secrets.Count, "# of secrets"); }
private async Task ProcessMessages() { using (var client = _settings.GetImapClient()) { ImapUtils.InitMailboxes(client, _endpointName); if (_purgeOnStartup) { ImapUtils.PurgeMailboxes(client, _endpointName); } client.Inbox.Open(FolderAccess.ReadWrite); var query = SearchQuery.SubjectContains($"NSB-MSG-{_endpointName}-"); // Listen to new messages void CheckForNewMessages(object o, EventArgs args) { _log.Debug("Mailbox count changed."); _timeoutTokenSource.Cancel(); } client.Inbox.CountChanged += CheckForNewMessages; _cancellationTokenSource = new CancellationTokenSource(); while (!_cancellationTokenSource.IsCancellationRequested) { _timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5)); using (_timeoutTokenSource) { try { foreach (var m in client.Inbox.Search(query)) { _log.Debug($"Processing message with UID: {m}."); await ProcessMessageWithTransaction(client, m); } if (client.Capabilities.HasFlag(ImapCapabilities.Idle)) { _log.Debug("Waiting for IDLE from IMAP server."); await client.IdleAsync(_timeoutTokenSource.Token, _cancellationTokenSource.Token); } else { _log.Debug("Waiting for new messages..."); client.NoOp(_cancellationTokenSource.Token); WaitHandle.WaitAny(new[] { _timeoutTokenSource.Token.WaitHandle, _cancellationTokenSource.Token.WaitHandle }); } } catch (OperationCanceledException) { } catch (ImapProtocolException) { break; } catch (ImapCommandException) { break; } catch (Exception ex) { _log.Error(ex.Message, ex); _criticalError.Raise(ex.Message, ex); } } } } }