Inheritance: Stream, ICancellableStream
Example #1
0
        /// <summary>
        /// Writes the literal to the specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        public void WriteTo(ImapStream stream, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (Type == ImapLiteralType.String)
            {
                var bytes = (byte[])Literal;
                stream.Write(bytes, 0, bytes.Length);
                stream.Flush();
                return;
            }

            if (Type == ImapLiteralType.MimeMessage)
            {
                var options = FormatOptions.Default.Clone();
                options.NewLineFormat = NewLineFormat.Dos;

                var message = (MimeMessage)Literal;

                message.WriteTo(options, stream, cancellationToken);
                stream.Flush();
                return;
            }

            var literal = (Stream)Literal;
            var buf     = new byte[4096];
            int nread   = 0;

            while ((nread = literal.Read(buf, 0, buf.Length)) > 0)
            {
                cancellationToken.ThrowIfCancellationRequested();
                stream.Write(buf, 0, nread);
            }

            stream.Flush();
        }
Example #2
0
		/// <summary>
		/// Write the literal to the specified stream.
		/// </summary>
		/// <remarks>
		/// Writes the literal to the specified stream.
		/// </remarks>
		/// <param name="stream">The stream.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		public void WriteTo (ImapStream stream, CancellationToken cancellationToken)
		{
			if (Type == ImapLiteralType.String) {
				var bytes = (byte[]) Literal;
				stream.Write (bytes, 0, bytes.Length, cancellationToken);
				stream.Flush (cancellationToken);
				return;
			}

			if (Type == ImapLiteralType.MimeMessage) {
				var message = (MimeMessage) Literal;

				using (var s = new ProgressStream (stream, update)) {
					message.WriteTo (format, s, cancellationToken);
					s.Flush (cancellationToken);
					return;
				}
			}

			var literal = (Stream) Literal;
			var buf = new byte[4096];
			int nread;

			while ((nread = literal.Read (buf, 0, buf.Length)) > 0)
				stream.Write (buf, 0, nread, cancellationToken);

			stream.Flush (cancellationToken);
		}
Example #3
0
		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.");
					}
				}
			}
		}
Example #4
0
		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?
					}
				}
			}
		}
Example #5
0
		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 ());
					}
				}
			}
		}
Example #6
0
		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.");
					}
				}
			}
		}
Example #7
0
		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.");
					}
				}
			}
		}
Example #8
0
		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);
					}
				}
			}
		}
Example #9
0
        /// <summary>
        /// Disconnects the <see cref="ImapStream"/>.
        /// </summary>
        public void Disconnect()
        {
            State = ImapEngineState.Disconnected;

            if (stream != null) {
                stream.Dispose ();
                stream = null;
            }
        }
Example #10
0
        /// <summary>
        /// Takes posession of the <see cref="ImapStream"/> and reads the greeting.
        /// </summary>
        /// <param name="imap">The IMAP stream.</param>
        /// <param name="cancellationToken">A cancellation token</param>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was canceled via the cancellation token.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurred.
        /// </exception>
        /// <exception cref="ImapProtocolException">
        /// An IMAP protocol error occurred.
        /// </exception>
        public void Connect(ImapStream imap, CancellationToken cancellationToken)
        {
            if (stream != null)
                stream.Dispose ();

            TagPrefix = (char) ('A' + (TagPrefixIndex++ % 26));
            ProtocolVersion = ImapProtocolVersion.Unknown;
            Capabilities = ImapCapabilities.None;
            AuthenticationMechanisms.Clear ();
            CompressionAlgorithms.Clear ();
            ThreadingAlgorithms.Clear ();
            SupportedCharsets.Clear ();
            SupportedContexts.Clear ();

            // TODO: should we clear the folder cache?

            State = ImapEngineState.Connected;
            SupportedCharsets.Add ("UTF-8");
            CapabilitiesVersion = 0;
            QResyncEnabled = false;
            stream = imap;
            Tag = 0;

            try {
                var token = stream.ReadToken (cancellationToken);

                if (token.Type != ImapTokenType.Asterisk)
                    throw UnexpectedToken (token, true);

                token = stream.ReadToken (cancellationToken);

                if (token.Type != ImapTokenType.Atom)
                    throw UnexpectedToken (token, true);

                var atom = (string) token.Value;

                switch (atom) {
                case "PREAUTH": State = ImapEngineState.Authenticated; break;
                case "OK":      State = ImapEngineState.PreAuth; break;
                case "BYE":
                    // FIXME: should we throw a special exception here?
                    throw UnexpectedToken (token, true);
                default:
                    throw UnexpectedToken (token, true);
                }

                token = stream.ReadToken (cancellationToken);

                if (token.Type == ImapTokenType.OpenBracket) {
                    var code = ParseResponseCode (cancellationToken);
                    if (code.Type == ImapResponseCodeType.Alert)
                        OnAlert (code.Message);
                } else if (token.Type != ImapTokenType.Eoln) {
                    // throw away any remaining text up until the end of the line
                    ReadLine (cancellationToken);
                }
            } catch {
                Disconnect ();
                throw;
            }
        }
