示例#1
0
        /// <summary>
        /// Parses an untagged ID response.
        /// </summary>
        /// <param name="engine">The IMAP engine.</param>
        /// <param name="ic">The IMAP command.</param>
        /// <param name="index">The index.</param>
        public static void ParseImplementation(ImapEngine engine, ImapCommand ic, int index)
        {
            var token          = engine.ReadToken(ic.CancellationToken);
            var implementation = new ImapImplementation();

            ic.UserData = implementation;

            if (token.Type == ImapTokenType.Nil)
            {
                return;
            }

            if (token.Type != ImapTokenType.OpenParen)
            {
                throw ImapEngine.UnexpectedToken(token, false);
            }

            token = engine.PeekToken(ic.CancellationToken);

            while (token.Type != ImapTokenType.CloseParen)
            {
                var property = ImapUtils.ReadStringToken(engine, ic.CancellationToken);
                var value    = ImapUtils.ReadNStringToken(engine, false, ic.CancellationToken);

                implementation.Properties[property] = value;

                token = engine.PeekToken(ic.CancellationToken);
            }

            // read the ')' token
            engine.ReadToken(ic.CancellationToken);
        }
示例#2
0
		public static void Capabilities ()
		{
			using (var client = new ImapClient ()) {
				client.Connect ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);

				var mechanisms = string.Join (", ", client.AuthenticationMechanisms);
				Console.WriteLine ("The IMAP server supports the following SASL authentication mechanisms: {0}", mechanisms);

				client.Authenticate ("username", "password");

				if (client.Capabilities.HasFlag (ImapCapabilities.Id)) {
					var clientImplementation = new ImapImplementation { Name = "MailKit", Version = "1.0" };
					var serverImplementation = client.Identify (clientImplementation);

					Console.WriteLine ("Server implementation details:");
					foreach (var property in serverImplementation.Properties)
						Console.WriteLine ("  {0} = {1}", property.Key, property.Value);
				}

				if (client.Capabilities.HasFlag (ImapCapabilities.Acl)) {
					Console.WriteLine ("The IMAP server supports Access Control Lists.");

					Console.WriteLine ("The IMAP server supports the following access rights: {0}", client.Rights);

					Console.WriteLine ("The Inbox has the following access controls:");
					var acl = client.Inbox.GetAccessControlList ();
					foreach (var ac in acl)
						Console.WriteLine ("  {0} = {1}", ac.Name, ac.Rights);

					var myRights = client.Inbox.GetMyAccessRights ();
					Console.WriteLine ("Your current rights for the Inbox folder are: {0}", myRights);
				}

				if (client.Capabilities.HasFlag (ImapCapabilities.Quota)) {
					Console.WriteLine ("The IMAP server supports quotas.");

					Console.WriteLine ("The current quota for the Inbox is:");
					var quota = client.Inbox.GetQuota ();

					if (quota.StorageLimit.HasValue && quota.StorageLimit.Value)
						Console.WriteLine ("  Limited by storage space. Using {0} out of {1} bytes.", quota.CurrentStorageSize.Value, quota.StorageLimit.Value);

					if (quota.MessageLimit.HasValue && quota.MessageLimit.Value)
						Console.WriteLine ("  Limited by the number of messages. Using {0} out of {1} bytes.", quota.CurrentMessageCount.Value, quota.MessageLimit.Value);

					Console.WriteLine ("The quota root is: {0}", quota.QuotaRoot);
				}

				if (client.Capabilities.HasFlag (ImapCapabilities.Thread)) {
					if (client.ThreadingAlgorithms.Contains (ThreadingAlgorithm.OrderedSubject))
						Console.WriteLine ("The IMAP server supports threading by subject.");
					if (client.ThreadingAlgorithms.Contains (ThreadingAlgorithm.References))
						Console.WriteLine ("The IMAP server supports threading by references.");
				}

				client.Disconnect (true);
			}
		}
 /// <summary>
 /// Asynchronously identify the client implementation to the server and obtain the server implementation details.
 /// </summary>
 /// <remarks>
 /// <para>Passes along the client implementation details to the server while also obtaining implementation
 /// details from the server.</para>
 /// <para>If the <paramref name="clientImplementation"/> is <c>null</c> or no properties have been set, no
 /// identifying information will be sent to the server.</para>
 /// <note type="security">
 /// <para>Security Implications</para>
 /// <para>This command has the danger of violating the privacy of users if misused. Clients should
 /// notify users that they send the ID command.</para>
 /// <para>It is highly desirable that implementations provide a method of disabling ID support, perhaps by
 /// not calling this method at all, or by passing <c>null</c> as the <paramref name="clientImplementation"/>
 /// argument.</para>
 /// <para>Implementors must exercise extreme care in adding properties to the <paramref name="clientImplementation"/>.
 /// Some properties, such as a processor ID number, Ethernet address, or other unique (or mostly unique) identifier
 /// would allow tracking of users in ways that violate user privacy expectations and may also make it easier for
 /// attackers to exploit security holes in the client.</para>
 /// </note>
 /// </remarks>
 /// <returns>The implementation details of the server if available; otherwise, <c>null</c>.</returns>
 /// <param name="clientImplementation">The client implementation.</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <exception cref="System.ObjectDisposedException">
 /// The <see cref="ImapClient"/> has been disposed.
 /// </exception>
 /// <exception cref="ServiceNotConnectedException">
 /// The <see cref="ImapClient"/> is not connected.
 /// </exception>
 /// <exception cref="System.NotSupportedException">
 /// The IMAP server does not support the ID extension.
 /// </exception>
 /// <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="ImapCommandException">
 /// The server replied to the ID command with a NO or BAD response.
 /// </exception>
 /// <exception cref="ImapProtocolException">
 /// An IMAP protocol error occurred.
 /// </exception>
 public Task <ImapImplementation> IdentifyAsync(ImapImplementation clientImplementation, CancellationToken cancellationToken = default(CancellationToken))
 {
     return(IdentifyAsync(clientImplementation, true, cancellationToken));
 }