Example #11
0
 /// <summary>
 /// Sets the stream - this is only here to be used by the unit tests.
 /// </summary>
 /// <param name="imap">The IMAP stream.</param>
 internal void SetStream(ImapStream imap)
 {
     stream = imap;
 }
Example #12
0
		/// <summary>
		/// Writes the literal to the specified stream.
		/// </summary>
		/// <param name="stream">The stream.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		public void WriteTo (ImapStream stream, CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested ();

			if (Type == ImapLiteralType.String) {
				var bytes = (byte[]) Literal;
				stream.Write (bytes, 0, bytes.Length);
				stream.Flush ();
				return;
			}

			if (Type == ImapLiteralType.MimeMessage) {
				var options = FormatOptions.Default.Clone ();
				options.NewLineFormat = NewLineFormat.Dos;

				var message = (MimeMessage) Literal;

				message.WriteTo (options, stream, cancellationToken);
				stream.Flush ();
				return;
			}

			var literal = (Stream) Literal;
			var buf = new byte[4096];
			int nread = 0;

			while ((nread = literal.Read (buf, 0, buf.Length)) > 0) {
				cancellationToken.ThrowIfCancellationRequested ();
				stream.Write (buf, 0, nread);
			}

			stream.Flush ();
		}
Example #13
0
 /// <summary>
 /// Sets the stream - this is only here to be used by the unit tests.
 /// </summary>
 /// <param name="stream">The IMAP stream.</param>
 internal void SetStream(ImapStream stream)
 {
     Stream = stream;
 }
Example #14
0
        /// <summary>
        /// Write the literal to the specified stream.
        /// </summary>
        /// <remarks>
        /// Writes the literal to the specified stream.
        /// </remarks>
        /// <param name="stream">The stream.</param>
        /// <param name="doAsync">Whether the literal should be written asynchronously or not.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        public async Task WriteToAsync(ImapStream stream, bool doAsync, CancellationToken cancellationToken)
        {
            if (Type == ImapLiteralType.String)
            {
                var bytes = (byte[])Literal;

                if (doAsync)
                {
                    await stream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false);

                    await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    stream.Write(bytes, 0, bytes.Length, cancellationToken);
                    stream.Flush(cancellationToken);
                }
                return;
            }

            if (Type == ImapLiteralType.MimeMessage)
            {
                var message = (MimeMessage)Literal;

                using (var s = new ProgressStream(stream, update)) {
                    if (doAsync)
                    {
                        await message.WriteToAsync(format, s, cancellationToken).ConfigureAwait(false);

                        await s.FlushAsync(cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        message.WriteTo(format, s, cancellationToken);
                        s.Flush(cancellationToken);
                    }
                    return;
                }
            }

            var literal = (Stream)Literal;
            var buf     = new byte[4096];
            int nread;

            if (doAsync)
            {
                while ((nread = await literal.ReadAsync(buf, 0, buf.Length, cancellationToken).ConfigureAwait(false)) > 0)
                {
                    await stream.WriteAsync(buf, 0, nread, cancellationToken).ConfigureAwait(false);
                }

                await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
            }
            else
            {
                while ((nread = literal.Read(buf, 0, buf.Length)) > 0)
                {
                    stream.Write(buf, 0, nread, cancellationToken);
                }

                stream.Flush(cancellationToken);
            }
        }