示例#4
0
		/// <summary>
		/// Asynchronously identify the client implementation to the server and obtain the server implementation details.
		/// </summary>
		/// <remarks>
		/// <para>Passes along the client implementation details to the server while also obtaining implementation
		/// details from the server.</para>
		/// <para>If the <paramref name="clientImplementation"/> is null or no properties have been set, no
		/// identifying information will be sent to the server.</para>
		/// <para>Security Implications</para>
		/// <para>This command has the danger of violating the privacy of users if misused. Clients should
		/// notify users that they send the ID command.</para>
		/// <para>It is highly desirable that implementations provide a method of disabling ID support, perhaps by
		/// not calling this method at all, or by passing <c>null</c> as the <paramref name="clientImplementation"/>
		/// argument.</para>
		/// <para>Implementors must exercise extreme care in adding properties to the <paramref name="clientImplementation"/>.
		/// Some properties, such as a processor ID number, Ethernet address, or other unique (or mostly unique) identifier
		/// would allow tracking of users in ways that violate user privacy expectations and may also make it easier for
		/// attackers to exploit security holes in the client.</para>
		/// </remarks>
		/// <returns>The implementation details of the server.</returns>
		/// <param name="clientImplementation">The client implementation.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="ImapClient"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="ImapClient"/> is not connected.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// The IMAP server does not support the ID extension.
		/// </exception>
		/// <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="ImapCommandException">
		/// The server replied to the ID command with a NO or BAD response.
		/// </exception>
		/// <exception cref="ImapProtocolException">
		/// An IMAP protocol error occurred.
		/// </exception>
		public Task<ImapImplementation> IdentifyAsync (ImapImplementation clientImplementation, CancellationToken cancellationToken = default (CancellationToken))
		{
			return Task.Factory.StartNew (() => {
				lock (SyncRoot) {
					return Identify (clientImplementation, cancellationToken);
				}
			}, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
		}
示例#5
0
		/// <summary>
		/// Identify the client implementation to the server and obtain the server implementation details.
		/// </summary>
		/// <remarks>
		/// <para>Passes along the client implementation details to the server while also obtaining implementation
		/// details from the server.</para>
		/// <para>If the <paramref name="clientImplementation"/> is null or no properties have been set, no
		/// identifying information will be sent to the server.</para>
		/// <para>Security Implications</para>
		/// <para>This command has the danger of violating the privacy of users if misused. Clients should
		/// notify users that they send the ID command.</para>
		/// <para>It is highly desirable that implementations provide a method of disabling ID support, perhaps by
		/// not calling this method at all, or by passing <c>null</c> as the <paramref name="clientImplementation"/>
		/// argument.</para>
		/// <para>Implementors must exercise extreme care in adding properties to the <paramref name="clientImplementation"/>.
		/// Some properties, such as a processor ID number, Ethernet address, or other unique (or mostly unique) identifier
		/// would allow tracking of users in ways that violate user privacy expectations and may also make it easier for
		/// attackers to exploit security holes in the client.</para>
		/// </remarks>
		/// <example>
		/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
		/// </example>
		/// <returns>The implementation details of the server.</returns>
		/// <param name="clientImplementation">The client implementation.</param>
		/// <param name="cancellationToken">The cancellation token.</param>
		/// <exception cref="System.ObjectDisposedException">
		/// The <see cref="ImapClient"/> has been disposed.
		/// </exception>
		/// <exception cref="ServiceNotConnectedException">
		/// The <see cref="ImapClient"/> is not connected.
		/// </exception>
		/// <exception cref="System.NotSupportedException">
		/// The IMAP server does not support the ID extension.
		/// </exception>
		/// <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="ImapCommandException">
		/// The server replied to the ID command with a NO or BAD response.
		/// </exception>
		/// <exception cref="ImapProtocolException">
		/// An IMAP protocol error occurred.
		/// </exception>
		public ImapImplementation Identify (ImapImplementation clientImplementation, CancellationToken cancellationToken = default (CancellationToken))
		{
			CheckDisposed ();
			CheckConnected ();

			if ((engine.Capabilities & ImapCapabilities.Id) == 0)
				throw new NotSupportedException ("The IMAP server does not support the ID extension.");

			var command = new StringBuilder ("ID ");
			var args = new List<object> ();

			if (clientImplementation != null && clientImplementation.Properties.Count > 0) {
				command.Append ('(');
				foreach (var property in clientImplementation.Properties) {
					command.Append ("%Q ");
					args.Add (property.Key);

					if (property.Value != null) {
						command.Append ("%Q ");
						args.Add (property.Value);
					} else {
						command.Append ("NIL ");
					}
				}
				command[command.Length - 1] = ')';
				command.Append ("\r\n");
			} else {
				command.Append ("NIL\r\n");
			}

			var ic = new ImapCommand (engine, cancellationToken, null, command.ToString (), args.ToArray ());
			ic.RegisterUntaggedHandler ("ID", ImapUtils.ParseImplementation);

			engine.QueueCommand (ic);
			engine.Wait (ic);

			if (ic.Response != ImapCommandResponse.Ok)
				throw ImapCommandException.Create ("ID", ic);

			return (ImapImplementation) ic.UserData;
		}
示例#6
0
		/// <summary>
		/// Parses an untagged ID response.
		/// </summary>
		/// <param name="engine">The IMAP engine.</param>
		/// <param name="ic">The IMAP command.</param>
		/// <param name="index">The index.</param>
		public static void ParseImplementation (ImapEngine engine, ImapCommand ic, int index)
		{
			var token = engine.ReadToken (ic.CancellationToken);
			var implementation = new ImapImplementation ();

			ic.UserData = implementation;

			if (token.Type == ImapTokenType.Nil)
				return;

			if (token.Type != ImapTokenType.OpenParen)
				throw ImapEngine.UnexpectedToken (token, false);

			token = engine.PeekToken (ic.CancellationToken);

			while (token.Type != ImapTokenType.CloseParen) {
				var property = ImapUtils.ReadStringToken (engine, ic.CancellationToken);
				var value = ImapUtils.ReadNStringToken (engine, false, ic.CancellationToken);

				implementation.Properties[property] = value;

				token = engine.PeekToken (ic.CancellationToken);
			}

			// read the ')' token
			engine.ReadToken (ic.CancellationToken);
		}
示例#7
0
		public async void TestImapClientFeatures ()
		{
			var commands = new List<ImapReplayCommand> ();
			commands.Add (new ImapReplayCommand ("", "gmail.greeting.txt"));
			commands.Add (new ImapReplayCommand ("A00000000 CAPABILITY\r\n", "gmail.capability.txt"));
			commands.Add (new ImapReplayCommand ("A00000001 AUTHENTICATE PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk\r\n", "gmail.authenticate.txt"));
			commands.Add (new ImapReplayCommand ("A00000002 NAMESPACE\r\n", "gmail.namespace.txt"));
			commands.Add (new ImapReplayCommand ("A00000003 LIST \"\" \"INBOX\"\r\n", "gmail.list-inbox.txt"));
			commands.Add (new ImapReplayCommand ("A00000004 XLIST \"\" \"*\"\r\n", "gmail.xlist.txt"));
			commands.Add (new ImapReplayCommand ("A00000005 ID (\"name\" \"MailKit\" \"version\" \"1.0\" \"vendor\" \"Xamarin Inc.\")\r\n", "common.id.txt"));
			commands.Add (new ImapReplayCommand ("A00000006 GETQUOTAROOT INBOX\r\n", "common.getquota.txt"));
			commands.Add (new ImapReplayCommand ("A00000007 SETQUOTA \"\" (MESSAGE 1000000 STORAGE 5242880)\r\n", "common.setquota.txt"));

			using (var client = new ImapClient ()) {
				try {
					client.ReplayConnect ("localhost", new ImapReplayStream (commands, false));
				} catch (Exception ex) {
					Assert.Fail ("Did not expect an exception in Connect: {0}", ex);
				}

				Assert.IsTrue (client.IsConnected, "Client failed to connect.");
				Assert.IsFalse (client.IsSecure, "IsSecure should be false.");

				Assert.AreEqual (GMailInitialCapabilities, client.Capabilities);
				Assert.AreEqual (5, client.AuthenticationMechanisms.Count);
				Assert.IsTrue (client.AuthenticationMechanisms.Contains ("XOAUTH"), "Expected SASL XOAUTH auth mechanism");
				Assert.IsTrue (client.AuthenticationMechanisms.Contains ("XOAUTH2"), "Expected SASL XOAUTH2 auth mechanism");
				Assert.IsTrue (client.AuthenticationMechanisms.Contains ("OAUTHBEARER"), "Expected SASL OAUTHBEARER auth mechanism");
				Assert.IsTrue (client.AuthenticationMechanisms.Contains ("PLAIN"), "Expected SASL PLAIN auth mechanism");
				Assert.IsTrue (client.AuthenticationMechanisms.Contains ("PLAIN-CLIENTTOKEN"), "Expected SASL PLAIN-CLIENTTOKEN auth mechanism");

				Assert.AreEqual (100000, client.Timeout, "Timeout");
				client.Timeout *= 2;

				// Note: Do not try XOAUTH2
				client.AuthenticationMechanisms.Remove ("XOAUTH2");

				try {
					await client.AuthenticateAsync (new NetworkCredential ("username", "password"));
				} catch (Exception ex) {
					Assert.Fail ("Did not expect an exception in Authenticate: {0}", ex);
				}

				Assert.AreEqual (GMailAuthenticatedCapabilities, client.Capabilities);
				Assert.IsTrue (client.SupportsQuotas, "SupportsQuotas");

				var implementation = new ImapImplementation {
					Name = "MailKit", Version = "1.0", Vendor = "Xamarin Inc."
				};

				implementation = await client.IdentifyAsync (implementation);
				Assert.IsNotNull (implementation, "Expected a non-null ID response.");
				Assert.AreEqual ("GImap", implementation.Name);
				Assert.AreEqual ("Google, Inc.", implementation.Vendor);
				Assert.AreEqual ("http://support.google.com/mail", implementation.SupportUrl);
				Assert.AreEqual ("gmail_imap_150623.03_p1", implementation.Version);
				Assert.AreEqual ("127.0.0.1", implementation.Properties["remote-host"]);

				var personal = client.GetFolder (client.PersonalNamespaces[0]);
				var inbox = client.Inbox;

				Assert.IsNotNull (inbox, "Expected non-null Inbox folder.");
				Assert.AreEqual (FolderAttributes.Inbox | FolderAttributes.HasNoChildren, inbox.Attributes, "Expected Inbox attributes to be \\HasNoChildren.");

				var quota = await inbox.GetQuotaAsync ();
				Assert.IsNotNull (quota, "Expected a non-null GETQUOTAROOT response.");
				Assert.AreEqual (personal.FullName, quota.QuotaRoot.FullName);
				Assert.AreEqual (personal, quota.QuotaRoot);
				Assert.AreEqual (3783, quota.CurrentStorageSize.Value);
				Assert.AreEqual (15728640, quota.StorageLimit.Value);
				Assert.IsFalse (quota.CurrentMessageCount.HasValue);
				Assert.IsFalse (quota.MessageLimit.HasValue);

				quota = await personal.SetQuotaAsync (1000000, 5242880);
				Assert.IsNotNull (quota, "Expected non-null SETQUOTA response.");
				Assert.AreEqual (1107, quota.CurrentMessageCount.Value);
				Assert.AreEqual (3783, quota.CurrentStorageSize.Value);
				Assert.AreEqual (1000000, quota.MessageLimit.Value);
				Assert.AreEqual (5242880, quota.StorageLimit.Value);

				await client.DisconnectAsync (false);
			}
		}
 public Task<ImapImplementation> IdentifyAsync(ImapImplementation clientImplementation,
     CancellationToken cancellationToken = new CancellationToken())
 {
     return _imapClient.IdentifyAsync(clientImplementation, cancellationToken);
 }
 public ImapImplementation Identify(ImapImplementation clientImplementation,
     CancellationToken cancellationToken = new CancellationToken())
 {
     return _imapClient.Identify(clientImplementation, cancellationToken);
 }
示例#10
0
		/// <summary>
		/// Parses an untagged ID response.
		/// </summary>
		/// <param name="engine">The IMAP engine.</param>
		/// <param name="ic">The IMAP command.</param>
		/// <param name="index">The index.</param>
		public static void ParseImplementation (ImapEngine engine, ImapCommand ic, int index)
		{
			string format = string.Format (ImapEngine.GenericUntaggedResponseSyntaxErrorFormat, "ID", "{0}");
			var token = engine.ReadToken (ic.CancellationToken);
			ImapImplementation implementation;

			if (token.Type == ImapTokenType.Nil)
				return;

			if (token.Type != ImapTokenType.OpenParen)
				throw ImapEngine.UnexpectedToken (format, token);

			token = engine.PeekToken (ic.CancellationToken);

			implementation = new ImapImplementation ();

			while (token.Type != ImapTokenType.CloseParen) {
				var property = ReadStringToken (engine, format, ic.CancellationToken);
				var value = ReadNStringToken (engine, format, false, ic.CancellationToken);

				implementation.Properties[property] = value;

				token = engine.PeekToken (ic.CancellationToken);
			}

			ic.UserData = implementation;

			// read the ')' token
			engine.ReadToken (ic.CancellationToken);
		}