add MailKit and MimeKit
parent
bff490f383
commit
c7fdde81cd
|
@ -0,0 +1,137 @@
|
||||||
|
//
|
||||||
|
// AccessControl.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An Access Control.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An Access Control is a set of permissions available for a particular identity,
|
||||||
|
/// controlling whether or not that identity has the ability to perform various tasks.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
public class AccessControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessControl"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.AccessControl"/> with the given name and
|
||||||
|
/// access rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="name">The identifier name.</param>
|
||||||
|
/// <param name="rights">The access rights.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="name"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="rights"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public AccessControl (string name, IEnumerable<AccessRight> rights)
|
||||||
|
{
|
||||||
|
if (name == null)
|
||||||
|
throw new ArgumentNullException (nameof (name));
|
||||||
|
|
||||||
|
Rights = new AccessRights (rights);
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessControl"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.AccessControl"/> with the given name and
|
||||||
|
/// access rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="name">The identifier name.</param>
|
||||||
|
/// <param name="rights">The access rights.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="name"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="rights"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public AccessControl (string name, string rights)
|
||||||
|
{
|
||||||
|
if (name == null)
|
||||||
|
throw new ArgumentNullException (nameof (name));
|
||||||
|
|
||||||
|
Rights = new AccessRights (rights);
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessControl"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.AccessControl"/> with the given name and no
|
||||||
|
/// access rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="name">The identifier name.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="name"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AccessControl (string name)
|
||||||
|
{
|
||||||
|
if (name == null)
|
||||||
|
throw new ArgumentNullException (nameof (name));
|
||||||
|
|
||||||
|
Rights = new AccessRights ();
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The identifier name for the access control.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The identifier name for the access control.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The identifier name.</value>
|
||||||
|
public string Name {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the access rights.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the access rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The access rights.</value>
|
||||||
|
public AccessRights Rights {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// AccessControlList.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An Access Control List (ACL)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An Access Control List (ACL) is a list of access controls defining the permissions
|
||||||
|
/// various identities have available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
public class AccessControlList : List<AccessControl>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessControlList"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.AccessControlList"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="controls">The list of access controls.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="controls"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AccessControlList (IEnumerable<AccessControl> controls) : base (controls)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessControlList"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.AccessControlList"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public AccessControlList ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
//
|
||||||
|
// AccessRight.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An individual Access Right to be used with ACLs.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An individual Access Right meant to be used with
|
||||||
|
/// <see cref="AccessControlList"/>.</para>
|
||||||
|
/// <para>For more information on what rights are available,
|
||||||
|
/// see https://tools.ietf.org/html/rfc4314#section-2.1
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public struct AccessRight : IEquatable<AccessRight>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for folder lookups.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Allows the <see cref="MailKit.IMailFolder"/> to be visible when listing folders.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight LookupFolder = new AccessRight ('l');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for opening a folder and getting the status.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access for opening and getting the status of the folder.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight OpenFolder = new AccessRight ('r');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for adding or removing the Seen flag on messages in the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to add or remove the <see cref="MessageFlags.Seen"/> flag on messages within the
|
||||||
|
/// <see cref="MailKit.IMailFolder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight SetMessageSeen = new AccessRight ('s');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for adding or removing flags (other than Seen and Deleted)
|
||||||
|
/// on messages in a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to add or remove the <see cref="MessageFlags"/> on messages
|
||||||
|
/// (other than <see cref="MessageFlags.Seen"/> and
|
||||||
|
/// <see cref="MessageFlags.Deleted"/>) within the folder.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight SetMessageFlags = new AccessRight ('w');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right allowing messages to be appended or copied into the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to append or copy messages into the folder.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight AppendMessages = new AccessRight ('i');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right allowing subfolders to be created.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to create subfolders.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight CreateFolder = new AccessRight ('k');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for deleting a folder and/or its subfolders.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to delete the folder and/or any subfolders.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight DeleteFolder = new AccessRight ('x');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for adding or removing the Deleted flag to messages within a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to add or remove the <see cref="MessageFlags.Deleted"/> flag from
|
||||||
|
/// messages within the folder. It also provides access for setting the
|
||||||
|
/// <see cref="MessageFlags.Deleted"/> flag when appending a message to a folder.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight SetMessageDeleted = new AccessRight ('t');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for expunging deleted messages in a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides access to expunge deleted messages in a folder.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight ExpungeFolder = new AccessRight ('e');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The access right for administering the ACLs of a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Provides administrative access to change the ACLs for the folder.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AccessRight Administer = new AccessRight ('a');
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The character representing the particular access right.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Represents the character value of the access right.
|
||||||
|
/// </remarks>
|
||||||
|
public readonly char Right;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessRight"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.AccessRight"/> struct.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="right">The access right.</param>
|
||||||
|
public AccessRight (char right)
|
||||||
|
{
|
||||||
|
Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEquatable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified <see cref="MailKit.AccessRight"/> is equal to the current <see cref="MailKit.AccessRight"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="MailKit.AccessRight"/> is equal to the current <see cref="MailKit.AccessRight"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="other">The <see cref="MailKit.AccessRight"/> to compare with the current <see cref="MailKit.AccessRight"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="MailKit.AccessRight"/> is equal to the current
|
||||||
|
/// <see cref="MailKit.AccessRight"/>; otherwise, <c>false</c>.</returns>
|
||||||
|
public bool Equals (AccessRight other)
|
||||||
|
{
|
||||||
|
return other.Right == Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether two access rights are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether two access rights are equal.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if <paramref name="right1"/> and <paramref name="right2"/> are equal; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="right1">The first access right to compare.</param>
|
||||||
|
/// <param name="right2">The second access right to compare.</param>
|
||||||
|
public static bool operator == (AccessRight right1, AccessRight right2)
|
||||||
|
{
|
||||||
|
return right1.Right == right2.Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether two access rights are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether two access rights are not equal.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if <paramref name="right1"/> and <paramref name="right2"/> are not equal; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="right1">The first access right to compare.</param>
|
||||||
|
/// <param name="right2">The second access right to compare.</param>
|
||||||
|
public static bool operator != (AccessRight right1, AccessRight right2)
|
||||||
|
{
|
||||||
|
return right1.Right != right2.Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AccessRight"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AccessRight"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="obj">The <see cref="System.Object"/> to compare with the current <see cref="MailKit.AccessRight"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AccessRight"/>;
|
||||||
|
/// otherwise, <c>false</c>.</returns>
|
||||||
|
public override bool Equals (object obj)
|
||||||
|
{
|
||||||
|
return obj is AccessRight && ((AccessRight) obj).Right == Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.AccessRight"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.AccessRight"/> object.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.</returns>
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return Right.GetHashCode ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AccessRight"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AccessRight"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.AccessRight"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
return Right.ToString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,317 @@
|
||||||
|
//
|
||||||
|
// AccessRights.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of access rights.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The set of access rights for a particular identity.
|
||||||
|
/// </remarks>
|
||||||
|
public class AccessRights : ICollection<AccessRight>
|
||||||
|
{
|
||||||
|
readonly List<AccessRight> list = new List<AccessRight> ();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessRights"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new set of access rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="rights">The access rights.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="rights"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AccessRights (IEnumerable<AccessRight> rights)
|
||||||
|
{
|
||||||
|
AddRange (rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessRights"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new set of access rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="rights">The access rights.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="rights"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AccessRights (string rights)
|
||||||
|
{
|
||||||
|
AddRange (rights);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AccessRights"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates an empty set of access rights.
|
||||||
|
/// </remarks>
|
||||||
|
public AccessRights ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the number of access rights in the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the number of access rights in the collection.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The count.</value>
|
||||||
|
public int Count {
|
||||||
|
get { return list.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not this set of access rights is read only.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not this set of access rights is read only.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if this collection is read only; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsReadOnly {
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the specified access right.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the specified access right if it is not already included.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="right">The access right.</param>
|
||||||
|
void ICollection<AccessRight>.Add (AccessRight right)
|
||||||
|
{
|
||||||
|
Add (right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the specified access right.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the specified access right if it is not already included.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if the right was added; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="right">The access right.</param>
|
||||||
|
public bool Add (AccessRight right)
|
||||||
|
{
|
||||||
|
if (list.Contains (right))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list.Add (right);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the specified right.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the right specified by the given character.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if the right was added; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="right">The right.</param>
|
||||||
|
public bool Add (char right)
|
||||||
|
{
|
||||||
|
return Add (new AccessRight (right));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the rights specified by the characters in the given string.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the rights specified by the characters in the given string.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="rights">The rights.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="rights"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public void AddRange (string rights)
|
||||||
|
{
|
||||||
|
if (rights == null)
|
||||||
|
throw new ArgumentNullException (nameof (rights));
|
||||||
|
|
||||||
|
for (int i = 0; i < rights.Length; i++)
|
||||||
|
Add (new AccessRight (rights[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the range of specified rights.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the range of specified rights.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="rights">The rights.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="rights"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public void AddRange (IEnumerable<AccessRight> rights)
|
||||||
|
{
|
||||||
|
if (rights == null)
|
||||||
|
throw new ArgumentNullException (nameof (rights));
|
||||||
|
|
||||||
|
foreach (var right in rights)
|
||||||
|
Add (right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the access rights.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Removes all of the access rights.
|
||||||
|
/// </remarks>
|
||||||
|
public void Clear ()
|
||||||
|
{
|
||||||
|
list.Clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the set of access rights contains the specified right.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether or not the set of access rights already contains the specified right
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><value>true</value> if the specified right exists; otherwise <value>false</value>.</returns>
|
||||||
|
/// <param name="right">The access right.</param>
|
||||||
|
public bool Contains (AccessRight right)
|
||||||
|
{
|
||||||
|
return list.Contains (right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies all of the access rights to the specified array.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Copies all of the access rights into the array,
|
||||||
|
/// starting at the specified array index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="array">The array.</param>
|
||||||
|
/// <param name="arrayIndex">The array index.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="array"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="arrayIndex"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public void CopyTo (AccessRight[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
throw new ArgumentNullException (nameof (array));
|
||||||
|
|
||||||
|
if (arrayIndex < 0 || arrayIndex + Count > array.Length)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (arrayIndex));
|
||||||
|
|
||||||
|
list.CopyTo (array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the specified access right.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Removes the specified access right.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><value>true</value> if the access right was removed; otherwise <value>false</value>.</returns>
|
||||||
|
/// <param name="right">The access right.</param>
|
||||||
|
public bool Remove (AccessRight right)
|
||||||
|
{
|
||||||
|
return list.Remove (right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the access right at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the access right at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The access right at the specified index.</value>
|
||||||
|
/// <param name="index">The index.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public AccessRight this [int index] {
|
||||||
|
get {
|
||||||
|
if (index < 0 || index >= list.Count)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
return list[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the access rights enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the access rights enumerator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The enumerator.</returns>
|
||||||
|
public IEnumerator<AccessRight> GetEnumerator ()
|
||||||
|
{
|
||||||
|
return list.GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the access rights enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the access rights enumerator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The enumerator.</returns>
|
||||||
|
IEnumerator IEnumerable.GetEnumerator ()
|
||||||
|
{
|
||||||
|
return list.GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a <see cref="System.String"/> that represents the current <see cref="MailKit.AccessRights"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AccessRights"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.AccessRights"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
var rights = new char[list.Count];
|
||||||
|
|
||||||
|
for (int i = 0; i < list.Count; i++)
|
||||||
|
rights[i] = list[i].Right;
|
||||||
|
|
||||||
|
return new string (rights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
//
|
||||||
|
// AlertEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Alert event arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Some <see cref="IMailStore"/> implementations, such as
|
||||||
|
/// <see cref="MailKit.Net.Imap.ImapClient"/>, will emit Alert
|
||||||
|
/// events when they receive alert messages from the server.
|
||||||
|
/// </remarks>
|
||||||
|
public class AlertEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AlertEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AlertEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The alert message.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="message"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AlertEventArgs (string message)
|
||||||
|
{
|
||||||
|
if (message == null)
|
||||||
|
throw new ArgumentNullException (nameof (message));
|
||||||
|
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the alert message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The alert message will be the exact message received from the server.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The alert message.</value>
|
||||||
|
public string Message {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
//
|
||||||
|
// Annotation.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An annotation.</para>
|
||||||
|
/// <para>For more information about annotations, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5257">rfc5257</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public class Annotation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Annotation"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="Annotation"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="entry">The annotation entry.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="entry"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public Annotation (AnnotationEntry entry)
|
||||||
|
{
|
||||||
|
if (entry == null)
|
||||||
|
throw new ArgumentNullException (nameof (entry));
|
||||||
|
|
||||||
|
Properties = new Dictionary<AnnotationAttribute, string> ();
|
||||||
|
Entry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the annotation tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the annotation tag.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The annotation tag.</value>
|
||||||
|
public AnnotationEntry Entry {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the annotation properties.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the annotation properties.
|
||||||
|
/// </remarks>
|
||||||
|
public Dictionary<AnnotationAttribute, string> Properties {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// AnnotationAccess.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation access level.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An annotation access level.</para>
|
||||||
|
/// <para>For more information about annotations, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5257">rfc5257</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public enum AnnotationAccess
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Annotations are not supported.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Annotations are read-only.
|
||||||
|
/// </summary>
|
||||||
|
ReadOnly,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Annotations are read-write.
|
||||||
|
/// </summary>
|
||||||
|
ReadWrite
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
//
|
||||||
|
// AnnotationAttribute.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation attribute.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An annotation attribute.</para>
|
||||||
|
/// <para>For more information about annotations, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5257">rfc5257</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public class AnnotationAttribute : IEquatable<AnnotationAttribute>
|
||||||
|
{
|
||||||
|
static readonly char[] Wildcards = { '*', '%' };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The annotation value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set both the private and shared values of an annotation.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationAttribute Value = new AnnotationAttribute ("value", AnnotationScope.Both);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The shared annotation value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set the shared value of an annotation.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationAttribute SharedValue = new AnnotationAttribute ("value", AnnotationScope.Shared);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The private annotation value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set the private value of an annotation.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationAttribute PrivateValue = new AnnotationAttribute ("value", AnnotationScope.Private);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of an annotation value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get the size of the both the private and shared annotation values.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationAttribute Size = new AnnotationAttribute ("size", AnnotationScope.Both);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of a shared annotation value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get the size of a shared annotation value.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationAttribute SharedSize = new AnnotationAttribute ("size", AnnotationScope.Shared);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of a private annotation value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get the size of a private annotation value.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationAttribute PrivateSize = new AnnotationAttribute ("size", AnnotationScope.Private);
|
||||||
|
|
||||||
|
AnnotationAttribute (string name, AnnotationScope scope)
|
||||||
|
{
|
||||||
|
switch (scope) {
|
||||||
|
case AnnotationScope.Shared: Specifier = string.Format ("{0}.shared", name); break;
|
||||||
|
case AnnotationScope.Private: Specifier = string.Format ("{0}.priv", name); break;
|
||||||
|
default: Specifier = name; break;
|
||||||
|
}
|
||||||
|
Scope = scope;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AnnotationAttribute"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="specifier">The annotation attribute specifier.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="specifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="specifier"/> contains illegal characters.
|
||||||
|
/// </exception>
|
||||||
|
public AnnotationAttribute (string specifier)
|
||||||
|
{
|
||||||
|
if (specifier == null)
|
||||||
|
throw new ArgumentNullException (nameof (specifier));
|
||||||
|
|
||||||
|
if (specifier.Length == 0)
|
||||||
|
throw new ArgumentException ("Annotation attribute specifiers cannot be empty.", nameof (specifier));
|
||||||
|
|
||||||
|
// TODO: improve validation
|
||||||
|
if (specifier.IndexOfAny (Wildcards) != -1)
|
||||||
|
throw new ArgumentException ("Annotation attribute specifiers cannot contain '*' or '%'.", nameof (specifier));
|
||||||
|
|
||||||
|
Specifier = specifier;
|
||||||
|
|
||||||
|
if (specifier.EndsWith (".shared", StringComparison.Ordinal)) {
|
||||||
|
Name = specifier.Substring (0, specifier.Length - ".shared".Length);
|
||||||
|
Scope = AnnotationScope.Shared;
|
||||||
|
} else if (specifier.EndsWith (".priv", StringComparison.Ordinal)) {
|
||||||
|
Name = specifier.Substring (0, specifier.Length - ".priv".Length);
|
||||||
|
Scope = AnnotationScope.Private;
|
||||||
|
} else {
|
||||||
|
Scope = AnnotationScope.Both;
|
||||||
|
Name = specifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the annotation attribute.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the name of the annotation attribute.
|
||||||
|
/// </remarks>
|
||||||
|
public string Name {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the scope of the annotation attribute.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the scope of the annotation attribute.
|
||||||
|
/// </remarks>
|
||||||
|
public AnnotationScope Scope {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the annotation attribute specifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the annotation attribute specifier.
|
||||||
|
/// </remarks>
|
||||||
|
public string Specifier {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEquatable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified <see cref="MailKit.AnnotationAttribute"/> is equal to the current <see cref="MailKit.AnnotationAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="MailKit.AnnotationAttribute"/> is equal to the current <see cref="MailKit.AnnotationAttribute"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="other">The <see cref="MailKit.AnnotationAttribute"/> to compare with the current <see cref="MailKit.AnnotationAttribute"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="MailKit.AnnotationAttribute"/> is equal to the current
|
||||||
|
/// <see cref="MailKit.AnnotationAttribute"/>; otherwise, <c>false</c>.</returns>
|
||||||
|
public bool Equals (AnnotationAttribute other)
|
||||||
|
{
|
||||||
|
return other?.Specifier == Specifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether two annotation attributes are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether two annotation attributes are equal.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if <paramref name="attr1"/> and <paramref name="attr2"/> are equal; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="attr1">The first annotation attribute to compare.</param>
|
||||||
|
/// <param name="attr2">The second annotation attribute to compare.</param>
|
||||||
|
public static bool operator == (AnnotationAttribute attr1, AnnotationAttribute attr2)
|
||||||
|
{
|
||||||
|
return attr1?.Specifier == attr2?.Specifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether two annotation attributes are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether two annotation attributes are not equal.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if <paramref name="attr1"/> and <paramref name="attr2"/> are not equal; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="attr1">The first annotation attribute to compare.</param>
|
||||||
|
/// <param name="attr2">The second annotation attribute to compare.</param>
|
||||||
|
public static bool operator != (AnnotationAttribute attr1, AnnotationAttribute attr2)
|
||||||
|
{
|
||||||
|
return attr1?.Specifier != attr2?.Specifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AnnotationAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AnnotationAttribute"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="obj">The <see cref="System.Object"/> to compare with the current <see cref="MailKit.AnnotationAttribute"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to the current
|
||||||
|
/// <see cref="MailKit.AnnotationAttribute"/>; otherwise, <c>false</c>.</returns>
|
||||||
|
public override bool Equals (object obj)
|
||||||
|
{
|
||||||
|
return obj is AnnotationAttribute && ((AnnotationAttribute) obj).Specifier == Specifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.AnnotationAttribute"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.AnnotationAttribute"/> object.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.</returns>
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return Specifier.GetHashCode ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AnnotationAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AnnotationAttribute"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.AnnotationAttribute"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
return Specifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,521 @@
|
||||||
|
//
|
||||||
|
// Annotationentry.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An annotation entry.</para>
|
||||||
|
/// <para>For more information about annotations, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5257">rfc5257</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public class AnnotationEntry : IEquatable<AnnotationEntry>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for a comment on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a comment on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry Comment = new AnnotationEntry ("/comment", AnnotationScope.Both);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for a private comment on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a private comment on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry PrivateComment = new AnnotationEntry ("/comment", AnnotationScope.Private);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for a shared comment on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a shared comment on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry SharedComment = new AnnotationEntry ("/comment", AnnotationScope.Shared);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for flags on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set flags on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry Flags = new AnnotationEntry ("/flags", AnnotationScope.Both);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for private flags on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set private flags on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry PrivateFlags = new AnnotationEntry ("/flags", AnnotationScope.Private);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Aa annotation entry for shared flags on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set shared flags on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry SharedFlags = new AnnotationEntry ("/flags", AnnotationScope.Shared);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for an alternate subject on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set an alternate subject on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry AltSubject = new AnnotationEntry ("/altsubject", AnnotationScope.Both);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for a private alternate subject on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a private alternate subject on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry PrivateAltSubject = new AnnotationEntry ("/altsubject", AnnotationScope.Private);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An annotation entry for a shared alternate subject on a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a shared alternate subject on a message.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly AnnotationEntry SharedAltSubject = new AnnotationEntry ("/altsubject", AnnotationScope.Shared);
|
||||||
|
|
||||||
|
static void ValidatePath (string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException (nameof (path));
|
||||||
|
|
||||||
|
if (path.Length == 0)
|
||||||
|
throw new ArgumentException ("Annotation entry paths cannot be empty.", nameof (path));
|
||||||
|
|
||||||
|
if (path[0] != '/' && path[0] != '*' && path[0] != '%')
|
||||||
|
throw new ArgumentException ("Annotation entry paths must begin with '/'.", nameof (path));
|
||||||
|
|
||||||
|
if (path.Length > 1 && path[1] >= '0' && path[1] <= '9')
|
||||||
|
throw new ArgumentException ("Annotation entry paths must not include a part-specifier.", nameof (path));
|
||||||
|
|
||||||
|
if (path == "*" || path == "%")
|
||||||
|
return;
|
||||||
|
|
||||||
|
char pc = path[0];
|
||||||
|
|
||||||
|
for (int i = 1; i < path.Length; i++) {
|
||||||
|
char c = path[i];
|
||||||
|
|
||||||
|
if (c > 127)
|
||||||
|
throw new ArgumentException ($"Invalid character in annotation entry path: '{c}'.", nameof (path));
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9' && pc == '/')
|
||||||
|
throw new ArgumentException ("Invalid annotation entry path.", nameof (path));
|
||||||
|
|
||||||
|
if ((pc == '/' || pc == '.') && (c == '/' || c == '.'))
|
||||||
|
throw new ArgumentException ("Invalid annotation entry path.", nameof (path));
|
||||||
|
|
||||||
|
pc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int endIndex = path.Length - 1;
|
||||||
|
|
||||||
|
if (path[endIndex] == '/')
|
||||||
|
throw new ArgumentException ("Annotation entry paths must not end with '/'.", nameof (path));
|
||||||
|
|
||||||
|
if (path[endIndex] == '.')
|
||||||
|
throw new ArgumentException ("Annotation entry paths must not end with '.'.", nameof (path));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ValidatePartSpecifier (string partSpecifier)
|
||||||
|
{
|
||||||
|
if (partSpecifier == null)
|
||||||
|
throw new ArgumentNullException (nameof (partSpecifier));
|
||||||
|
|
||||||
|
char pc = '\0';
|
||||||
|
|
||||||
|
for (int i = 0; i < partSpecifier.Length; i++) {
|
||||||
|
char c = partSpecifier[i];
|
||||||
|
|
||||||
|
if (!((c >= '0' && c <= '9') || c == '.') || (c == '.' && (pc == '.' || pc == '\0')))
|
||||||
|
throw new ArgumentException ("Invalid part-specifier.", nameof (partSpecifier));
|
||||||
|
|
||||||
|
pc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc == '.')
|
||||||
|
throw new ArgumentException ("Invalid part-specifier.", nameof (partSpecifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationEntry ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AnnotationEntry"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AnnotationEntry"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="path">The annotation entry path.</param>
|
||||||
|
/// <param name="scope">The scope of the annotation.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="path"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
public AnnotationEntry (string path, AnnotationScope scope = AnnotationScope.Both)
|
||||||
|
{
|
||||||
|
ValidatePath (path);
|
||||||
|
|
||||||
|
switch (scope) {
|
||||||
|
case AnnotationScope.Private: Entry = path + ".priv"; break;
|
||||||
|
case AnnotationScope.Shared: Entry = path + ".shared"; break;
|
||||||
|
default: Entry = path; break;
|
||||||
|
}
|
||||||
|
PartSpecifier = null;
|
||||||
|
Path = path;
|
||||||
|
Scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AnnotationEntry"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AnnotationEntry"/> for an individual body part of a message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="partSpecifier">The part-specifier of the body part of the message.</param>
|
||||||
|
/// <param name="path">The annotation entry path.</param>
|
||||||
|
/// <param name="scope">The scope of the annotation.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="partSpecifier"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="path"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para><paramref name="partSpecifier"/> is invalid.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="path"/> is invalid.</para>
|
||||||
|
/// </exception>
|
||||||
|
public AnnotationEntry (string partSpecifier, string path, AnnotationScope scope = AnnotationScope.Both)
|
||||||
|
{
|
||||||
|
ValidatePartSpecifier (partSpecifier);
|
||||||
|
ValidatePath (path);
|
||||||
|
|
||||||
|
switch (scope) {
|
||||||
|
case AnnotationScope.Private: Entry = string.Format ("/{0}{1}.priv", partSpecifier, path); break;
|
||||||
|
case AnnotationScope.Shared: Entry = string.Format ("/{0}{1}.shared", partSpecifier, path); break;
|
||||||
|
default: Entry = string.Format ("/{0}{1}", partSpecifier, path); break;
|
||||||
|
}
|
||||||
|
PartSpecifier = partSpecifier;
|
||||||
|
Path = path;
|
||||||
|
Scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AnnotationEntry"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AnnotationEntry"/> for an individual body part of a message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="part">The body part of the message.</param>
|
||||||
|
/// <param name="path">The annotation entry path.</param>
|
||||||
|
/// <param name="scope">The scope of the annotation.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="part"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="path"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="path"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
public AnnotationEntry (BodyPart part, string path, AnnotationScope scope = AnnotationScope.Both)
|
||||||
|
{
|
||||||
|
if (part == null)
|
||||||
|
throw new ArgumentNullException (nameof (part));
|
||||||
|
|
||||||
|
ValidatePath (path);
|
||||||
|
|
||||||
|
switch (scope) {
|
||||||
|
case AnnotationScope.Private: Entry = string.Format ("/{0}{1}.priv", part.PartSpecifier, path); break;
|
||||||
|
case AnnotationScope.Shared: Entry = string.Format ("/{0}{1}.shared", part.PartSpecifier, path); break;
|
||||||
|
default: Entry = string.Format ("/{0}{1}", part.PartSpecifier, path); break;
|
||||||
|
}
|
||||||
|
PartSpecifier = part.PartSpecifier;
|
||||||
|
Path = path;
|
||||||
|
Scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the annotation entry specifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the annotation entry specifier.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The annotation entry specifier.</value>
|
||||||
|
public string Entry {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the part-specifier component of the annotation entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the part-specifier component of the annotation entry.
|
||||||
|
/// </remarks>
|
||||||
|
public string PartSpecifier {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the path component of the annotation entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the path component of the annotation entry.
|
||||||
|
/// </remarks>
|
||||||
|
public string Path {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the scope of the annotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the scope of the annotation.
|
||||||
|
/// </remarks>
|
||||||
|
public AnnotationScope Scope {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEquatable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified <see cref="MailKit.AnnotationEntry"/> is equal to the current <see cref="MailKit.AnnotationEntry"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="MailKit.AnnotationEntry"/> is equal to the current <see cref="MailKit.AnnotationEntry"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="other">The <see cref="MailKit.AnnotationEntry"/> to compare with the current <see cref="MailKit.AnnotationEntry"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="MailKit.AnnotationEntry"/> is equal to the current
|
||||||
|
/// <see cref="MailKit.AnnotationEntry"/>; otherwise, <c>false</c>.</returns>
|
||||||
|
public bool Equals (AnnotationEntry other)
|
||||||
|
{
|
||||||
|
return other?.Entry == Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether two annotation entries are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether two annotation entries are equal.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if <paramref name="entry1"/> and <paramref name="entry2"/> are equal; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="entry1">The first annotation entry to compare.</param>
|
||||||
|
/// <param name="entry2">The second annotation entry to compare.</param>
|
||||||
|
public static bool operator == (AnnotationEntry entry1, AnnotationEntry entry2)
|
||||||
|
{
|
||||||
|
return entry1?.Entry == entry2?.Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether two annotation entries are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether two annotation entries are not equal.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c> if <paramref name="entry1"/> and <paramref name="entry2"/> are not equal; otherwise, <c>false</c>.</returns>
|
||||||
|
/// <param name="entry1">The first annotation entry to compare.</param>
|
||||||
|
/// <param name="entry2">The second annotation entry to compare.</param>
|
||||||
|
public static bool operator != (AnnotationEntry entry1, AnnotationEntry entry2)
|
||||||
|
{
|
||||||
|
return entry1?.Entry != entry2?.Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AnnotationEntry"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.AnnotationEntry"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="obj">The <see cref="System.Object"/> to compare with the current <see cref="MailKit.AnnotationEntry"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to the current
|
||||||
|
/// <see cref="MailKit.AnnotationEntry"/>; otherwise, <c>false</c>.</returns>
|
||||||
|
public override bool Equals (object obj)
|
||||||
|
{
|
||||||
|
return obj is AnnotationEntry && ((AnnotationEntry) obj).Entry == Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.AnnotationEntry"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.AnnotationEntry"/> object.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.</returns>
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return Entry.GetHashCode ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AnnotationEntry"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.AnnotationEntry"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.AnnotationEntry"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
return Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parse an annotation entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Parses an annotation entry.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="entry">The annotation entry.</param>
|
||||||
|
/// <returns>The parsed annotation entry.</returns>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="entry"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.FormatException">
|
||||||
|
/// <paramref name="entry"/> does not conform to the annotation entry syntax.
|
||||||
|
/// </exception>
|
||||||
|
public static AnnotationEntry Parse (string entry)
|
||||||
|
{
|
||||||
|
if (entry == null)
|
||||||
|
throw new ArgumentNullException (nameof (entry));
|
||||||
|
|
||||||
|
if (entry.Length == 0)
|
||||||
|
throw new FormatException ("An annotation entry cannot be empty.");
|
||||||
|
|
||||||
|
if (entry[0] != '/' && entry[0] != '*' && entry[0] != '%')
|
||||||
|
throw new FormatException ("An annotation entry must begin with a '/' character.");
|
||||||
|
|
||||||
|
var scope = AnnotationScope.Both;
|
||||||
|
int startIndex = 0, endIndex;
|
||||||
|
string partSpecifier = null;
|
||||||
|
var component = 0;
|
||||||
|
var pc = entry[0];
|
||||||
|
string path;
|
||||||
|
|
||||||
|
for (int i = 1; i < entry.Length; i++) {
|
||||||
|
char c = entry[i];
|
||||||
|
|
||||||
|
if (c >= '0' && c <= '9' && pc == '/') {
|
||||||
|
if (component > 0)
|
||||||
|
throw new FormatException ("Invalid annotation entry.");
|
||||||
|
|
||||||
|
startIndex = i;
|
||||||
|
endIndex = i + 1;
|
||||||
|
pc = c;
|
||||||
|
|
||||||
|
while (endIndex < entry.Length) {
|
||||||
|
c = entry[endIndex];
|
||||||
|
|
||||||
|
if (c == '/') {
|
||||||
|
if (pc == '.')
|
||||||
|
throw new FormatException ("Invalid part-specifier in annotation entry.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(c >= '0' && c <= '9') && c != '.')
|
||||||
|
throw new FormatException ($"Invalid character in part-specifier: '{c}'.");
|
||||||
|
|
||||||
|
if (c == '.' && pc == '.')
|
||||||
|
throw new FormatException ("Invalid part-specifier in annotation entry.");
|
||||||
|
|
||||||
|
endIndex++;
|
||||||
|
pc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endIndex >= entry.Length)
|
||||||
|
throw new FormatException ("Incomplete part-specifier in annotation entry.");
|
||||||
|
|
||||||
|
partSpecifier = entry.Substring (startIndex, endIndex - startIndex);
|
||||||
|
i = startIndex = endIndex;
|
||||||
|
component++;
|
||||||
|
} else if (c == '/' || c == '.') {
|
||||||
|
if (pc == '/' || pc == '.')
|
||||||
|
throw new FormatException ("Invalid annotation entry path.");
|
||||||
|
|
||||||
|
if (c == '/')
|
||||||
|
component++;
|
||||||
|
} else if (c > 127) {
|
||||||
|
throw new FormatException ($"Invalid character in annotation entry path: '{c}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
pc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc == '/' || pc == '.')
|
||||||
|
throw new FormatException ("Invalid annotation entry path.");
|
||||||
|
|
||||||
|
if (entry.EndsWith (".shared", StringComparison.Ordinal)) {
|
||||||
|
endIndex = entry.Length - ".shared".Length;
|
||||||
|
scope = AnnotationScope.Shared;
|
||||||
|
} else if (entry.EndsWith (".priv", StringComparison.Ordinal)) {
|
||||||
|
endIndex = entry.Length - ".priv".Length;
|
||||||
|
scope = AnnotationScope.Private;
|
||||||
|
} else {
|
||||||
|
endIndex = entry.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = entry.Substring (startIndex, endIndex - startIndex);
|
||||||
|
|
||||||
|
return new AnnotationEntry {
|
||||||
|
PartSpecifier = partSpecifier,
|
||||||
|
Entry = entry,
|
||||||
|
Path = path,
|
||||||
|
Scope = scope
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static AnnotationEntry Create (string entry)
|
||||||
|
{
|
||||||
|
switch (entry) {
|
||||||
|
case "/comment": return Comment;
|
||||||
|
case "/comment.priv": return PrivateComment;
|
||||||
|
case "/comment.shared": return SharedComment;
|
||||||
|
case "/flags": return Flags;
|
||||||
|
case "/flags.priv": return PrivateFlags;
|
||||||
|
case "/flags.shared": return SharedFlags;
|
||||||
|
case "/altsubject": return AltSubject;
|
||||||
|
case "/altsubject.priv": return PrivateAltSubject;
|
||||||
|
case "/altsubject.shared": return SharedAltSubject;
|
||||||
|
default: return Parse (entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// AnnotationScope.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// The scope of an annotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Represents the scope of an annotation.</para>
|
||||||
|
/// <para>For more information about annotations, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5257">rfc5257</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum AnnotationScope
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No scopes.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The private annotation scope.
|
||||||
|
/// </summary>
|
||||||
|
Private,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The shared annotation scope.
|
||||||
|
/// </summary>
|
||||||
|
Shared,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Both private and shared scopes.
|
||||||
|
/// </summary>
|
||||||
|
Both = Private | Shared
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
//
|
||||||
|
// AnnotationsChangedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when an annotation changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when an annotation changes.
|
||||||
|
/// </remarks>
|
||||||
|
public class AnnotationsChangedEventArgs : MessageEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AnnotationsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AnnotationsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
internal AnnotationsChangedEventArgs (int index) : base (index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.AnnotationsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AnnotationsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="annotations">The annotations that changed.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="annotations"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AnnotationsChangedEventArgs (int index, IEnumerable<Annotation> annotations) : base (index)
|
||||||
|
{
|
||||||
|
if (annotations == null)
|
||||||
|
throw new ArgumentNullException (nameof (annotations));
|
||||||
|
|
||||||
|
Annotations = new ReadOnlyCollection<Annotation> (annotations.ToArray ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the annotations that changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the annotations that changed.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The annotation.</value>
|
||||||
|
public IList<Annotation> Annotations {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated mod-sequence value of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated mod-sequence value of the message, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mod-sequence value.</value>
|
||||||
|
public ulong? ModSeq {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
//
|
||||||
|
// AuthenticatedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Authenticated event arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Some servers, such as GMail IMAP, will send some free-form text in
|
||||||
|
/// the response to a successful login.
|
||||||
|
/// </remarks>
|
||||||
|
public class AuthenticatedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.AuthenticatedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="AuthenticatedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The free-form text.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="message"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public AuthenticatedEventArgs (string message)
|
||||||
|
{
|
||||||
|
if (message == null)
|
||||||
|
throw new ArgumentNullException (nameof (message));
|
||||||
|
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the free-form text sent by the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the free-form text sent by the server.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The free-form text sent by the server.</value>
|
||||||
|
public string Message {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,716 @@
|
||||||
|
//
|
||||||
|
// BodyPart.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An abstract body part of a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Each body part will actually be a <see cref="BodyPartBasic"/>,
|
||||||
|
/// <see cref="BodyPartText"/>, <see cref="BodyPartMessage"/>, or
|
||||||
|
/// <see cref="BodyPartMultipart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
public abstract class BodyPart
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.BodyPart"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.BodyPart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
protected BodyPart ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Type of the body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Content-Type of the body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content type.</value>
|
||||||
|
public ContentType ContentType {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the part specifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the part specifier.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The part specifier.</value>
|
||||||
|
public string PartSpecifier {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches to the specific visit method for this MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This default implementation for <see cref="MailKit.BodyPart"/> nodes
|
||||||
|
/// calls <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>. Override this
|
||||||
|
/// method to call into a more specific method on a derived visitor class
|
||||||
|
/// of the <see cref="MailKit.BodyPartVisitor"/> class. However, it should still
|
||||||
|
/// support unknown visitors by calling
|
||||||
|
/// <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="visitor">The visitor.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="visitor"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public abstract void Accept (BodyPartVisitor visitor);
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, uint value)
|
||||||
|
{
|
||||||
|
builder.Append (value.ToString ());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, string value)
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
builder.Append (MimeUtils.Quote (value));
|
||||||
|
else
|
||||||
|
builder.Append ("NIL");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, Uri location)
|
||||||
|
{
|
||||||
|
if (location != null)
|
||||||
|
builder.Append (MimeUtils.Quote (location.ToString ()));
|
||||||
|
else
|
||||||
|
builder.Append ("NIL");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, string[] values)
|
||||||
|
{
|
||||||
|
if (values == null || values.Length == 0) {
|
||||||
|
builder.Append ("NIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append ('(');
|
||||||
|
|
||||||
|
for (int i = 0; i < values.Length; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
builder.Append (' ');
|
||||||
|
|
||||||
|
Encode (builder, values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, IList<Parameter> parameters)
|
||||||
|
{
|
||||||
|
if (parameters == null || parameters.Count == 0) {
|
||||||
|
builder.Append ("NIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append ('(');
|
||||||
|
|
||||||
|
for (int i = 0; i < parameters.Count; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
builder.Append (' ');
|
||||||
|
|
||||||
|
Encode (builder, parameters[i].Name);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, parameters[i].Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, ContentDisposition disposition)
|
||||||
|
{
|
||||||
|
if (disposition == null) {
|
||||||
|
builder.Append ("NIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append ('(');
|
||||||
|
Encode (builder, disposition.Disposition);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, disposition.Parameters);
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, ContentType contentType)
|
||||||
|
{
|
||||||
|
Encode (builder, contentType.MediaType);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, contentType.MediaSubtype);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, contentType.Parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, BodyPartCollection parts)
|
||||||
|
{
|
||||||
|
if (parts == null || parts.Count == 0) {
|
||||||
|
builder.Append ("NIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < parts.Count; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
builder.Append (' ');
|
||||||
|
|
||||||
|
Encode (builder, parts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, Envelope envelope)
|
||||||
|
{
|
||||||
|
if (envelope == null) {
|
||||||
|
builder.Append ("NIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
envelope.Encode (builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Encode (StringBuilder builder, BodyPart body)
|
||||||
|
{
|
||||||
|
if (body == null) {
|
||||||
|
builder.Append ("NIL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append ('(');
|
||||||
|
body.Encode (builder);
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="builder">The string builder.</param>
|
||||||
|
protected abstract void Encode (StringBuilder builder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.BodyPart"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.BodyPart"/>.</para>
|
||||||
|
/// <note type="note">The syntax of the string returned, while similar to IMAP's BODYSTRUCTURE syntax,
|
||||||
|
/// is not completely compatible.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.BodyPart"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder ();
|
||||||
|
|
||||||
|
builder.Append ('(');
|
||||||
|
Encode (builder);
|
||||||
|
builder.Append (')');
|
||||||
|
|
||||||
|
return builder.ToString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out uint value)
|
||||||
|
{
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
int startIndex = index;
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
|
||||||
|
while (index < text.Length && char.IsDigit (text[index]))
|
||||||
|
value = (value * 10) + (uint) (text[index++] - '0');
|
||||||
|
|
||||||
|
return index > startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out string nstring)
|
||||||
|
{
|
||||||
|
nstring = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] != '"') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = new StringBuilder ();
|
||||||
|
bool escaped = false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
while (index < text.Length) {
|
||||||
|
if (text[index] == '"' && !escaped)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (escaped || text[index] != '\\') {
|
||||||
|
token.Append (text[index]);
|
||||||
|
escaped = false;
|
||||||
|
} else {
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nstring = token.ToString ();
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out string[] values)
|
||||||
|
{
|
||||||
|
values = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] != '(') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var list = new List<string> ();
|
||||||
|
string value;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (text[index] == ')')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list.Add (value);
|
||||||
|
} while (index < text.Length);
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != ')')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
values = list.ToArray ();
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out Uri uri)
|
||||||
|
{
|
||||||
|
string nstring;
|
||||||
|
|
||||||
|
uri = null;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out nstring))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty (nstring)) {
|
||||||
|
if (Uri.IsWellFormedUriString (nstring, UriKind.Absolute))
|
||||||
|
uri = new Uri (nstring, UriKind.Absolute);
|
||||||
|
else if (Uri.IsWellFormedUriString (nstring, UriKind.Relative))
|
||||||
|
uri = new Uri (nstring, UriKind.Relative);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out IList<Parameter> parameters)
|
||||||
|
{
|
||||||
|
string name, value;
|
||||||
|
|
||||||
|
parameters = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] != '(') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
parameters = new List<Parameter> ();
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parameters = new List<Parameter> ();
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (text[index] == ')')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parameters.Add (new Parameter (name, value));
|
||||||
|
} while (index < text.Length);
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != ')')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out ContentDisposition disposition)
|
||||||
|
{
|
||||||
|
IList<Parameter> parameters;
|
||||||
|
string value;
|
||||||
|
|
||||||
|
disposition = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] != '(') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out parameters))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != ')')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
disposition = new ContentDisposition (value);
|
||||||
|
|
||||||
|
foreach (var param in parameters)
|
||||||
|
disposition.Parameters.Add (param);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, bool multipart, out ContentType contentType)
|
||||||
|
{
|
||||||
|
IList<Parameter> parameters;
|
||||||
|
string type, subtype;
|
||||||
|
|
||||||
|
contentType = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!multipart) {
|
||||||
|
if (!TryParse (text, ref index, out type))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
type = "multipart";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out subtype))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out parameters))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
contentType = new ContentType (type ?? "application", subtype ?? "octet-stream");
|
||||||
|
|
||||||
|
foreach (var param in parameters)
|
||||||
|
contentType.Parameters.Add (param);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, string prefix, out IList<BodyPart> children)
|
||||||
|
{
|
||||||
|
BodyPart part;
|
||||||
|
string path;
|
||||||
|
int id = 1;
|
||||||
|
|
||||||
|
children = null;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
children = new List<BodyPart> ();
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (text[index] != '(')
|
||||||
|
break;
|
||||||
|
|
||||||
|
path = prefix + id;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, path, out part))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
children.Add (part);
|
||||||
|
id++;
|
||||||
|
} while (index < text.Length);
|
||||||
|
|
||||||
|
return index < text.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, string path, out BodyPart part)
|
||||||
|
{
|
||||||
|
ContentDisposition disposition;
|
||||||
|
ContentType contentType;
|
||||||
|
string[] array;
|
||||||
|
string nstring;
|
||||||
|
Uri location;
|
||||||
|
uint number;
|
||||||
|
|
||||||
|
part = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != '(') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] == '(') {
|
||||||
|
var prefix = path.Length > 0 ? path + "." : string.Empty;
|
||||||
|
var multipart = new BodyPartMultipart ();
|
||||||
|
IList<BodyPart> children;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, prefix, out children))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var child in children)
|
||||||
|
multipart.BodyParts.Add (child);
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, true, out contentType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
multipart.ContentType = contentType;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out disposition))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
multipart.ContentDisposition = disposition;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out array))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
multipart.ContentLanguage = array;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out location))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
multipart.ContentLocation = location;
|
||||||
|
|
||||||
|
part = multipart;
|
||||||
|
} else {
|
||||||
|
BodyPartMessage message = null;
|
||||||
|
BodyPartText txt = null;
|
||||||
|
BodyPartBasic basic;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, false, out contentType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (contentType.IsMimeType ("message", "rfc822"))
|
||||||
|
basic = message = new BodyPartMessage ();
|
||||||
|
else if (contentType.IsMimeType ("text", "*"))
|
||||||
|
basic = txt = new BodyPartText ();
|
||||||
|
else
|
||||||
|
basic = new BodyPartBasic ();
|
||||||
|
|
||||||
|
basic.ContentType = contentType;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out nstring))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentId = nstring;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out nstring))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentDescription = nstring;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out nstring))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentTransferEncoding = nstring;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out number))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.Octets = number;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out nstring))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentMd5 = nstring;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out disposition))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentDisposition = disposition;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out array))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentLanguage = array;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out location))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic.ContentLocation = location;
|
||||||
|
|
||||||
|
if (message != null) {
|
||||||
|
Envelope envelope;
|
||||||
|
BodyPart body;
|
||||||
|
|
||||||
|
if (!Envelope.TryParse (text, ref index, out envelope))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
message.Envelope = envelope;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, path, out body))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
message.Body = body;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out number))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
message.Lines = number;
|
||||||
|
} else if (txt != null) {
|
||||||
|
if (!TryParse (text, ref index, out number))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
txt.Lines = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = basic;
|
||||||
|
}
|
||||||
|
|
||||||
|
part.PartSpecifier = path;
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != ')')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to parse the given text into a new <see cref="MailKit.BodyPart"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Parses a body part from the specified text.</para>
|
||||||
|
/// <note type="note">This syntax, while similar to IMAP's BODYSTRUCTURE syntax, is not completely
|
||||||
|
/// compatible.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c>, if the body part was successfully parsed, <c>false</c> otherwise.</returns>
|
||||||
|
/// <param name="text">The text to parse.</param>
|
||||||
|
/// <param name="part">The parsed body part.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="text"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool TryParse (string text, out BodyPart part)
|
||||||
|
{
|
||||||
|
if (text == null)
|
||||||
|
throw new ArgumentNullException (nameof (text));
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
return TryParse (text, ref index, string.Empty, out part) && index == text.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,245 @@
|
||||||
|
//
|
||||||
|
// BodyPartBasic.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A basic message body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Represents any message body part that is not a multipart,
|
||||||
|
/// message/rfc822 part, or a text part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
public class BodyPartBasic : BodyPart
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.BodyPartBasic"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="BodyPartBasic"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public BodyPartBasic ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Id of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Content-Id of the body part, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content identifier.</value>
|
||||||
|
public string ContentId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Description of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Content-Description of the body part, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content description.</value>
|
||||||
|
public string ContentDescription {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Transfer-Encoding of the body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the Content-Transfer-Encoding of the body part.</para>
|
||||||
|
/// <para>Hint: Use the <a href="M_MimeKit_Utils_MimeUtils_TryParse_1.htm">MimeUtils.TryParse</a>
|
||||||
|
/// method to parse this value into a usable <see cref="MimeKit.ContentEncoding"/>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content transfer encoding.</value>
|
||||||
|
public string ContentTransferEncoding {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the size of the body part, in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the size of the body part, in bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The number of octets.</value>
|
||||||
|
public uint Octets {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the MD5 hash of the content, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the MD5 hash of the content, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content md5.</value>
|
||||||
|
public string ContentMd5 {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Disposition of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the Content-Disposition of the body part, if available.</para>
|
||||||
|
/// <note type="note">The Content-Disposition value is only retrieved if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is used when fetching
|
||||||
|
/// summary information from an <see cref="IMailFolder"/>.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content disposition.</value>
|
||||||
|
public ContentDisposition ContentDisposition {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Language of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the Content-Language of the body part, if available.</para>
|
||||||
|
/// <para>The Content-Language value is only retrieved if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is used when fetching
|
||||||
|
/// summary information from an <see cref="IMailFolder"/>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content language.</value>
|
||||||
|
public string[] ContentLanguage {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Location of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the Content-Location of the body part, if available.</para>
|
||||||
|
/// <para>The Content-Location value is only retrieved if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is used when fetching
|
||||||
|
/// summary information from an <see cref="IMailFolder"/>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content location.</value>
|
||||||
|
public Uri ContentLocation {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether or not the body part is an attachment.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Determines whether or not the body part is an attachment based on the value of
|
||||||
|
/// the Content-Disposition.</para>
|
||||||
|
/// <note type="note">Since the value of the Content-Disposition header is needed, it
|
||||||
|
/// is necessary to include the <see cref="MessageSummaryItems.BodyStructure"/> flag when
|
||||||
|
/// fetching summary information from an <see cref="IMailFolder"/>.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if this part is an attachment; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsAttachment {
|
||||||
|
get { return ContentDisposition != null && ContentDisposition.IsAttachment; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the file.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>First checks for the "filename" parameter on the Content-Disposition header. If
|
||||||
|
/// that does not exist, then the "name" parameter on the Content-Type header is used.</para>
|
||||||
|
/// <note type="note">Since the value of the Content-Disposition header is needed, it is
|
||||||
|
/// necessary to include the <see cref="MessageSummaryItems.BodyStructure"/> flag when
|
||||||
|
/// fetching summary information from an <see cref="IMailFolder"/>.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the file.</value>
|
||||||
|
public string FileName {
|
||||||
|
get {
|
||||||
|
string filename = null;
|
||||||
|
|
||||||
|
if (ContentDisposition != null)
|
||||||
|
filename = ContentDisposition.FileName;
|
||||||
|
|
||||||
|
if (filename == null)
|
||||||
|
filename = ContentType.Name;
|
||||||
|
|
||||||
|
return filename != null ? filename.Trim () : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches to the specific visit method for this MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This default implementation for <see cref="MailKit.BodyPart"/> nodes
|
||||||
|
/// calls <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>. Override this
|
||||||
|
/// method to call into a more specific method on a derived visitor class
|
||||||
|
/// of the <see cref="MailKit.BodyPartVisitor"/> class. However, it should still
|
||||||
|
/// support unknown visitors by calling
|
||||||
|
/// <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="visitor">The visitor.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="visitor"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public override void Accept (BodyPartVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
throw new ArgumentNullException (nameof (visitor));
|
||||||
|
|
||||||
|
visitor.VisitBodyPartBasic (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="builder">The string builder.</param>
|
||||||
|
protected override void Encode (StringBuilder builder)
|
||||||
|
{
|
||||||
|
Encode (builder, ContentType);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentId);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentDescription);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentTransferEncoding);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, Octets);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentMd5);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentDisposition);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentLanguage);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,276 @@
|
||||||
|
//
|
||||||
|
// BodyPartCollection.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A <see cref="BodyPart"/> collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A <see cref="BodyPart"/> collection.
|
||||||
|
/// </remarks>
|
||||||
|
public class BodyPartCollection : ICollection<BodyPart>
|
||||||
|
{
|
||||||
|
readonly List<BodyPart> collection = new List<BodyPart> ();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.BodyPartCollection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.BodyPartCollection"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public BodyPartCollection ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the number of body parts in the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the number of body parts in the collection.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The count.</value>
|
||||||
|
public int Count {
|
||||||
|
get { return collection.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not this body part collection is read only.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not this body part collection is read only.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if this collection is read only; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsReadOnly {
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the specified body part to the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the specified body part to the collection.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="part">The body part.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="part"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public void Add (BodyPart part)
|
||||||
|
{
|
||||||
|
if (part == null)
|
||||||
|
throw new ArgumentNullException (nameof (part));
|
||||||
|
|
||||||
|
collection.Add (part);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the body part collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Removes all of the body parts from the collection.
|
||||||
|
/// </remarks>
|
||||||
|
public void Clear ()
|
||||||
|
{
|
||||||
|
collection.Clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the collection contains the specified body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether or not the collection contains the specified body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><value>true</value> if the specified body part exists; otherwise <value>false</value>.</returns>
|
||||||
|
/// <param name="part">The body part.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="part"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public bool Contains (BodyPart part)
|
||||||
|
{
|
||||||
|
if (part == null)
|
||||||
|
throw new ArgumentNullException (nameof (part));
|
||||||
|
|
||||||
|
return collection.Contains (part);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies all of the body parts in the collection to the specified array.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Copies all of the body parts within the collection into the array,
|
||||||
|
/// starting at the specified array index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="array">The array.</param>
|
||||||
|
/// <param name="arrayIndex">The array index.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="array"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="arrayIndex"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public void CopyTo (BodyPart[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
if (array == null)
|
||||||
|
throw new ArgumentNullException (nameof (array));
|
||||||
|
|
||||||
|
if (arrayIndex < 0 || arrayIndex + Count > array.Length)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (arrayIndex));
|
||||||
|
|
||||||
|
collection.CopyTo (array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the specified body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Removes the specified body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><value>true</value> if the body part was removed; otherwise <value>false</value>.</returns>
|
||||||
|
/// <param name="part">The body part.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="part"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public bool Remove (BodyPart part)
|
||||||
|
{
|
||||||
|
if (part == null)
|
||||||
|
throw new ArgumentNullException (nameof (part));
|
||||||
|
|
||||||
|
return collection.Remove (part);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the body part at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the body part at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The body part at the specified index.</value>
|
||||||
|
/// <param name="index">The index.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public BodyPart this [int index] {
|
||||||
|
get {
|
||||||
|
if (index < 0 || index >= collection.Count)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
return collection[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the index of the body part matching the specified URI.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Finds the index of the body part matching the specified URI, if it exists.</para>
|
||||||
|
/// <para>If the URI scheme is <c>"cid"</c>, then matching is performed based on the Content-Id header
|
||||||
|
/// values, otherwise the Content-Location headers are used. If the provided URI is absolute and a child
|
||||||
|
/// part's Content-Location is relative, then then the child part's Content-Location URI will be combined
|
||||||
|
/// with the value of its Content-Base header, if available, otherwise it will be combined with the
|
||||||
|
/// multipart/related part's Content-Base header in order to produce an absolute URI that can be
|
||||||
|
/// compared with the provided absolute URI.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The index of the part matching the specified URI if found; otherwise <c>-1</c>.</returns>
|
||||||
|
/// <param name="uri">The URI of the body part.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="uri"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public int IndexOf (Uri uri)
|
||||||
|
{
|
||||||
|
if (uri == null)
|
||||||
|
throw new ArgumentNullException (nameof (uri));
|
||||||
|
|
||||||
|
bool cid = uri.IsAbsoluteUri && uri.Scheme.ToLowerInvariant () == "cid";
|
||||||
|
|
||||||
|
for (int index = 0; index < Count; index++) {
|
||||||
|
var bodyPart = this[index] as BodyPartBasic;
|
||||||
|
|
||||||
|
if (bodyPart == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (uri.IsAbsoluteUri) {
|
||||||
|
if (cid) {
|
||||||
|
if (!string.IsNullOrEmpty (bodyPart.ContentId)) {
|
||||||
|
// Note: we might have a Content-Id in the form "<id@domain.com>", so attempt to decode it
|
||||||
|
var id = MimeUtils.EnumerateReferences (bodyPart.ContentId).FirstOrDefault () ?? bodyPart.ContentId;
|
||||||
|
|
||||||
|
if (id == uri.AbsolutePath)
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
} else if (bodyPart.ContentLocation != null) {
|
||||||
|
if (!bodyPart.ContentLocation.IsAbsoluteUri)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bodyPart.ContentLocation == uri)
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
} else if (bodyPart.ContentLocation == uri) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the body part enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the body part enumerator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The enumerator.</returns>
|
||||||
|
public IEnumerator<BodyPart> GetEnumerator ()
|
||||||
|
{
|
||||||
|
return collection.GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the body part enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the body part enumerator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The enumerator.</returns>
|
||||||
|
IEnumerator IEnumerable.GetEnumerator ()
|
||||||
|
{
|
||||||
|
return GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
//
|
||||||
|
// BodyPartMessage.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A message/rfc822 body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Represents a message/rfc822 body part.
|
||||||
|
/// </remarks>
|
||||||
|
public class BodyPartMessage : BodyPartBasic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.BodyPartMessage"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="BodyPartMessage"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public BodyPartMessage ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the envelope of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the envelope of the message, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The envelope.</value>
|
||||||
|
public Envelope Envelope {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the body structure of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the body structure of the message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The body structure.</value>
|
||||||
|
public BodyPart Body {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the message, in lines.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the length of the message, in lines.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The number of lines.</value>
|
||||||
|
public uint Lines {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches to the specific visit method for this MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This default implementation for <see cref="MailKit.BodyPart"/> nodes
|
||||||
|
/// calls <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>. Override this
|
||||||
|
/// method to call into a more specific method on a derived visitor class
|
||||||
|
/// of the <see cref="MailKit.BodyPartVisitor"/> class. However, it should still
|
||||||
|
/// support unknown visitors by calling
|
||||||
|
/// <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="visitor">The visitor.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="visitor"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public override void Accept (BodyPartVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
throw new ArgumentNullException (nameof (visitor));
|
||||||
|
|
||||||
|
visitor.VisitBodyPartMessage (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="builder">The string builder.</param>
|
||||||
|
protected override void Encode (StringBuilder builder)
|
||||||
|
{
|
||||||
|
base.Encode (builder);
|
||||||
|
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, Envelope);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, Body);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, Lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
//
|
||||||
|
// BodyPartMultipart.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A multipart body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A multipart body part.
|
||||||
|
/// </remarks>
|
||||||
|
public class BodyPartMultipart : BodyPart
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.BodyPartMultipart"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="BodyPartMultipart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public BodyPartMultipart ()
|
||||||
|
{
|
||||||
|
BodyParts = new BodyPartCollection ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the child body parts.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the child body parts.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The child body parts.</value>
|
||||||
|
public BodyPartCollection BodyParts {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Disposition of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Content-Disposition of the body part, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content disposition.</value>
|
||||||
|
public ContentDisposition ContentDisposition {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Language of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Content-Language of the body part, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content language.</value>
|
||||||
|
public string[] ContentLanguage {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Content-Location of the body part, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Content-Location of the body part, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The content location.</value>
|
||||||
|
public Uri ContentLocation {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches to the specific visit method for this MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This default implementation for <see cref="MailKit.BodyPart"/> nodes
|
||||||
|
/// calls <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>. Override this
|
||||||
|
/// method to call into a more specific method on a derived visitor class
|
||||||
|
/// of the <see cref="MailKit.BodyPartVisitor"/> class. However, it should still
|
||||||
|
/// support unknown visitors by calling
|
||||||
|
/// <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="visitor">The visitor.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="visitor"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public override void Accept (BodyPartVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
throw new ArgumentNullException (nameof (visitor));
|
||||||
|
|
||||||
|
visitor.VisitBodyPartMultipart (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="builder">The string builder.</param>
|
||||||
|
protected override void Encode (StringBuilder builder)
|
||||||
|
{
|
||||||
|
Encode (builder, BodyParts);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentType.MediaSubtype);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentType.Parameters);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentDisposition);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentLanguage);
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, ContentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
//
|
||||||
|
// BodyPartText.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A textual body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Represents any body part with a media type of "text".
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
public class BodyPartText : BodyPartBasic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.BodyPartText"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="BodyPartText"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public BodyPartText ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not this text part contains plain text.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Checks whether or not the text part's Content-Type is text/plain.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the text is html; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsPlain {
|
||||||
|
get { return ContentType.IsMimeType ("text", "plain"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not this text part contains HTML.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Checks whether or not the text part's Content-Type is text/html.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the text is html; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsHtml {
|
||||||
|
get { return ContentType.IsMimeType ("text", "html"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the text, in lines.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the length of the text, in lines.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The number of lines.</value>
|
||||||
|
public uint Lines {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches to the specific visit method for this MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This default implementation for <see cref="MailKit.BodyPart"/> nodes
|
||||||
|
/// calls <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>. Override this
|
||||||
|
/// method to call into a more specific method on a derived visitor class
|
||||||
|
/// of the <see cref="MailKit.BodyPartVisitor"/> class. However, it should still
|
||||||
|
/// support unknown visitors by calling
|
||||||
|
/// <see cref="MailKit.BodyPartVisitor.VisitBodyPart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="visitor">The visitor.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="visitor"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public override void Accept (BodyPartVisitor visitor)
|
||||||
|
{
|
||||||
|
if (visitor == null)
|
||||||
|
throw new ArgumentNullException (nameof (visitor));
|
||||||
|
|
||||||
|
visitor.VisitBodyPartText (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Encodes the <see cref="BodyPart"/> into the <see cref="System.Text.StringBuilder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="builder">The string builder.</param>
|
||||||
|
protected override void Encode (StringBuilder builder)
|
||||||
|
{
|
||||||
|
base.Encode (builder);
|
||||||
|
|
||||||
|
builder.Append (' ');
|
||||||
|
Encode (builder, Lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
//
|
||||||
|
// BodyPartVisitor.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a visitor for a tree of MIME body parts.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This class is designed to be inherited to create more specialized classes whose
|
||||||
|
/// functionality requires traversing, examining or copying a tree of MIME body parts.
|
||||||
|
/// </remarks>
|
||||||
|
public abstract class BodyPartVisitor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches the entity to one of the more specialized visit methods in this class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Dispatches the entity to one of the more specialized visit methods in this class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="body">The MIME body part.</param>
|
||||||
|
public virtual void Visit (BodyPart body)
|
||||||
|
{
|
||||||
|
if (body != null)
|
||||||
|
body.Accept (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the abstract MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the abstract MIME body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="entity">The MIME body part.</param>
|
||||||
|
protected internal virtual void VisitBodyPart (BodyPart entity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the basic MIME body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the basic MIME body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="entity">The basic MIME body part.</param>
|
||||||
|
protected internal virtual void VisitBodyPartBasic (BodyPartBasic entity)
|
||||||
|
{
|
||||||
|
VisitBodyPart (entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the message contained within a message/rfc822 or message/news MIME entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the message contained within a message/rfc822 or message/news MIME entity.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The body part representing the message/rfc822 message.</param>
|
||||||
|
protected virtual void VisitMessage (BodyPart message)
|
||||||
|
{
|
||||||
|
if (message != null)
|
||||||
|
message.Accept (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the message/rfc822 or message/news MIME entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the message/rfc822 or message/news MIME entity.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="entity">The message/rfc822 or message/news body part.</param>
|
||||||
|
protected internal virtual void VisitBodyPartMessage (BodyPartMessage entity)
|
||||||
|
{
|
||||||
|
VisitBodyPartBasic (entity);
|
||||||
|
VisitMessage (entity.Body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the children of a <see cref="MailKit.BodyPartMultipart"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the children of a <see cref="MailKit.BodyPartMultipart"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="multipart">The multipart.</param>
|
||||||
|
protected virtual void VisitChildren (BodyPartMultipart multipart)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < multipart.BodyParts.Count; i++)
|
||||||
|
multipart.BodyParts[i].Accept (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the abstract multipart MIME entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the abstract multipart MIME entity.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="multipart">The multipart body part.</param>
|
||||||
|
protected internal virtual void VisitBodyPartMultipart (BodyPartMultipart multipart)
|
||||||
|
{
|
||||||
|
VisitBodyPart (multipart);
|
||||||
|
VisitChildren (multipart);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Visit the text-based MIME part entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Visits the text-based MIME part entity.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="entity">The text-based body part.</param>
|
||||||
|
protected internal virtual void VisitBodyPartText (BodyPartText entity)
|
||||||
|
{
|
||||||
|
VisitBodyPartBasic (entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
//
|
||||||
|
// CommandException.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
#if SERIALIZABLE
|
||||||
|
using System.Security;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// The exception that is thrown when there is a command error.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A <see cref="CommandException"/> can be thrown by any of the various client
|
||||||
|
/// methods in MailKit. Unlike a <see cref="ProtocolException"/>, a
|
||||||
|
/// <see cref="CommandException"/> is typically non-fatal (meaning that it does
|
||||||
|
/// not force the client to disconnect).
|
||||||
|
/// </remarks>
|
||||||
|
#if SERIALIZABLE
|
||||||
|
[Serializable]
|
||||||
|
#endif
|
||||||
|
public abstract class CommandException : Exception
|
||||||
|
{
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.CommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="CommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
[SecuritySafeCritical]
|
||||||
|
protected CommandException (SerializationInfo info, StreamingContext context) : base (info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.CommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="CommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="innerException">An inner exception.</param>
|
||||||
|
protected CommandException (string message, Exception innerException) : base (message, innerException)
|
||||||
|
{
|
||||||
|
HelpLink = "https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.CommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="CommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
protected CommandException (string message) : base (message)
|
||||||
|
{
|
||||||
|
HelpLink = "https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.CommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="CommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
protected CommandException ()
|
||||||
|
{
|
||||||
|
HelpLink = "https://github.com/jstedfast/MailKit/blob/master/FAQ.md#ProtocolLog";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,435 @@
|
||||||
|
//
|
||||||
|
// CompressedStream.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Org.BouncyCastle.Utilities.Zlib;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A compressed stream.
|
||||||
|
/// </summary>
|
||||||
|
class CompressedStream : Stream
|
||||||
|
{
|
||||||
|
readonly ZStream zIn, zOut;
|
||||||
|
bool eos, disposed;
|
||||||
|
|
||||||
|
public CompressedStream (Stream innerStream)
|
||||||
|
{
|
||||||
|
InnerStream = innerStream;
|
||||||
|
|
||||||
|
zOut = new ZStream ();
|
||||||
|
zOut.deflateInit (5, true);
|
||||||
|
zOut.next_out = new byte[4096];
|
||||||
|
|
||||||
|
zIn = new ZStream ();
|
||||||
|
zIn.inflateInit (true);
|
||||||
|
zIn.next_in = new byte[4096];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the inner stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The inner stream.</value>
|
||||||
|
public Stream InnerStream {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports reading.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports reading; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanRead {
|
||||||
|
get { return InnerStream.CanRead; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports writing.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports writing; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanWrite {
|
||||||
|
get { return InnerStream.CanWrite; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports seeking.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports seeking; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanSeek {
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports I/O timeouts.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports I/O timeouts; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanTimeout {
|
||||||
|
get { return InnerStream.CanTimeout; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value, in miliseconds, that determines how long the stream will attempt to read before timing out.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A value, in miliseconds, that determines how long the stream will attempt to read before timing out.</returns>
|
||||||
|
/// <value>The read timeout.</value>
|
||||||
|
public override int ReadTimeout {
|
||||||
|
get { return InnerStream.ReadTimeout; }
|
||||||
|
set { InnerStream.ReadTimeout = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value, in miliseconds, that determines how long the stream will attempt to write before timing out.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A value, in miliseconds, that determines how long the stream will attempt to write before timing out.</returns>
|
||||||
|
/// <value>The write timeout.</value>
|
||||||
|
public override int WriteTimeout {
|
||||||
|
get { return InnerStream.WriteTimeout; }
|
||||||
|
set { InnerStream.WriteTimeout = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the position within the current stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current position within the stream.</returns>
|
||||||
|
/// <value>The position of the stream.</value>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support seeking.
|
||||||
|
/// </exception>
|
||||||
|
public override long Position {
|
||||||
|
get { throw new NotSupportedException (); }
|
||||||
|
set { throw new NotSupportedException (); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length in bytes of the stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A long value representing the length of the stream in bytes.</returns>
|
||||||
|
/// <value>The length of the stream.</value>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support seeking.
|
||||||
|
/// </exception>
|
||||||
|
public override long Length {
|
||||||
|
get { throw new NotSupportedException (); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ValidateArguments (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (buffer == null)
|
||||||
|
throw new ArgumentNullException (nameof (buffer));
|
||||||
|
|
||||||
|
if (offset < 0 || offset > buffer.Length)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (offset));
|
||||||
|
|
||||||
|
if (count < 0 || count > (buffer.Length - offset))
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (count));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckDisposed ()
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
throw new ObjectDisposedException (nameof (CompressedStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<int> ReadAsync (byte[] buffer, int offset, int count, bool doAsync, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
ValidateArguments (buffer, offset, count);
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
zIn.next_out = buffer;
|
||||||
|
zIn.next_out_index = offset;
|
||||||
|
zIn.avail_out = count;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (zIn.avail_in == 0 && !eos) {
|
||||||
|
cancellationToken.ThrowIfCancellationRequested ();
|
||||||
|
|
||||||
|
if (doAsync)
|
||||||
|
zIn.avail_in = await InnerStream.ReadAsync (zIn.next_in, 0, zIn.next_in.Length, cancellationToken).ConfigureAwait (false);
|
||||||
|
else
|
||||||
|
zIn.avail_in = InnerStream.Read (zIn.next_in, 0, zIn.next_in.Length);
|
||||||
|
|
||||||
|
eos = zIn.avail_in == 0;
|
||||||
|
zIn.next_in_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int retval = zIn.inflate (JZlib.Z_FULL_FLUSH);
|
||||||
|
|
||||||
|
if (retval == JZlib.Z_STREAM_END)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (eos && retval == JZlib.Z_BUF_ERROR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (retval != JZlib.Z_OK)
|
||||||
|
throw new IOException ("Error inflating: " + zIn.msg);
|
||||||
|
} while (zIn.avail_out == count);
|
||||||
|
|
||||||
|
return count - zIn.avail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a sequence of bytes from the stream and advances the position
|
||||||
|
/// within the stream by the number of bytes read.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many
|
||||||
|
/// bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns>
|
||||||
|
/// <param name="buffer">The buffer.</param>
|
||||||
|
/// <param name="offset">The buffer offset.</param>
|
||||||
|
/// <param name="count">The number of bytes to read.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override int Read (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return ReadAsync (buffer, offset, count, false, CancellationToken.None).GetAwaiter ().GetResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a sequence of bytes from the stream and advances the position
|
||||||
|
/// within the stream by the number of bytes read.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many
|
||||||
|
/// bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns>
|
||||||
|
/// <param name="buffer">The buffer.</param>
|
||||||
|
/// <param name="offset">The buffer offset.</param>
|
||||||
|
/// <param name="count">The number of bytes to read.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return ReadAsync (buffer, offset, count, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task WriteAsync (byte[] buffer, int offset, int count, bool doAsync, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
ValidateArguments (buffer, offset, count);
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zOut.next_in = buffer;
|
||||||
|
zOut.next_in_index = offset;
|
||||||
|
zOut.avail_in = count;
|
||||||
|
|
||||||
|
do {
|
||||||
|
cancellationToken.ThrowIfCancellationRequested ();
|
||||||
|
|
||||||
|
zOut.avail_out = zOut.next_out.Length;
|
||||||
|
zOut.next_out_index = 0;
|
||||||
|
|
||||||
|
if (zOut.deflate (JZlib.Z_FULL_FLUSH) != JZlib.Z_OK)
|
||||||
|
throw new IOException ("Error deflating: " + zOut.msg);
|
||||||
|
|
||||||
|
if (doAsync)
|
||||||
|
await InnerStream.WriteAsync (zOut.next_out, 0, zOut.next_out.Length - zOut.avail_out, cancellationToken).ConfigureAwait (false);
|
||||||
|
else
|
||||||
|
InnerStream.Write (zOut.next_out, 0, zOut.next_out.Length - zOut.avail_out);
|
||||||
|
} while (zOut.avail_in > 0 || zOut.avail_out == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a sequence of bytes to the stream and advances the current
|
||||||
|
/// position within this stream by the number of bytes written.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to write.</param>
|
||||||
|
/// <param name="offset">The offset of the first byte to write.</param>
|
||||||
|
/// <param name="count">The number of bytes to write.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override void Write (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
WriteAsync (buffer, offset, count, false, CancellationToken.None).GetAwaiter ().GetResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a sequence of bytes to the stream and advances the current
|
||||||
|
/// position within this stream by the number of bytes written.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task that represents the asynchronous write operation.</returns>
|
||||||
|
/// <param name="buffer">The buffer to write.</param>
|
||||||
|
/// <param name="offset">The offset of the first byte to write.</param>
|
||||||
|
/// <param name="count">The number of bytes to write.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return WriteAsync (buffer, offset, count, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all output buffers for this stream and causes any buffered data to be written
|
||||||
|
/// to the underlying device.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override void Flush ()
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
InnerStream.Flush ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all output buffers for this stream and causes any buffered data to be written
|
||||||
|
/// to the underlying device.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task that represents the asynchronous flush operation.</returns>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task FlushAsync (CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
return InnerStream.FlushAsync (cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the position within the current stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The new position within the stream.</returns>
|
||||||
|
/// <param name="offset">The offset into the stream relative to the <paramref name="origin"/>.</param>
|
||||||
|
/// <param name="origin">The origin to seek from.</param>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support seeking.
|
||||||
|
/// </exception>
|
||||||
|
public override long Seek (long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the length of the stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The desired length of the stream in bytes.</param>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support setting the length.
|
||||||
|
/// </exception>
|
||||||
|
public override void SetLength (long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources used by the <see cref="CompressedStream"/> and
|
||||||
|
/// optionally releases the managed resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
|
||||||
|
/// <c>false</c> to release only the unmanaged resources.</param>
|
||||||
|
protected override void Dispose (bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && !disposed) {
|
||||||
|
InnerStream.Dispose ();
|
||||||
|
disposed = true;
|
||||||
|
zOut.free ();
|
||||||
|
zIn.free ();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose (disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
//
|
||||||
|
// ConnectedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using MailKit.Security;
|
||||||
|
|
||||||
|
namespace MailKit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Connected event arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// When a <see cref="IMailService"/> is connected, it will emit a
|
||||||
|
/// <see cref=" IMailService.Connected"/> event.
|
||||||
|
/// </remarks>
|
||||||
|
public class ConnectedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.ConnectedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="host">The name of the host that the client connected to.</param>
|
||||||
|
/// <param name="port">The port that the client connected to on the remote host.</param>
|
||||||
|
/// <param name="options">The SSL/TLS options that were used when connecting to the remote host.</param>
|
||||||
|
public ConnectedEventArgs (string host, int port, SecureSocketOptions options)
|
||||||
|
{
|
||||||
|
Options = options;
|
||||||
|
Host = host;
|
||||||
|
Port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the remote host.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the name of the remote host.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The host name of the server.</value>
|
||||||
|
public string Host {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the port.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the port.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The port.</value>
|
||||||
|
public int Port {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the SSL/TLS options.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the SSL/TLS options.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The SSL/TLS options.</value>
|
||||||
|
public SecureSocketOptions Options {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// DeliveryStatusNotification.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Delivery status notification types.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A set of flags that may be bitwise-or'd together to specify
|
||||||
|
/// when a delivery status notification should be sent for a
|
||||||
|
/// particlar recipient.
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum DeliveryStatusNotification {
|
||||||
|
/// <summary>
|
||||||
|
/// Never send delivery status notifications.
|
||||||
|
/// </summary>
|
||||||
|
Never = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a notification on successful delivery to the recipient.
|
||||||
|
/// </summary>
|
||||||
|
Success = (1 << 0),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a notification on failure to deliver to the recipient.
|
||||||
|
/// </summary>
|
||||||
|
Failure = (1 << 1),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a notification when the delivery to the recipient has
|
||||||
|
/// been delayed for an unusual amount of time.
|
||||||
|
/// </summary>
|
||||||
|
Delay = (1 << 2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// DeliveryStatusNotificationReturnType.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2019 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit.Net.Smtp
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Delivery status notification type.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The delivery status notification type specifies whether or not
|
||||||
|
/// the full message should be included in any failed DSN issued for
|
||||||
|
/// a message transmission as opposed to just the headers.
|
||||||
|
/// </remarks>
|
||||||
|
public enum DeliveryStatusNotificationType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The return type is unspecified, allowing the server to choose.
|
||||||
|
/// </summary>
|
||||||
|
Unspecified,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The full message should be included in any failed delivery status notification issued by the server.
|
||||||
|
/// </summary>
|
||||||
|
Full,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only the headers should be included in any failed delivery status notification issued by the server.
|
||||||
|
/// </summary>
|
||||||
|
HeadersOnly,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// DisconnectedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using MailKit.Security;
|
||||||
|
|
||||||
|
namespace MailKit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnected event arguments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// When a <see cref="IMailService"/> gets disconnected, it will emit a
|
||||||
|
/// <see cref=" IMailService.Disconnected"/> event.
|
||||||
|
/// </remarks>
|
||||||
|
public class DisconnectedEventArgs : ConnectedEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.DisconnectedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.DisconnectedEventArgs"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="host">The name of the host that the client was connected to.</param>
|
||||||
|
/// <param name="port">The port that the client was connected to.</param>
|
||||||
|
/// <param name="options">The SSL/TLS options that were used by the client.</param>
|
||||||
|
/// <param name="requested">If <c>true</c>, the <see cref="IMailService"/> was disconnected via the
|
||||||
|
/// <see cref="IMailService.Disconnect(bool, System.Threading.CancellationToken)"/> method.</param>
|
||||||
|
public DisconnectedEventArgs (string host, int port, SecureSocketOptions options, bool requested) : base (host, port, options)
|
||||||
|
{
|
||||||
|
IsRequested = requested;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not the service was explicitly asked to disconnect.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the <see cref="IMailService"/> was disconnected via the
|
||||||
|
/// <see cref="IMailService.Disconnect(bool, System.Threading.CancellationToken)"/> method, then
|
||||||
|
/// the value of <see cref="IsRequested"/> will be <c>true</c>. If the connection was unexpectedly
|
||||||
|
/// dropped, then the value will be <c>false</c>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the disconnect was explicitly requested; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsRequested {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,395 @@
|
||||||
|
//
|
||||||
|
// DuplexStream.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A duplex stream.
|
||||||
|
/// </summary>
|
||||||
|
class DuplexStream : Stream
|
||||||
|
{
|
||||||
|
bool disposed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.DuplexStream"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="istream">The stream to use for input.</param>
|
||||||
|
/// <param name="ostream">The stream to use for output.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="istream"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="ostream"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public DuplexStream (Stream istream, Stream ostream)
|
||||||
|
{
|
||||||
|
if (istream == null)
|
||||||
|
throw new ArgumentNullException (nameof (istream));
|
||||||
|
|
||||||
|
if (ostream == null)
|
||||||
|
throw new ArgumentNullException (nameof (ostream));
|
||||||
|
|
||||||
|
InputStream = istream;
|
||||||
|
OutputStream = ostream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the input stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The input stream.</value>
|
||||||
|
public Stream InputStream {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the output stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The output stream.</value>
|
||||||
|
public Stream OutputStream {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports reading.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports reading; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanRead {
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports writing.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports writing; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanWrite {
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports seeking.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports seeking; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanSeek {
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the stream supports I/O timeouts.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if the stream supports I/O timeouts; otherwise, <c>false</c>.</value>
|
||||||
|
public override bool CanTimeout {
|
||||||
|
get { return InputStream.CanTimeout && OutputStream.CanTimeout; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value, in miliseconds, that determines how long the stream will attempt to read before timing out.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A value, in miliseconds, that determines how long the stream will attempt to read before timing out.</returns>
|
||||||
|
/// <value>The read timeout.</value>
|
||||||
|
public override int ReadTimeout {
|
||||||
|
get { return InputStream.ReadTimeout; }
|
||||||
|
set { InputStream.ReadTimeout = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value, in miliseconds, that determines how long the stream will attempt to write before timing out.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A value, in miliseconds, that determines how long the stream will attempt to write before timing out.</returns>
|
||||||
|
/// <value>The write timeout.</value>
|
||||||
|
public override int WriteTimeout {
|
||||||
|
get { return OutputStream.WriteTimeout; }
|
||||||
|
set { OutputStream.WriteTimeout = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the position within the current stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current position within the stream.</returns>
|
||||||
|
/// <value>The position of the stream.</value>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support seeking.
|
||||||
|
/// </exception>
|
||||||
|
public override long Position {
|
||||||
|
get { throw new NotSupportedException (); }
|
||||||
|
set { throw new NotSupportedException (); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length in bytes of the stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A long value representing the length of the stream in bytes.</returns>
|
||||||
|
/// <value>The length of the stream.</value>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support seeking.
|
||||||
|
/// </exception>
|
||||||
|
public override long Length {
|
||||||
|
get { throw new NotSupportedException (); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ValidateArguments (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
if (buffer == null)
|
||||||
|
throw new ArgumentNullException (nameof (buffer));
|
||||||
|
|
||||||
|
if (offset < 0 || offset > buffer.Length)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (offset));
|
||||||
|
|
||||||
|
if (count < 0 || count > (buffer.Length - offset))
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (count));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckDisposed ()
|
||||||
|
{
|
||||||
|
if (disposed)
|
||||||
|
throw new ObjectDisposedException (nameof (DuplexStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a sequence of bytes from the stream and advances the position
|
||||||
|
/// within the stream by the number of bytes read.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many
|
||||||
|
/// bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns>
|
||||||
|
/// <param name="buffer">The buffer.</param>
|
||||||
|
/// <param name="offset">The buffer offset.</param>
|
||||||
|
/// <param name="count">The number of bytes to read.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override int Read (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
ValidateArguments (buffer, offset, count);
|
||||||
|
|
||||||
|
return InputStream.Read (buffer, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a sequence of bytes from the stream and advances the position
|
||||||
|
/// within the stream by the number of bytes read.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many
|
||||||
|
/// bytes are not currently available, or zero (0) if the end of the stream has been reached.</returns>
|
||||||
|
/// <param name="buffer">The buffer.</param>
|
||||||
|
/// <param name="offset">The buffer offset.</param>
|
||||||
|
/// <param name="count">The number of bytes to read.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
ValidateArguments (buffer, offset, count);
|
||||||
|
|
||||||
|
return InputStream.ReadAsync (buffer, offset, count, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a sequence of bytes to the stream and advances the current
|
||||||
|
/// position within this stream by the number of bytes written.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">The buffer to write.</param>
|
||||||
|
/// <param name="offset">The offset of the first byte to write.</param>
|
||||||
|
/// <param name="count">The number of bytes to write.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override void Write (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
ValidateArguments (buffer, offset, count);
|
||||||
|
|
||||||
|
OutputStream.Write (buffer, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes a sequence of bytes to the stream and advances the current
|
||||||
|
/// position within this stream by the number of bytes written.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task that represents the asynchronous write operation.</returns>
|
||||||
|
/// <param name="buffer">The buffer to write.</param>
|
||||||
|
/// <param name="offset">The offset of the first byte to write.</param>
|
||||||
|
/// <param name="count">The number of bytes to write.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
ValidateArguments (buffer, offset, count);
|
||||||
|
|
||||||
|
return OutputStream.WriteAsync (buffer, offset, count, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all output buffers for this stream and causes any buffered data to be written
|
||||||
|
/// to the underlying device.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override void Flush ()
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
OutputStream.Flush ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all output buffers for this stream and causes any buffered data to be written
|
||||||
|
/// to the underlying device.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A task that represents the asynchronous flush operation.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The stream has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support writing.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task FlushAsync (CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CheckDisposed ();
|
||||||
|
|
||||||
|
return OutputStream.FlushAsync (cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the position within the current stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The new position within the stream.</returns>
|
||||||
|
/// <param name="offset">The offset into the stream relative to the <paramref name="origin"/>.</param>
|
||||||
|
/// <param name="origin">The origin to seek from.</param>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support seeking.
|
||||||
|
/// </exception>
|
||||||
|
public override long Seek (long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the length of the stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The desired length of the stream in bytes.</param>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The stream does not support setting the length.
|
||||||
|
/// </exception>
|
||||||
|
public override void SetLength (long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources used by the <see cref="DuplexStream"/> and
|
||||||
|
/// optionally releases the managed resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
|
||||||
|
/// <c>false</c> to release only the unmanaged resources.</param>
|
||||||
|
protected override void Dispose (bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && !disposed) {
|
||||||
|
OutputStream.Dispose ();
|
||||||
|
InputStream.Dispose ();
|
||||||
|
disposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose (disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,592 @@
|
||||||
|
//
|
||||||
|
// Envelope.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A message envelope containing a brief summary of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The envelope of a message contains information such as the
|
||||||
|
/// date the message was sent, the subject of the message,
|
||||||
|
/// the sender of the message, who the message was sent to,
|
||||||
|
/// which message(s) the message may be in reply to,
|
||||||
|
/// and the message id.
|
||||||
|
/// </remarks>
|
||||||
|
public class Envelope
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Envelope"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="Envelope"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public Envelope ()
|
||||||
|
{
|
||||||
|
From = new InternetAddressList ();
|
||||||
|
Sender = new InternetAddressList ();
|
||||||
|
ReplyTo = new InternetAddressList ();
|
||||||
|
To = new InternetAddressList ();
|
||||||
|
Cc = new InternetAddressList ();
|
||||||
|
Bcc = new InternetAddressList ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the address(es) that the message is from.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the address(es) that the message is from.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The address(es) that the message is from.</value>
|
||||||
|
public InternetAddressList From {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the actual sender(s) of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The senders may differ from the addresses in <see cref="From"/> if
|
||||||
|
/// the message was sent by someone on behalf of someone else.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The actual sender(s) of the message.</value>
|
||||||
|
public InternetAddressList Sender {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the address(es) that replies should be sent to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The senders of the message may prefer that replies are sent
|
||||||
|
/// somewhere other than the address they used to send the message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The address(es) that replies should be sent to.</value>
|
||||||
|
public InternetAddressList ReplyTo {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of addresses that the message was sent to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the list of addresses that the message was sent to.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The address(es) that the message was sent to.</value>
|
||||||
|
public InternetAddressList To {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of addresses that the message was carbon-copied to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the list of addresses that the message was carbon-copied to.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The address(es) that the message was carbon-copied to.</value>
|
||||||
|
public InternetAddressList Cc {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of addresses that the message was blind-carbon-copied to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the list of addresses that the message was blind-carbon-copied to.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The address(es) that the message was carbon-copied to.</value>
|
||||||
|
public InternetAddressList Bcc {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Message-Id that the message is replying to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The Message-Id that the message is replying to.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The Message-Id that the message is replying to.</value>
|
||||||
|
public string InReplyTo {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the date that the message was sent on, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the date that the message was sent on, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The date the message was sent.</value>
|
||||||
|
public DateTimeOffset? Date {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ID of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the ID of the message, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message identifier.</value>
|
||||||
|
public string MessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the subject of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the subject of the message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The subject.</value>
|
||||||
|
public string Subject {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EncodeMailbox (StringBuilder builder, MailboxAddress mailbox)
|
||||||
|
{
|
||||||
|
builder.Append ('(');
|
||||||
|
|
||||||
|
if (mailbox.Name != null)
|
||||||
|
builder.AppendFormat ("{0} ", MimeUtils.Quote (mailbox.Name));
|
||||||
|
else
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
|
||||||
|
if (mailbox.Route.Count != 0)
|
||||||
|
builder.AppendFormat ("\"{0}\" ", mailbox.Route);
|
||||||
|
else
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
|
||||||
|
int at = mailbox.Address.LastIndexOf ('@');
|
||||||
|
|
||||||
|
if (at >= 0) {
|
||||||
|
var domain = mailbox.Address.Substring (at + 1);
|
||||||
|
var user = mailbox.Address.Substring (0, at);
|
||||||
|
|
||||||
|
builder.AppendFormat ("{0} {1}", MimeUtils.Quote (user), MimeUtils.Quote (domain));
|
||||||
|
} else {
|
||||||
|
builder.AppendFormat ("{0} \"localhost\"", MimeUtils.Quote (mailbox.Address));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EncodeInternetAddressListAddresses (StringBuilder builder, InternetAddressList addresses)
|
||||||
|
{
|
||||||
|
foreach (var addr in addresses) {
|
||||||
|
var mailbox = addr as MailboxAddress;
|
||||||
|
var group = addr as GroupAddress;
|
||||||
|
|
||||||
|
if (mailbox != null)
|
||||||
|
EncodeMailbox (builder, mailbox);
|
||||||
|
else if (group != null)
|
||||||
|
EncodeGroup (builder, group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EncodeGroup (StringBuilder builder, GroupAddress group)
|
||||||
|
{
|
||||||
|
builder.AppendFormat ("(NIL NIL {0} NIL)", MimeUtils.Quote (group.Name));
|
||||||
|
EncodeInternetAddressListAddresses (builder, group.Members);
|
||||||
|
builder.Append ("(NIL NIL NIL NIL)");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EncodeAddressList (StringBuilder builder, InternetAddressList list)
|
||||||
|
{
|
||||||
|
builder.Append ('(');
|
||||||
|
EncodeInternetAddressListAddresses (builder, list);
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Encode (StringBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Append ('(');
|
||||||
|
|
||||||
|
if (Date.HasValue)
|
||||||
|
builder.AppendFormat ("\"{0}\" ", DateUtils.FormatDate (Date.Value));
|
||||||
|
else
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
|
||||||
|
if (Subject != null)
|
||||||
|
builder.AppendFormat ("{0} ", MimeUtils.Quote (Subject));
|
||||||
|
else
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
|
||||||
|
if (From.Count > 0) {
|
||||||
|
EncodeAddressList (builder, From);
|
||||||
|
builder.Append (' ');
|
||||||
|
} else {
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Sender.Count > 0) {
|
||||||
|
EncodeAddressList (builder, Sender);
|
||||||
|
builder.Append (' ');
|
||||||
|
} else {
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReplyTo.Count > 0) {
|
||||||
|
EncodeAddressList (builder, ReplyTo);
|
||||||
|
builder.Append (' ');
|
||||||
|
} else {
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (To.Count > 0) {
|
||||||
|
EncodeAddressList (builder, To);
|
||||||
|
builder.Append (' ');
|
||||||
|
} else {
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cc.Count > 0) {
|
||||||
|
EncodeAddressList (builder, Cc);
|
||||||
|
builder.Append (' ');
|
||||||
|
} else {
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bcc.Count > 0) {
|
||||||
|
EncodeAddressList (builder, Bcc);
|
||||||
|
builder.Append (' ');
|
||||||
|
} else {
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InReplyTo != null) {
|
||||||
|
if (InReplyTo.Length > 1 && InReplyTo[0] != '<' && InReplyTo[InReplyTo.Length - 1] != '>')
|
||||||
|
builder.AppendFormat ("{0} ", MimeUtils.Quote ('<' + InReplyTo + '>'));
|
||||||
|
else
|
||||||
|
builder.AppendFormat ("{0} ", MimeUtils.Quote (InReplyTo));
|
||||||
|
} else
|
||||||
|
builder.Append ("NIL ");
|
||||||
|
|
||||||
|
if (MessageId != null) {
|
||||||
|
if (MessageId.Length > 1 && MessageId[0] != '<' && MessageId[MessageId.Length - 1] != '>')
|
||||||
|
builder.AppendFormat ("{0}", MimeUtils.Quote ('<' + MessageId + '>'));
|
||||||
|
else
|
||||||
|
builder.AppendFormat ("{0}", MimeUtils.Quote (MessageId));
|
||||||
|
} else
|
||||||
|
builder.Append ("NIL");
|
||||||
|
|
||||||
|
builder.Append (')');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.Envelope"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The returned string can be parsed by <see cref="TryParse(string,out Envelope)"/>.</para>
|
||||||
|
/// <note type="warning">The syntax of the string returned, while similar to IMAP's ENVELOPE syntax,
|
||||||
|
/// is not completely compatible.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.Envelope"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder ();
|
||||||
|
|
||||||
|
Encode (builder);
|
||||||
|
|
||||||
|
return builder.ToString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out string nstring)
|
||||||
|
{
|
||||||
|
nstring = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] != '"') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = new StringBuilder ();
|
||||||
|
bool escaped = false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
while (index < text.Length) {
|
||||||
|
if (text[index] == '"' && !escaped)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (escaped || text[index] != '\\') {
|
||||||
|
token.Append (text[index]);
|
||||||
|
escaped = false;
|
||||||
|
} else {
|
||||||
|
escaped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nstring = token.ToString ();
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out InternetAddress addr)
|
||||||
|
{
|
||||||
|
string name, route, user, domain;
|
||||||
|
DomainList domains;
|
||||||
|
|
||||||
|
addr = null;
|
||||||
|
|
||||||
|
if (text[index] != '(')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out route))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out user))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out domain))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != ')')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (domain != null) {
|
||||||
|
var address = user + "@" + domain;
|
||||||
|
|
||||||
|
if (route != null && DomainList.TryParse (route, out domains))
|
||||||
|
addr = new MailboxAddress (name, domains, address);
|
||||||
|
else
|
||||||
|
addr = new MailboxAddress (name, address);
|
||||||
|
} else if (user != null) {
|
||||||
|
addr = new GroupAddress (user);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryParse (string text, ref int index, out InternetAddressList list)
|
||||||
|
{
|
||||||
|
list = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (text[index] != '(') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
list = new InternetAddressList ();
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
list = new InternetAddressList ();
|
||||||
|
var stack = new List<InternetAddressList> ();
|
||||||
|
int sp = 0;
|
||||||
|
|
||||||
|
stack.Add (list);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (text[index] == ')')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out InternetAddress addr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (addr != null) {
|
||||||
|
var group = addr as GroupAddress;
|
||||||
|
|
||||||
|
stack[sp].Add (addr);
|
||||||
|
|
||||||
|
if (group != null) {
|
||||||
|
stack.Add (group.Members);
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
} else if (sp > 0) {
|
||||||
|
stack.RemoveAt (sp);
|
||||||
|
sp--;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
} while (index < text.Length);
|
||||||
|
|
||||||
|
// Note: technically, we should check that sp == 0 as well, since all groups should
|
||||||
|
// be popped off the stack, but in the interest of being liberal in what we accept,
|
||||||
|
// we'll ignore that.
|
||||||
|
if (index >= text.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool TryParse (string text, ref int index, out Envelope envelope)
|
||||||
|
{
|
||||||
|
InternetAddressList from, sender, replyto, to, cc, bcc;
|
||||||
|
string inreplyto, messageid, subject, nstring;
|
||||||
|
DateTimeOffset? date = null;
|
||||||
|
|
||||||
|
envelope = null;
|
||||||
|
|
||||||
|
while (index < text.Length && text[index] == ' ')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != '(') {
|
||||||
|
if (index + 3 <= text.Length && text.Substring (index, 3) == "NIL") {
|
||||||
|
index += 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out nstring))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (nstring != null) {
|
||||||
|
DateTimeOffset value;
|
||||||
|
|
||||||
|
if (!DateUtils.TryParse (nstring, out value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
date = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out subject))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out from))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out sender))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out replyto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out to))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out cc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out bcc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out inreplyto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!TryParse (text, ref index, out messageid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (index >= text.Length || text[index] != ')')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
envelope = new Envelope {
|
||||||
|
Date = date,
|
||||||
|
Subject = subject,
|
||||||
|
From = from,
|
||||||
|
Sender = sender,
|
||||||
|
ReplyTo = replyto,
|
||||||
|
To = to,
|
||||||
|
Cc = cc,
|
||||||
|
Bcc = bcc,
|
||||||
|
InReplyTo = inreplyto != null ? MimeUtils.EnumerateReferences (inreplyto).FirstOrDefault () ?? inreplyto : null,
|
||||||
|
MessageId = messageid != null ? MimeUtils.EnumerateReferences (messageid).FirstOrDefault () ?? messageid : null
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to parse the given text into a new <see cref="MailKit.Envelope"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Parses an Envelope value from the specified text.</para>
|
||||||
|
/// <note type="warning">This syntax, while similar to IMAP's ENVELOPE syntax, is not
|
||||||
|
/// completely compatible.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><c>true</c>, if the envelope was successfully parsed, <c>false</c> otherwise.</returns>
|
||||||
|
/// <param name="text">The text to parse.</param>
|
||||||
|
/// <param name="envelope">The parsed envelope.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="text"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool TryParse (string text, out Envelope envelope)
|
||||||
|
{
|
||||||
|
if (text == null)
|
||||||
|
throw new ArgumentNullException (nameof (text));
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
return TryParse (text, ref index, out envelope) && index == text.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// FolderMode.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A folder access mode.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A folder access mode.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadMessages"/>
|
||||||
|
/// </example>
|
||||||
|
public enum FolderAccess {
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is not open.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is read-only.
|
||||||
|
/// </summary>
|
||||||
|
ReadOnly,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is read/write.
|
||||||
|
/// </summary>
|
||||||
|
ReadWrite
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
//
|
||||||
|
// FolderAttributes.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Folder attributes as used by <see cref="IMailFolder.Attributes"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Folder attributes as used by <see cref="IMailFolder.Attributes"/>.
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum FolderAttributes {
|
||||||
|
/// <summary>
|
||||||
|
/// The folder does not have any attributes.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// It is not possible for any subfolders to exist under the folder.
|
||||||
|
/// </summary>
|
||||||
|
NoInferiors = (1 << 0),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// It is not possible to select the folder.
|
||||||
|
/// </summary>
|
||||||
|
NoSelect = (1 << 1),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder has been marked as possibly containing new messages
|
||||||
|
/// since the folder was last selected.
|
||||||
|
/// </summary>
|
||||||
|
Marked = (1 << 2),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder does not contain any new messages since the folder
|
||||||
|
/// was last selected.
|
||||||
|
/// </summary>
|
||||||
|
Unmarked = (1 << 3),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder does not exist, but is simply a place-holder.
|
||||||
|
/// </summary>
|
||||||
|
NonExistent = (1 << 4),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is subscribed.
|
||||||
|
/// </summary>
|
||||||
|
Subscribed = (1 << 5),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is remote.
|
||||||
|
/// </summary>
|
||||||
|
Remote = (1 << 6),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder has subfolders.
|
||||||
|
/// </summary>
|
||||||
|
HasChildren = (1 << 7),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder does not have any subfolders.
|
||||||
|
/// </summary>
|
||||||
|
HasNoChildren = (1 << 8),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is a special "All" folder containing an aggregate of all messages.
|
||||||
|
/// </summary>
|
||||||
|
All = (1 << 9),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is a special "Archive" folder.
|
||||||
|
/// </summary>
|
||||||
|
Archive = (1 << 10),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Drafts" folder.
|
||||||
|
/// </summary>
|
||||||
|
Drafts = (1 << 11),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Flagged" folder.
|
||||||
|
/// </summary>
|
||||||
|
Flagged = (1 << 12),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Important" folder.
|
||||||
|
/// </summary>
|
||||||
|
Important = (1 << 13),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Inbox" folder.
|
||||||
|
/// </summary>
|
||||||
|
Inbox = (1 << 14),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Junk" folder.
|
||||||
|
/// </summary>
|
||||||
|
Junk = (1 << 15),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Sent" folder.
|
||||||
|
/// </summary>
|
||||||
|
Sent = (1 << 16),
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The folder is the special "Trash" folder.
|
||||||
|
/// </summary>
|
||||||
|
Trash = (1 << 17),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// FolderCreatedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when a <see cref="IMailFolder"/> is created.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when a <see cref="IMailFolder"/> is created.
|
||||||
|
/// </remarks>
|
||||||
|
public class FolderCreatedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.FolderCreatedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderCreatedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folder">The newly created folder.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folder"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderCreatedEventArgs (IMailFolder folder)
|
||||||
|
{
|
||||||
|
if (folder == null)
|
||||||
|
throw new ArgumentNullException (nameof (folder));
|
||||||
|
|
||||||
|
Folder = folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder that was just created.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder that was just created.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The folder.</value>
|
||||||
|
public IMailFolder Folder {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
//
|
||||||
|
// FolderFeature.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An optional feature that an <see cref="IMailFolder"/> may support.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An optional feature that an <see cref="IMailFolder"/> may support.
|
||||||
|
/// </remarks>
|
||||||
|
public enum FolderFeature
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder supports access rights.
|
||||||
|
/// </summary>
|
||||||
|
AccessRights,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder allows arbitrary annotations to be set on a message.
|
||||||
|
/// </summary>
|
||||||
|
Annotations,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder allows arbitrary metadata to be set.
|
||||||
|
/// </summary>
|
||||||
|
Metadata,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder uses modification sequences for every state change of a message.
|
||||||
|
/// </summary>
|
||||||
|
ModSequences,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder supports quick resynchronization when opening.
|
||||||
|
/// </summary>
|
||||||
|
QuickResync,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder supports quotas.
|
||||||
|
/// </summary>
|
||||||
|
Quotas,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder supports sorting messages.
|
||||||
|
/// </summary>
|
||||||
|
Sorting,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder supports threading messages.
|
||||||
|
/// </summary>
|
||||||
|
Threading,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the folder supports the use of UTF-8.
|
||||||
|
/// </summary>
|
||||||
|
UTF8,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// FolderNamespace.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A folder namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A folder namespace.
|
||||||
|
/// </remarks>
|
||||||
|
public class FolderNamespace
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The directory separator for this folder namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The directory separator for this folder namespace.
|
||||||
|
/// </remarks>
|
||||||
|
public readonly char DirectorySeparator;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The base path for this folder namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The base path for this folder namespace.
|
||||||
|
/// </remarks>
|
||||||
|
public readonly string Path;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.FolderNamespace"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new folder namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="directorySeparator">The directory separator.</param>
|
||||||
|
/// <param name="path">The folder path.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNamespace (char directorySeparator, string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException (nameof (path));
|
||||||
|
|
||||||
|
DirectorySeparator = directorySeparator;
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
//
|
||||||
|
// FolderNamespaceCollection.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A read-only collection of folder namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A read-only collection of folder namespaces.
|
||||||
|
/// </remarks>
|
||||||
|
public class FolderNamespaceCollection : IEnumerable<FolderNamespace>
|
||||||
|
{
|
||||||
|
readonly List<FolderNamespace> namespaces;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNamespaceCollection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNamespaceCollection"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public FolderNamespaceCollection ()
|
||||||
|
{
|
||||||
|
namespaces = new List<FolderNamespace> ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ICollection implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of folder namespaces contained in the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the number of folder namespaces contained in the collection.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The count.</value>
|
||||||
|
public int Count {
|
||||||
|
get { return namespaces.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Adds the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="namespace">The namespace to add.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public void Add (FolderNamespace @namespace)
|
||||||
|
{
|
||||||
|
if (@namespace == null)
|
||||||
|
throw new ArgumentNullException (nameof (@namespace));
|
||||||
|
|
||||||
|
namespaces.Add (@namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all namespaces from the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Removes all namespaces from the collection.
|
||||||
|
/// </remarks>
|
||||||
|
public void Clear ()
|
||||||
|
{
|
||||||
|
namespaces.Clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the collection contains the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Checks if the collection contains the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><value>true</value> if the specified namespace exists;
|
||||||
|
/// otherwise <value>false</value>.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public bool Contains (FolderNamespace @namespace)
|
||||||
|
{
|
||||||
|
if (@namespace == null)
|
||||||
|
throw new ArgumentNullException (nameof (@namespace));
|
||||||
|
|
||||||
|
return namespaces.Contains (@namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the first occurance of the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Removes the first occurance of the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns><value>true</value> if the frst occurance of the specified
|
||||||
|
/// namespace was removed; otherwise <value>false</value>.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public bool Remove (FolderNamespace @namespace)
|
||||||
|
{
|
||||||
|
if (@namespace == null)
|
||||||
|
throw new ArgumentNullException (nameof (@namespace));
|
||||||
|
|
||||||
|
return namespaces.Remove (@namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="MailKit.FolderNamespace"/> at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the <see cref="MailKit.FolderNamespace"/> at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The folder namespace at the specified index.</value>
|
||||||
|
/// <param name="index">The index.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="value"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNamespace this [int index] {
|
||||||
|
get {
|
||||||
|
if (index < 0 || index >= namespaces.Count)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
return namespaces[index];
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if (index < 0 || index >= namespaces.Count)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException (nameof (value));
|
||||||
|
|
||||||
|
namespaces[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the enumerator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The enumerator.</returns>
|
||||||
|
public IEnumerator<FolderNamespace> GetEnumerator ()
|
||||||
|
{
|
||||||
|
return namespaces.GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the enumerator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the enumerator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The enumerator.</returns>
|
||||||
|
IEnumerator IEnumerable.GetEnumerator ()
|
||||||
|
{
|
||||||
|
return namespaces.GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
static bool Escape (char directorySeparator)
|
||||||
|
{
|
||||||
|
return directorySeparator == '\\' || directorySeparator == '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:MailKit.FolderNamespaceCollection"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:MailKit.FolderNamespaceCollection"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="T:System.String"/> that represents the current <see cref="T:MailKit.FolderNamespaceCollection"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder ();
|
||||||
|
|
||||||
|
builder.Append ('(');
|
||||||
|
for (int i = 0; i < namespaces.Count; i++) {
|
||||||
|
builder.Append ("(\"");
|
||||||
|
if (Escape (namespaces[i].DirectorySeparator))
|
||||||
|
builder.Append ('\\');
|
||||||
|
builder.Append (namespaces[i].DirectorySeparator);
|
||||||
|
builder.Append ("\" ");
|
||||||
|
builder.Append (MimeUtils.Quote (namespaces[i].Path));
|
||||||
|
builder.Append (")");
|
||||||
|
}
|
||||||
|
builder.Append (')');
|
||||||
|
|
||||||
|
return builder.ToString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
//
|
||||||
|
// FolderNotFoundException.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
#if SERIALIZABLE
|
||||||
|
using System.Security;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// The exception that is thrown when a folder could not be found.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This exception is thrown by <see cref="IMailFolder.GetSubfolder(string,System.Threading.CancellationToken)"/>.
|
||||||
|
/// </remarks>
|
||||||
|
#if SERIALIZABLE
|
||||||
|
[Serializable]
|
||||||
|
#endif
|
||||||
|
public class FolderNotFoundException : Exception
|
||||||
|
{
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Deserializes a <see cref="FolderNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
protected FolderNotFoundException (SerializationInfo info, StreamingContext context) : base (info, context)
|
||||||
|
{
|
||||||
|
FolderName = info.GetString ("FolderName");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="folderName">The name of the folder.</param>
|
||||||
|
/// <param name="innerException">The inner exception.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folderName"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNotFoundException (string message, string folderName, Exception innerException) : base (message, innerException)
|
||||||
|
{
|
||||||
|
if (folderName == null)
|
||||||
|
throw new ArgumentNullException (nameof (folderName));
|
||||||
|
|
||||||
|
FolderName = folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="folderName">The name of the folder.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folderName"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNotFoundException (string message, string folderName) : base (message)
|
||||||
|
{
|
||||||
|
if (folderName == null)
|
||||||
|
throw new ArgumentNullException (nameof (folderName));
|
||||||
|
|
||||||
|
FolderName = folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folderName">The name of the folder.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folderName"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNotFoundException (string folderName) : this ("The requested folder could not be found.", folderName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the folder that could not be found.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the name of the folder that could not be found.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the folder.</value>
|
||||||
|
public string FolderName {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, sets the <see cref="System.Runtime.Serialization.SerializationInfo"/>
|
||||||
|
/// with information about the exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serializes the state of the <see cref="FolderNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
[SecurityCritical]
|
||||||
|
public override void GetObjectData (SerializationInfo info, StreamingContext context)
|
||||||
|
{
|
||||||
|
base.GetObjectData (info, context);
|
||||||
|
|
||||||
|
info.AddValue ("FolderName", FolderName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
//
|
||||||
|
// FolderNotOpenException.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
#if SERIALIZABLE
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// The exception that is thrown when a folder is not open.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This exception is thrown when an operation on a folder could not be completed
|
||||||
|
/// due to the folder being in a closed state. For example, the
|
||||||
|
/// <see cref="IMailFolder.GetMessage(UniqueId,System.Threading.CancellationToken, ITransferProgress)"/>
|
||||||
|
/// method will throw a <see cref="FolderNotOpenException"/> if the folder is not
|
||||||
|
/// current open.
|
||||||
|
/// </remarks>
|
||||||
|
#if SERIALIZABLE
|
||||||
|
[Serializable]
|
||||||
|
#endif
|
||||||
|
public class FolderNotOpenException : InvalidOperationException
|
||||||
|
{
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotOpenException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Deserializes a <see cref="FolderNotOpenException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
protected FolderNotOpenException (SerializationInfo info, StreamingContext context) : base (info, context)
|
||||||
|
{
|
||||||
|
var value = info.GetString ("FolderAccess");
|
||||||
|
FolderAccess access;
|
||||||
|
|
||||||
|
if (!Enum.TryParse (value, out access))
|
||||||
|
FolderAccess = FolderAccess.ReadOnly;
|
||||||
|
else
|
||||||
|
FolderAccess = access;
|
||||||
|
|
||||||
|
FolderName = info.GetString ("FolderName");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotOpenException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNotOpenException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folderName">The folder name.</param>
|
||||||
|
/// <param name="access">The minimum folder access required by the operation.</param>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="innerException">The inner exception.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folderName"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNotOpenException (string folderName, FolderAccess access, string message, Exception innerException) : base (message, innerException)
|
||||||
|
{
|
||||||
|
if (folderName == null)
|
||||||
|
throw new ArgumentNullException (nameof (folderName));
|
||||||
|
|
||||||
|
FolderName = folderName;
|
||||||
|
FolderAccess = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotOpenException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNotOpenException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folderName">The folder name.</param>
|
||||||
|
/// <param name="access">The minimum folder access required by the operation.</param>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folderName"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNotOpenException (string folderName, FolderAccess access, string message) : base (message)
|
||||||
|
{
|
||||||
|
if (folderName == null)
|
||||||
|
throw new ArgumentNullException (nameof (folderName));
|
||||||
|
|
||||||
|
FolderName = folderName;
|
||||||
|
FolderAccess = access;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderNotOpenException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderNotOpenException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folderName">The folder name.</param>
|
||||||
|
/// <param name="access">The minimum folder access required by the operation.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folderName"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public FolderNotOpenException (string folderName, FolderAccess access) : this (folderName, access, GetDefaultMessage (access))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the name of the folder.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the folder.</value>
|
||||||
|
public string FolderName {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the minimum folder access required by the operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the minimum folder access required by the operation.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The minimum required folder access.</value>
|
||||||
|
public FolderAccess FolderAccess {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetDefaultMessage (FolderAccess access)
|
||||||
|
{
|
||||||
|
if (access == FolderAccess.ReadWrite)
|
||||||
|
return "The folder is not currently open in read-write mode.";
|
||||||
|
|
||||||
|
return "The folder is not currently open.";
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, sets the <see cref="System.Runtime.Serialization.SerializationInfo"/>
|
||||||
|
/// with information about the exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serializes the state of the <see cref="FolderNotOpenException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public override void GetObjectData (SerializationInfo info, StreamingContext context)
|
||||||
|
{
|
||||||
|
base.GetObjectData (info, context);
|
||||||
|
|
||||||
|
info.AddValue ("FolderAccess", FolderAccess.ToString ());
|
||||||
|
info.AddValue ("FolderName", FolderName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
//
|
||||||
|
// FolderQuota.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A folder quota.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A <see cref="FolderQuota"/> is returned by <see cref="IMailFolder.GetQuota(System.Threading.CancellationToken)"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
public class FolderQuota
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.FolderQuota"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderQuota"/> with the specified root.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="quotaRoot">The quota root.</param>
|
||||||
|
public FolderQuota (IMailFolder quotaRoot)
|
||||||
|
{
|
||||||
|
QuotaRoot = quotaRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the quota root.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the quota root. If the quota root is <c>null</c>, then
|
||||||
|
/// it suggests that the folder does not have a quota.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The quota root.</value>
|
||||||
|
public IMailFolder QuotaRoot {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the message limit.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the message limit.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The message limit.</value>
|
||||||
|
public uint? MessageLimit {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the storage limit, in kilobytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the storage limit, in kilobytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The storage limit, in kilobytes.</value>
|
||||||
|
public uint? StorageLimit {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the current message count.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the current message count.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The current message count.</value>
|
||||||
|
public uint? CurrentMessageCount {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the size of the current storage, in kilobytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the size of the current storage, in kilobytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The size of the current storage, in kilobytes.</value>
|
||||||
|
public uint? CurrentStorageSize {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
//
|
||||||
|
// FolderRenamedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when a <see cref="IMailFolder"/> is renamed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when a <see cref="IMailFolder"/> is renamed.
|
||||||
|
/// </remarks>
|
||||||
|
public class FolderRenamedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.FolderRenamedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="FolderRenamedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="oldName">The old name of the folder.</param>
|
||||||
|
/// <param name="newName">The new name of the folder.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="oldName"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="newName"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public FolderRenamedEventArgs (string oldName, string newName)
|
||||||
|
{
|
||||||
|
if (oldName == null)
|
||||||
|
throw new ArgumentNullException (nameof (oldName));
|
||||||
|
|
||||||
|
if (newName == null)
|
||||||
|
throw new ArgumentNullException (nameof (newName));
|
||||||
|
|
||||||
|
OldName = oldName;
|
||||||
|
NewName = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The old name of the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The old name of the folder.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The old name.</value>
|
||||||
|
public string OldName {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The new name of the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The new name of the folder.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The new name.</value>
|
||||||
|
public string NewName {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,511 @@
|
||||||
|
//
|
||||||
|
// IMailSpool.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for retreiving messages from a spool.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An interface for retreiving messages from a spool.
|
||||||
|
/// </remarks>
|
||||||
|
public interface IMailSpool : IMailService, IEnumerable<MimeMessage>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the number of messages available in the message spool.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the number of messages available in the message spool.</para>
|
||||||
|
/// <para>Once authenticated, the <see cref="Count"/> property will be set
|
||||||
|
/// to the number of available messages in the spool.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message count.</value>
|
||||||
|
int Count { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not the service supports referencing messages by UIDs.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Not all servers support referencing messages by UID, so this property should
|
||||||
|
/// be checked before using <see cref="GetMessageUid(int, CancellationToken)"/>
|
||||||
|
/// and <see cref="GetMessageUids(CancellationToken)"/>.</para>
|
||||||
|
/// <para>If the server does not support UIDs, then all methods that take UID arguments
|
||||||
|
/// along with <see cref="GetMessageUid(int, CancellationToken)"/> and
|
||||||
|
/// <see cref="GetMessageUids(CancellationToken)"/> will fail.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if supports uids; otherwise, <c>false</c>.</value>
|
||||||
|
bool SupportsUids { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message count.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message count.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message count.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
int GetMessageCount (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the UID of the message at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not all servers support UIDs, so you should first check
|
||||||
|
/// the <see cref="SupportsUids"/> property.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message UID.</returns>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
string GetMessageUid (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the UID of the message at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not all servers support UIDs, so you should first check
|
||||||
|
/// the <see cref="SupportsUids"/> property.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message UID.</returns>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<string> GetMessageUidAsync (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the full list of available message UIDs.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not all servers support UIDs, so you should first check
|
||||||
|
/// the <see cref="SupportsUids"/> property.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message UIDs.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
IList<string> GetMessageUids (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the full list of available message UIDs.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not all servers support UIDs, so you should first check
|
||||||
|
/// the <see cref="SupportsUids"/> property.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message UIDs.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<IList<string>> GetMessageUidsAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the size of the specified message, in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the size of the specified message, in bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message size, in bytes.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
int GetMessageSize (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the size of the specified message, in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the size of the specified message, in bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message size, in bytes.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<int> GetMessageSizeAsync (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the sizes for all available messages, in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the sizes for all available messages, in bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message sizes, in bytes.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
IList<int> GetMessageSizes (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the sizes for all available messages, in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the sizes for all available messages, in bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message sizes, in bytes.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<IList<int>> GetMessageSizesAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the headers for the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the headers for the specified message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message headers.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
HeaderList GetMessageHeaders (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the headers for the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the headers for the specified message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message headers.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<HeaderList> GetMessageHeadersAsync (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the headers for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the headers for the specified messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The headers for the specified messages.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
IList<HeaderList> GetMessageHeaders (IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the headers for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the headers for the specified messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The headers for the specified messages.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<IList<HeaderList>> GetMessageHeadersAsync (IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the headers of the messages within the specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the headers of the messages within the specified range.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The headers of the messages within the specified range.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first message to get.</param>
|
||||||
|
/// <param name="count">The number of messages to get.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
IList<HeaderList> GetMessageHeaders (int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the headers of the messages within the specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the headers of the messages within the specified range.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The headers of the messages within the specified range.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first message to get.</param>
|
||||||
|
/// <param name="count">The number of messages to get.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<IList<HeaderList>> GetMessageHeadersAsync (int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
MimeMessage GetMessage (int index, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the message at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the message at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task<MimeMessage> GetMessageAsync (int index, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the messages at the specified indexes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the messages at the specified indexes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The messages.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
IList<MimeMessage> GetMessages (IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the messages at the specified indexes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the messages at the specified indexes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The messages.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task<IList<MimeMessage>> GetMessagesAsync (IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the messages within the specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the messages within the specified range.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The messages.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first message to get.</param>
|
||||||
|
/// <param name="count">The number of messages to get.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
IList<MimeMessage> GetMessages (int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the messages within the specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the messages within the specified range.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The messages.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first message to get.</param>
|
||||||
|
/// <param name="count">The number of messages to get.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task<IList<MimeMessage>> GetMessagesAsync (int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message or header stream at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message or header stream at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message or header stream.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="headersOnly"><c>true</c> if only the headers should be retrieved; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Stream GetStream (int index, bool headersOnly = false, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the message or header stream at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the message or header stream at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message or header stream.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="headersOnly"><c>true</c> if only the headers should be retrieved; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task<Stream> GetStreamAsync (int index, bool headersOnly = false, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message or header streams at the specified index.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message or header streams at the specified index.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message or header streams.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="headersOnly"><c>true</c> if only the headers should be retrieved; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
IList<Stream> GetStreams (IList<int> indexes, bool headersOnly = false, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the message or header streams at the specified indexes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the message or header streams at the specified indexes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message or header streams.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="headersOnly"><c>true</c> if only the headers should be retrieved; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task<IList<Stream>> GetStreamsAsync (IList<int> indexes, bool headersOnly = false, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message or header streams within the specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message or header streams within the specified range.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The message or header streams.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first stream to get.</param>
|
||||||
|
/// <param name="count">The number of streams to get.</param>
|
||||||
|
/// <param name="headersOnly"><c>true</c> if only the headers should be retrieved; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
IList<Stream> GetStreams (int startIndex, int count, bool headersOnly = false, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the message or header streams within the specified range.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the message or header streams within the specified range.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The messages.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first stream to get.</param>
|
||||||
|
/// <param name="count">The number of streams to get.</param>
|
||||||
|
/// <param name="headersOnly"><c>true</c> if only the headers should be retrieved; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task<IList<Stream>> GetStreamsAsync (int startIndex, int count, bool headersOnly = false, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark the specified message for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
void DeleteMessage (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously mark the specified message for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task DeleteMessageAsync (int index, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark the specified messages for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
void DeleteMessages (IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously mark the specified messages for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task DeleteMessagesAsync (IList<int> indexes, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark the specified range of messages for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="startIndex">The index of the first message to mark for deletion.</param>
|
||||||
|
/// <param name="count">The number of messages to mark for deletion.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
void DeleteMessages (int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously mark the specified range of messages for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="startIndex">The index of the first message to mark for deletion.</param>
|
||||||
|
/// <param name="count">The number of messages to mark for deletion.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task DeleteMessagesAsync (int startIndex, int count, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark all messages for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
void DeleteAllMessages (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously mark all messages for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task DeleteAllMessagesAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset the state of all messages marked for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
void Reset (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously reset the state of all messages marked for deletion.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Messages marked for deletion are not actually deleted until the session
|
||||||
|
/// is cleanly disconnected
|
||||||
|
/// (see <see cref="IMailService.Disconnect(bool, CancellationToken)"/>).
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task ResetAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,549 @@
|
||||||
|
//
|
||||||
|
// IMailStore.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for retreiving messages from a message store such as IMAP.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Implemented by <see cref="MailKit.Net.Imap.ImapClient"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public interface IMailStore : IMailService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the personal namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The personal folder namespaces contain a user's personal mailbox folders.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The personal namespaces.</value>
|
||||||
|
FolderNamespaceCollection PersonalNamespaces { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the shared namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The shared folder namespaces contain mailbox folders that are shared with the user.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The shared namespaces.</value>
|
||||||
|
FolderNamespaceCollection SharedNamespaces { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the other namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The other folder namespaces contain other mailbox folders.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The other namespaces.</value>
|
||||||
|
FolderNamespaceCollection OtherNamespaces { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not the mail store supports quotas.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not the mail store supports quotas.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the mail store supports quotas; otherwise, <c>false</c>.</value>
|
||||||
|
bool SupportsQuotas { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the threading algorithms supported by the mail store.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The threading algorithms are queried as part of the
|
||||||
|
/// <a href="Overload_MailKit_IMailStore_Connect.htm">Connect</a>
|
||||||
|
/// and <a href="Overload_MailKit_IMailStore_Authenticate.htm">Authenticate</a> methods.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The threading algorithms.</value>
|
||||||
|
HashSet<ThreadingAlgorithm> ThreadingAlgorithms { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the Inbox folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The Inbox folder is the default folder and is typically the folder
|
||||||
|
/// where all new messages are delivered.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The Inbox folder.</value>
|
||||||
|
IMailFolder Inbox { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable the quick resynchronization feature.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Enables quick resynchronization when a folder is opened using the
|
||||||
|
/// <see cref="IMailFolder.Open(FolderAccess,uint,ulong,System.Collections.Generic.IList<UniqueId>,System.Threading.CancellationToken)"/>
|
||||||
|
/// method.</para>
|
||||||
|
/// <para>If this feature is enabled, the <see cref="IMailFolder.MessageExpunged"/> event
|
||||||
|
/// is replaced with the <see cref="IMailFolder.MessagesVanished"/> event.</para>
|
||||||
|
/// <para>This method needs to be called immediately after
|
||||||
|
/// <see cref="IMailService.Authenticate(System.Net.ICredentials,System.Threading.CancellationToken)"/>,
|
||||||
|
/// before the opening of any folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailService"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailService"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Quick resynchronization needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The mail store does not support quick resynchronization.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
void EnableQuickResync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable the quick resynchronization feature.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Enables quick resynchronization when a folder is opened using the
|
||||||
|
/// <see cref="IMailFolder.Open(FolderAccess,uint,ulong,System.Collections.Generic.IList<UniqueId>,System.Threading.CancellationToken)"/>
|
||||||
|
/// method.</para>
|
||||||
|
/// <para>If this feature is enabled, the <see cref="IMailFolder.MessageExpunged"/> event
|
||||||
|
/// is replaced with the <see cref="IMailFolder.MessagesVanished"/> event.</para>
|
||||||
|
/// <para>This method needs to be called immediately after
|
||||||
|
/// <see cref="IMailService.Authenticate(System.Net.ICredentials,System.Threading.CancellationToken)"/>,
|
||||||
|
/// before the opening of any folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailService"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailService"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Quick resynchronization needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The mail store does not support quick resynchronization.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
Task EnableQuickResyncAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the specified special folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not all message stores support the concept of special folders,
|
||||||
|
/// so this method may return <c>null</c>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder if available; otherwise <c>null</c>.</returns>
|
||||||
|
/// <param name="folder">The type of special folder.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="folder"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
IMailFolder GetFolder (SpecialFolder folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder for the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The main reason to get the toplevel folder in a namespace is
|
||||||
|
/// to list its child folders.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
IMailFolder GetFolder (FolderNamespace @namespace);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailService"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailService"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailService"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The namespace folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
IList<IMailFolder> GetFolders (FolderNamespace @namespace, bool subscribedOnly, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailService"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailService"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The namespace folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
Task<IList<IMailFolder>> GetFoldersAsync (FolderNamespace @namespace, bool subscribedOnly, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="items">The status items to pre-populate.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailService"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailService"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailService"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The namespace folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
IList<IMailFolder> GetFolders (FolderNamespace @namespace, StatusItems items = StatusItems.None, bool subscribedOnly = false, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="items">The status items to pre-populate.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailService"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailService"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The namespace folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
Task<IList<IMailFolder>> GetFoldersAsync (FolderNamespace @namespace, StatusItems items = StatusItems.None, bool subscribedOnly = false, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder for the specified path.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder for the specified path.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="path">The folder path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
IMailFolder GetFolder (string path, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the folder for the specified path.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the folder for the specified path.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="path">The folder path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
Task<IMailFolder> GetFolderAsync (string path, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata value.</returns>
|
||||||
|
/// <param name="tag">The metadata tag.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
string GetMetadata (MetadataTag tag, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata value.</returns>
|
||||||
|
/// <param name="tag">The metadata tag.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<string> GetMetadataAsync (MetadataTag tag, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
MetadataCollection GetMetadata (IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<MetadataCollection> GetMetadataAsync (IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="options">The metadata options.</param>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
MetadataCollection GetMetadata (MetadataOptions options, IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="options">The metadata options.</param>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task<MetadataCollection> GetMetadataAsync (MetadataOptions options, IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="metadata">The metadata.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
void SetMetadata (MetadataCollection metadata, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously sets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously sets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="metadata">The metadata.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
Task SetMetadataAsync (MetadataCollection metadata, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a remote message store receives an alert message from the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Some implementations, such as <see cref="MailKit.Net.Imap.ImapClient"/>,
|
||||||
|
/// will emit Alert events when they receive alert messages from the server.
|
||||||
|
/// </remarks>
|
||||||
|
event EventHandler<AlertEventArgs> Alert;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a folder is created.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="FolderCreated"/> event is emitted when a new folder is created.
|
||||||
|
/// </remarks>
|
||||||
|
event EventHandler<FolderCreatedEventArgs> FolderCreated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when metadata changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="MetadataChanged"/> event is emitted when metadata changes.
|
||||||
|
/// </remarks>
|
||||||
|
event EventHandler<MetadataChangedEventArgs> MetadataChanged;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
//
|
||||||
|
// IMailTransport.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for sending messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An interface for sending messages.
|
||||||
|
/// </remarks>
|
||||||
|
public interface IMailTransport : IMailService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
void Send (MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task SendAsync (MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
void Send (MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task SendAsync (MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
void Send (FormatOptions options, MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task SendAsync (FormatOptions options, MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
void Send (FormatOptions options, MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
Task SendAsync (FormatOptions options, MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a message is successfully sent via the transport.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="MessageSent"/> event will be emitted each time a message is successfully sent.
|
||||||
|
/// </remarks>
|
||||||
|
event EventHandler<MessageSentEventArgs> MessageSent;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,460 @@
|
||||||
|
//
|
||||||
|
// IMessageSummary.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A summary of a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a> and
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a> methods
|
||||||
|
/// return lists of <see cref="IMessageSummary"/> items.</para>
|
||||||
|
/// <para>The properties of the <see cref="IMessageSummary"/> that will be available
|
||||||
|
/// depend on the <see cref="MessageSummaryItems"/> passed to the aformentioned method.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public interface IMessageSummary
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder that the message belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder that the message belongs to, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The folder.</value>
|
||||||
|
IMailFolder Folder {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a bitmask of fields that have been populated.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets a bitmask of fields that have been populated.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The fields that have been populated.</value>
|
||||||
|
MessageSummaryItems Fields { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the body structure of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The body will be one of <see cref="BodyPartText"/>,
|
||||||
|
/// <see cref="BodyPartMessage"/>, <see cref="BodyPartBasic"/>,
|
||||||
|
/// or <see cref="BodyPartMultipart"/>.</para>
|
||||||
|
/// <para>This property will only be set if either the
|
||||||
|
/// <see cref="MessageSummaryItems.Body"/> flag or the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The body structure of the message.</value>
|
||||||
|
BodyPart Body { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text body part of the message if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the <c>text/plain</c> body part of the message.</para>
|
||||||
|
/// <para>This property will only be usable if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The text body if it exists; otherwise, <c>null</c>.</value>
|
||||||
|
BodyPartText TextBody { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the html body part of the message if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the <c>text/html</c> body part of the message.</para>
|
||||||
|
/// <para>This property will only be usable if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The html body if it exists; otherwise, <c>null</c>.</value>
|
||||||
|
BodyPartText HtmlBody { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the body parts of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Traverses over the <see cref="Body"/>, enumerating all of the
|
||||||
|
/// <see cref="BodyPartBasic"/> objects.</para>
|
||||||
|
/// <para>This property will only be usable if either the
|
||||||
|
/// <see cref="MessageSummaryItems.Body"/> flag or the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The body parts.</value>
|
||||||
|
IEnumerable<BodyPartBasic> BodyParts { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the attachments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Traverses over the <see cref="Body"/>, enumerating all of the
|
||||||
|
/// <see cref="BodyPartBasic"/> objects that have a <c>Content-Disposition</c>
|
||||||
|
/// header set to <c>"attachment"</c>.</para>
|
||||||
|
/// <para>This property will only be usable if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The attachments.</value>
|
||||||
|
IEnumerable<BodyPartBasic> Attachments { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the preview text of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The preview text is a short snippet of the beginning of the message
|
||||||
|
/// text, typically shown in a mail client's message list to provide the user
|
||||||
|
/// with a sense of what the message is about.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.PreviewText"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The preview text.</value>
|
||||||
|
string PreviewText { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the envelope of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The envelope of a message contains information such as the
|
||||||
|
/// date the message was sent, the subject of the message,
|
||||||
|
/// the sender of the message, who the message was sent to,
|
||||||
|
/// which message(s) the message may be in reply to,
|
||||||
|
/// and the message id.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Envelope"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The envelope of the message.</value>
|
||||||
|
Envelope Envelope { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the normalized subject.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>A normalized <c>Subject</c> header value where prefixes such as <c>"Re:"</c>, <c>"Re[#]:"</c> and <c>"FWD:"</c> have been pruned.</para>
|
||||||
|
/// <para>This property is typically used for threading messages by subject.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The normalized subject.</value>
|
||||||
|
string NormalizedSubject { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Date header value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Date header value. If the Date header is not present, the arrival date is used.
|
||||||
|
/// If neither are known, <see cref="System.DateTimeOffset.MinValue"/> is returned.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The date.</value>
|
||||||
|
DateTimeOffset Date { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the message is a reply.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This value should be based on whether the message subject contained any <c>"Re:"</c>, <c>"Re[#]:"</c> or <c>"FWD:"</c> prefixes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the message is a reply; otherwise, <c>false</c>.</value>
|
||||||
|
bool IsReply { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message flags, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message flags, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Flags"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message flags.</value>
|
||||||
|
MessageFlags? Flags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user-defined message flags, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the user-defined message flags, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Flags"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The user-defined message flags.</value>
|
||||||
|
HashSet<string> Keywords { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user-defined message flags, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the user-defined message flags, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Flags"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The user-defined message flags.</value>
|
||||||
|
[Obsolete ("Use Keywords instead.")]
|
||||||
|
HashSet<string> UserFlags { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message annotations, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message annotations, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Annotations"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message annotations.</value>
|
||||||
|
IList<Annotation> Annotations { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of headers, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the list of headers, if available.</para>
|
||||||
|
/// <para>This property will only be set if <see cref="MessageSummaryItems.Headers"/>
|
||||||
|
/// is specified in a call to one of the
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods or specific headers are requested via a one of the Fetch or FetchAsync methods
|
||||||
|
/// that accept list of specific headers to request for each message such as
|
||||||
|
/// <see cref="IMailFolder.Fetch(System.Collections.Generic.IList<UniqueId>,MessageSummaryItems,System.Collections.Generic.IEnumerable<MimeKit.HeaderId>,System.Threading.CancellationToken)"/>.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The list of headers.</value>
|
||||||
|
HeaderList Headers { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the internal date of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the internal date of the message (often the same date as found in the <c>Received</c> header), if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.InternalDate"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The internal date of the message.</value>
|
||||||
|
DateTimeOffset? InternalDate { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the size of the message, in bytes, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the size of the message, in bytes, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Size"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The size of the message.</value>
|
||||||
|
uint? Size { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the mod-sequence value for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the mod-sequence value for the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.ModSeq"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mod-sequence value.</value>
|
||||||
|
ulong? ModSeq { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message-ids that the message references, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message-ids that the message references, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.References"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The references.</value>
|
||||||
|
MessageIdList References { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the globally unique identifier for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the globally unique identifier of the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.EmailId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <note type="info">This property maps to the <c>EMAILID</c> value defined in the
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The globally unique message identifier.</value>
|
||||||
|
string EmailId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the globally unique identifier for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the globally unique identifier of the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.EmailId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <note type="info">This property maps to the <c>EMAILID</c> value defined in the
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The globally unique message identifier.</value>
|
||||||
|
[Obsolete ("Use EmailId instead.")]
|
||||||
|
string Id { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the globally unique thread identifier for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the globally unique thread identifier for the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.ThreadId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <note type="info">This property maps to the <c>THREADID</c> value defined in the
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The globally unique thread identifier.</value>
|
||||||
|
string ThreadId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique identifier of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the unique identifier of the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.UniqueId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The uid of the message.</value>
|
||||||
|
UniqueId UniqueId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the index of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the index of the message.</para>
|
||||||
|
/// <para>This property is always set.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The index of the message.</value>
|
||||||
|
int Index { get; }
|
||||||
|
|
||||||
|
#region GMail extension properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the GMail message identifier, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the GMail message identifier, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.GMailMessageId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The GMail message identifier.</value>
|
||||||
|
ulong? GMailMessageId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the GMail thread identifier, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the GMail thread identifier, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.GMailThreadId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The GMail thread identifier.</value>
|
||||||
|
ulong? GMailThreadId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of GMail labels, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the list of GMail labels, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.GMailLabels"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The GMail labels.</value>
|
||||||
|
IList<string> GMailLabels { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
//
|
||||||
|
// IProtocolLogger.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for logging the communication between a client and server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An interface for logging the communication between a client and server.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\SmtpExamples.cs" region="ProtocolLogger" />
|
||||||
|
/// </example>
|
||||||
|
public interface IProtocolLogger : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a connection to the specified URI.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Logs a connection to the specified URI.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uri">The URI.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="uri"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The logger has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void LogConnect (Uri uri);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a sequence of bytes sent by the client.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Logs a sequence of bytes sent by the client.</para>
|
||||||
|
/// <para><see cref="LogClient(byte[], int, int)"/> is called by the <see cref="IMailService"/> upon every successful
|
||||||
|
/// write operation to its underlying network stream, passing the exact same <paramref name="buffer"/>,
|
||||||
|
/// <paramref name="offset"/>, and <paramref name="count"/> arguments to the logging function.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name='buffer'>The buffer to log.</param>
|
||||||
|
/// <param name='offset'>The offset of the first byte to log.</param>
|
||||||
|
/// <param name='count'>The number of bytes to log.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The logger has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void LogClient (byte[] buffer, int offset, int count);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a sequence of bytes sent by the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Logs a sequence of bytes sent by the server.</para>
|
||||||
|
/// <para><see cref="LogServer(byte[], int, int)"/> is called by the <see cref="IMailService"/> upon every successful
|
||||||
|
/// read of its underlying network stream with the exact buffer that was read.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name='buffer'>The buffer to log.</param>
|
||||||
|
/// <param name='offset'>The offset of the first byte to log.</param>
|
||||||
|
/// <param name='count'>The number of bytes to log.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="buffer"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="offset"/> is less than zero or greater than the length of <paramref name="buffer"/>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <paramref name="buffer"/> is not large enough to contain <paramref name="count"/> bytes strting
|
||||||
|
/// at the specified <paramref name="offset"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The logger has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void LogServer (byte[] buffer, int offset, int count);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// ITransferProgress.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for reporting progress of uploading or downloading messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An interface for reporting progress of uploading or downloading messages.
|
||||||
|
/// </remarks>
|
||||||
|
public interface ITransferProgress
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Report the progress of the transfer operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Reports the progress of the transfer operation.</para>
|
||||||
|
/// <para>This method is only used if the operation knows the size
|
||||||
|
/// of the message, part, or stream being transferred without doing
|
||||||
|
/// extra work to calculate it.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="bytesTransferred">The number of bytes transferred.</param>
|
||||||
|
/// <param name="totalSize">The total size, in bytes, of the message, part, or stream being transferred.</param>
|
||||||
|
void Report (long bytesTransferred, long totalSize);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Report the progress of the transfer operation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Reports the progress of the transfer operation.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="bytesTransferred">The number of bytes transferred.</param>
|
||||||
|
void Report (long bytesTransferred);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,872 @@
|
||||||
|
//
|
||||||
|
// MailStore.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An abstract mail store implementation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An abstract mail store implementation.
|
||||||
|
/// </remarks>
|
||||||
|
public abstract class MailStore : MailService, IMailStore
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MailStore"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MailStore"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="protocolLogger">The protocol logger.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="protocolLogger"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
protected MailStore (IProtocolLogger protocolLogger) : base (protocolLogger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the personal namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The personal folder namespaces contain a user's personal mailbox folders.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The personal namespaces.</value>
|
||||||
|
public abstract FolderNamespaceCollection PersonalNamespaces {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the shared namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The shared folder namespaces contain mailbox folders that are shared with the user.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The shared namespaces.</value>
|
||||||
|
public abstract FolderNamespaceCollection SharedNamespaces {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the other namespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The other folder namespaces contain other mailbox folders.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The other namespaces.</value>
|
||||||
|
public abstract FolderNamespaceCollection OtherNamespaces {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not the mail store supports quotas.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not the mail store supports quotas.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the mail store supports quotas; otherwise, <c>false</c>.</value>
|
||||||
|
public abstract bool SupportsQuotas {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the threading algorithms supported by the mail store.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The threading algorithms are queried as part of the
|
||||||
|
/// <a href="Overload_MailKit_MailStore_Connect.htm">Connect</a>
|
||||||
|
/// and <a href="Overload_MailKit_MailStore_Authenticate.htm">Authenticate</a> methods.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The supported threading algorithms.</value>
|
||||||
|
public abstract HashSet<ThreadingAlgorithm> ThreadingAlgorithms {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the Inbox folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The Inbox folder is the default folder and always exists on the mail store.</para>
|
||||||
|
/// <note type="note">This property will only be available after the client has been authenticated.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The Inbox folder.</value>
|
||||||
|
public abstract IMailFolder Inbox {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable the quick resynchronization feature.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Enables quick resynchronization when a folder is opened using the
|
||||||
|
/// <see cref="MailFolder.Open(FolderAccess,uint,ulong,System.Collections.Generic.IList<UniqueId>,System.Threading.CancellationToken)"/>
|
||||||
|
/// method.</para>
|
||||||
|
/// <para>If this feature is enabled, the <see cref="MailFolder.MessageExpunged"/> event is replaced
|
||||||
|
/// with the <see cref="MailFolder.MessagesVanished"/> event.</para>
|
||||||
|
/// <para>This method needs to be called immediately after calling one of the
|
||||||
|
/// <a href="Overload_MailKit_MailService_Authenticate.htm">Authenticate</a> methods, before
|
||||||
|
/// opening any folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Quick resynchronization needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The mail store does not support quick resynchronization.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract void EnableQuickResync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable the quick resynchronization feature.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Enables quick resynchronization when a folder is opened using the
|
||||||
|
/// <see cref="MailFolder.Open(FolderAccess,uint,ulong,System.Collections.Generic.IList<UniqueId>,System.Threading.CancellationToken)"/>
|
||||||
|
/// method.</para>
|
||||||
|
/// <para>If this feature is enabled, the <see cref="MailFolder.MessageExpunged"/> event is replaced
|
||||||
|
/// with the <see cref="MailFolder.MessagesVanished"/> event.</para>
|
||||||
|
/// <para>This method needs to be called immediately after calling one of the
|
||||||
|
/// <a href="Overload_MailKit_MailService_Authenticate.htm">Authenticate</a> methods, before
|
||||||
|
/// opening any folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Quick resynchronization needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The mail store does not support quick resynchronization.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task EnableQuickResyncAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the specified special folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not all mail stores support special folders. Each implementation
|
||||||
|
/// should provide a way to determine if special folders are supported.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder if available; otherwise <c>null</c>.</returns>
|
||||||
|
/// <param name="folder">The type of special folder.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="folder"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
public abstract IMailFolder GetFolder (SpecialFolder folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder for the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder for the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
public abstract IMailFolder GetFolder (FolderNamespace @namespace);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public virtual IList<IMailFolder> GetFolders (FolderNamespace @namespace, bool subscribedOnly, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetFolders (@namespace, StatusItems.None, subscribedOnly, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public virtual Task<IList<IMailFolder>> GetFoldersAsync (FolderNamespace @namespace, bool subscribedOnly, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetFoldersAsync (@namespace, StatusItems.None, subscribedOnly, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="items">The status items to pre-populate.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract IList<IMailFolder> GetFolders (FolderNamespace @namespace, StatusItems items = StatusItems.None, bool subscribedOnly = false, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="items">The status items to pre-populate.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task<IList<IMailFolder>> GetFoldersAsync (FolderNamespace @namespace, StatusItems items = StatusItems.None, bool subscribedOnly = false, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder for the specified path.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder for the specified path.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="path">The folder path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract IMailFolder GetFolder (string path, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the folder for the specified path.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the folder for the specified path.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="path">The folder path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="MailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task<IMailFolder> GetFolderAsync (string path, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata value.</returns>
|
||||||
|
/// <param name="tag">The metadata tag.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract string GetMetadata (MetadataTag tag, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata value.</returns>
|
||||||
|
/// <param name="tag">The metadata tag.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task<string> GetMetadataAsync (MetadataTag tag, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="tags"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public virtual MetadataCollection GetMetadata (IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetMetadata (new MetadataOptions (), tags, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="tags"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public virtual Task<MetadataCollection> GetMetadataAsync (IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetMetadataAsync (new MetadataOptions (), tags, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="options">The metadata options.</param>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="tags"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract MetadataCollection GetMetadata (MetadataOptions options, IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="options">The metadata options.</param>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="tags"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task<MetadataCollection> GetMetadataAsync (MetadataOptions options, IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="metadata">The metadata.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="metadata"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract void SetMetadata (MetadataCollection metadata, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously sets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously sets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="metadata">The metadata.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="metadata"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="IMailStore"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="IMailStore"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The folder does not support metadata.
|
||||||
|
/// </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="ProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The command failed.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task SetMetadataAsync (MetadataCollection metadata, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a remote message store receives an alert message from the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="Alert"/> event is raised whenever the mail server sends an
|
||||||
|
/// alert message.
|
||||||
|
/// </remarks>
|
||||||
|
public event EventHandler<AlertEventArgs> Alert;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise the alert event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Raises the alert event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The alert message.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="message"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
protected virtual void OnAlert (string message)
|
||||||
|
{
|
||||||
|
var handler = Alert;
|
||||||
|
|
||||||
|
if (handler != null)
|
||||||
|
handler (this, new AlertEventArgs (message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a folder is created.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="FolderCreated"/> event is emitted when a new folder is created.
|
||||||
|
/// </remarks>
|
||||||
|
public event EventHandler<FolderCreatedEventArgs> FolderCreated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise the folder created event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Raises the folder created event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folder">The folder that was just created.</param>
|
||||||
|
protected virtual void OnFolderCreated (IMailFolder folder)
|
||||||
|
{
|
||||||
|
var handler = FolderCreated;
|
||||||
|
|
||||||
|
if (handler != null)
|
||||||
|
handler (this, new FolderCreatedEventArgs (folder));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when metadata changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="MetadataChanged"/> event is emitted when metadata changes.
|
||||||
|
/// </remarks>
|
||||||
|
public event EventHandler<MetadataChangedEventArgs> MetadataChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise the metadata changed event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Raises the metadata changed event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="metadata">The metadata that changed.</param>
|
||||||
|
protected virtual void OnMetadataChanged (Metadata metadata)
|
||||||
|
{
|
||||||
|
var handler = MetadataChanged;
|
||||||
|
|
||||||
|
if (handler != null)
|
||||||
|
handler (this, new MetadataChangedEventArgs (metadata));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,507 @@
|
||||||
|
//
|
||||||
|
// MailTransport.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An abstract mail transport implementation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An abstract mail transport implementation.
|
||||||
|
/// </remarks>
|
||||||
|
public abstract class MailTransport : MailService, IMailTransport
|
||||||
|
{
|
||||||
|
static readonly FormatOptions DefaultOptions;
|
||||||
|
|
||||||
|
static MailTransport ()
|
||||||
|
{
|
||||||
|
var options = FormatOptions.Default.Clone ();
|
||||||
|
options.HiddenHeaders.Add (HeaderId.ContentLength);
|
||||||
|
options.HiddenHeaders.Add (HeaderId.ResentBcc);
|
||||||
|
options.HiddenHeaders.Add (HeaderId.Bcc);
|
||||||
|
options.NewLineFormat = NewLineFormat.Dos;
|
||||||
|
|
||||||
|
DefaultOptions = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MailTransport"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MailTransport"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="protocolLogger">The protocol logger.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="protocolLogger"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
protected MailTransport (IProtocolLogger protocolLogger) : base (protocolLogger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\SmtpExamples.cs" region="SendMessage"/>
|
||||||
|
/// </example>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="message"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public virtual void Send (MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null)
|
||||||
|
{
|
||||||
|
Send (DefaultOptions, message, cancellationToken, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="message"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public virtual Task SendAsync (MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null)
|
||||||
|
{
|
||||||
|
return SendAsync (DefaultOptions, message, cancellationToken, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="sender"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="recipients"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public virtual void Send (MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null)
|
||||||
|
{
|
||||||
|
Send (DefaultOptions, message, sender, recipients, cancellationToken, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="sender"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="recipients"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public virtual Task SendAsync (MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null)
|
||||||
|
{
|
||||||
|
return SendAsync (DefaultOptions, message, sender, recipients, cancellationToken, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\SmtpExamples.cs" region="SendMessageWithOptions"/>
|
||||||
|
/// </example>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>Internationalized formatting was requested but is not supported by the transport.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public abstract void Send (FormatOptions options, MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously sends the specified message.</para>
|
||||||
|
/// <para>The sender address is determined by checking the following
|
||||||
|
/// message headers (in order of precedence): Resent-Sender,
|
||||||
|
/// Resent-From, Sender, and From.</para>
|
||||||
|
/// <para>If either the Resent-Sender or Resent-From addresses are present,
|
||||||
|
/// the recipients are collected from the Resent-To, Resent-Cc, and
|
||||||
|
/// Resent-Bcc headers, otherwise the To, Cc, and Bcc headers are used.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>Internationalized formatting was requested but is not supported by the transport.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task SendAsync (FormatOptions options, MimeMessage message, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="sender"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="recipients"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>Internationalized formatting was requested but is not supported by the transport.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public abstract void Send (FormatOptions options, MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously send the specified message using the supplied sender and recipients.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously sends the specified message using the supplied sender and recipients.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="sender">The mailbox address to use for sending the message.</param>
|
||||||
|
/// <param name="recipients">The mailbox addresses that should receive the message.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="sender"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="recipients"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="MailTransport"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="MailTransport"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotAuthenticatedException">
|
||||||
|
/// Authentication is required before sending a message.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// <para>A sender has not been specified.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>No recipients have been specified.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation has been canceled.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>Internationalized formatting was requested but is not supported by the transport.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="CommandException">
|
||||||
|
/// The send command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ProtocolException">
|
||||||
|
/// A protocol exception occurred.
|
||||||
|
/// </exception>
|
||||||
|
public abstract Task SendAsync (FormatOptions options, MimeMessage message, MailboxAddress sender, IEnumerable<MailboxAddress> recipients, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a message is successfully sent via the transport.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <see cref="MessageSent"/> event will be emitted each time a message is successfully sent.
|
||||||
|
/// </remarks>
|
||||||
|
public event EventHandler<MessageSentEventArgs> MessageSent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise the message sent event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Raises the message sent event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="e">The message sent event args.</param>
|
||||||
|
protected virtual void OnMessageSent (MessageSentEventArgs e)
|
||||||
|
{
|
||||||
|
var handler = MessageSent;
|
||||||
|
|
||||||
|
if (handler != null)
|
||||||
|
handler (this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
//
|
||||||
|
// MessageEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when the state of a message changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when the state of a message changes.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.MessageEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageEventArgs (int index)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
Index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.MessageEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageEventArgs (int index, UniqueId uid)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
Index = index;
|
||||||
|
UniqueId = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the index of the message that changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the index of the message that changed.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The index of the message.</value>
|
||||||
|
public int Index {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique ID of the message that changed, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the unique ID of the message that changed, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The unique ID of the message.</value>
|
||||||
|
public UniqueId? UniqueId {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// MessageFlags.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// An enumeration of message flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An enumeration of message flags.
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum MessageFlags {
|
||||||
|
/// <summary>
|
||||||
|
/// No message flags are set.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message has been read.
|
||||||
|
/// </summary>
|
||||||
|
Seen = 1 << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message has been answered (replied to).
|
||||||
|
/// </summary>
|
||||||
|
Answered = 1 << 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message has been flagged for importance.
|
||||||
|
/// </summary>
|
||||||
|
Flagged = 1 << 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message has been marked for deletion.
|
||||||
|
/// </summary>
|
||||||
|
Deleted = 1 << 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message is marked as a draft.
|
||||||
|
/// </summary>
|
||||||
|
Draft = 1 << 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The message has just recently arrived in the folder.
|
||||||
|
/// </summary>
|
||||||
|
Recent = 1 << 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User-defined flags are allowed by the folder.
|
||||||
|
/// </summary>
|
||||||
|
UserDefined = 1 << 6,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,269 @@
|
||||||
|
//
|
||||||
|
// MessageFlagsChangedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args for the <see cref="IMailFolder.MessageFlagsChanged"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args for the <see cref="IMailFolder.MessageFlagsChanged"/> event.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageFlagsChangedEventArgs : MessageEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
internal MessageFlagsChangedEventArgs (int index) : base (index)
|
||||||
|
{
|
||||||
|
Keywords = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, MessageFlags flags) : base (index)
|
||||||
|
{
|
||||||
|
Keywords = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <param name="keywords">The user-defined message flags.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="keywords"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, MessageFlags flags, HashSet<string> keywords) : base (index)
|
||||||
|
{
|
||||||
|
if (keywords == null)
|
||||||
|
throw new ArgumentNullException (nameof (keywords));
|
||||||
|
|
||||||
|
Keywords = keywords;
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, MessageFlags flags, ulong modseq) : base (index)
|
||||||
|
{
|
||||||
|
Keywords = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
ModSeq = modseq;
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <param name="keywords">The user-defined message flags.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="keywords"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, MessageFlags flags, HashSet<string> keywords, ulong modseq) : base (index)
|
||||||
|
{
|
||||||
|
if (keywords == null)
|
||||||
|
throw new ArgumentNullException (nameof (keywords));
|
||||||
|
|
||||||
|
Keywords = keywords;
|
||||||
|
ModSeq = modseq;
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, UniqueId uid, MessageFlags flags) : base (index, uid)
|
||||||
|
{
|
||||||
|
Keywords = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <param name="keywords">The user-defined message flags.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="keywords"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, UniqueId uid, MessageFlags flags, HashSet<string> keywords) : base (index, uid)
|
||||||
|
{
|
||||||
|
if (keywords == null)
|
||||||
|
throw new ArgumentNullException (nameof (keywords));
|
||||||
|
|
||||||
|
Keywords = keywords;
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, UniqueId uid, MessageFlags flags, ulong modseq) : base (index, uid)
|
||||||
|
{
|
||||||
|
Keywords = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
ModSeq = modseq;
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="flags">The message flags.</param>
|
||||||
|
/// <param name="keywords">The user-defined message flags.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="keywords"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageFlagsChangedEventArgs (int index, UniqueId uid, MessageFlags flags, HashSet<string> keywords, ulong modseq) : base (index, uid)
|
||||||
|
{
|
||||||
|
if (keywords == null)
|
||||||
|
throw new ArgumentNullException (nameof (keywords));
|
||||||
|
|
||||||
|
Keywords = keywords;
|
||||||
|
ModSeq = modseq;
|
||||||
|
Flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated message flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated message flags.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The updated message flags.</value>
|
||||||
|
public MessageFlags Flags {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated user-defined message flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated user-defined message flags.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The updated user-defined message flags.</value>
|
||||||
|
public HashSet<string> Keywords {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated user-defined message flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated user-defined message flags.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The updated user-defined message flags.</value>
|
||||||
|
[Obsolete ("Use Keywords instead.")]
|
||||||
|
public HashSet<string> UserFlags {
|
||||||
|
get { return Keywords; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated mod-sequence value of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated mod-sequence value of the message, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mod-sequence value.</value>
|
||||||
|
public ulong? ModSeq {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
//
|
||||||
|
// LabelsChangedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args for the <see cref="IMailFolder.MessageLabelsChanged"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args for the <see cref="IMailFolder.MessageLabelsChanged"/> event.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageLabelsChangedEventArgs : MessageEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageLabelsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageLabelsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
internal MessageLabelsChangedEventArgs (int index) : base (index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageLabelsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageLabelsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="labels">The message labels.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="labels"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageLabelsChangedEventArgs (int index, IList<string> labels) : base (index)
|
||||||
|
{
|
||||||
|
if (labels == null)
|
||||||
|
throw new ArgumentNullException (nameof (labels));
|
||||||
|
|
||||||
|
Labels = new ReadOnlyCollection<string> (labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageLabelsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageLabelsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="labels">The message labels.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="labels"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageLabelsChangedEventArgs (int index, IList<string> labels, ulong modseq) : base (index)
|
||||||
|
{
|
||||||
|
if (labels == null)
|
||||||
|
throw new ArgumentNullException (nameof (labels));
|
||||||
|
|
||||||
|
Labels = new ReadOnlyCollection<string> (labels);
|
||||||
|
ModSeq = modseq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageLabelsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageLabelsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="labels">The message labels.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="labels"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageLabelsChangedEventArgs (int index, UniqueId uid, IList<string> labels) : base (index, uid)
|
||||||
|
{
|
||||||
|
if (labels == null)
|
||||||
|
throw new ArgumentNullException (nameof (labels));
|
||||||
|
|
||||||
|
Labels = new ReadOnlyCollection<string> (labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageLabelsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageLabelsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="labels">The message labels.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="labels"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public MessageLabelsChangedEventArgs (int index, UniqueId uid, IList<string> labels, ulong modseq) : base (index, uid)
|
||||||
|
{
|
||||||
|
if (labels == null)
|
||||||
|
throw new ArgumentNullException (nameof (labels));
|
||||||
|
|
||||||
|
Labels = new ReadOnlyCollection<string> (labels);
|
||||||
|
ModSeq = modseq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated labels.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated labels.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The updated labels.</value>
|
||||||
|
public IList<string> Labels {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated mod-sequence value of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated mod-sequence value of the message, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mod-sequence value.</value>
|
||||||
|
public ulong? ModSeq {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// MessageNotFoundException.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
#if SERIALIZABLE
|
||||||
|
using System.Security;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// The exception that is thrown when a message (or body part) could not be found.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This exception is thrown by methods such as
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_GetMessage.htm">IMailFolder.GetMessage</a>,
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_GetBodyPart.htm">IMailFolder.GetBodyPart</a>, or
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_GetStream.htm">IMailFolder.GetStream</a>
|
||||||
|
/// when the server's response does not contain the message, body part, or stream data requested.
|
||||||
|
/// </remarks>
|
||||||
|
#if SERIALIZABLE
|
||||||
|
[Serializable]
|
||||||
|
#endif
|
||||||
|
public class MessageNotFoundException : Exception
|
||||||
|
{
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Deserializes a <see cref="MessageNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
[SecuritySafeCritical]
|
||||||
|
protected MessageNotFoundException (SerializationInfo info, StreamingContext context) : base (info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="innerException">The inner exception.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// </exception>
|
||||||
|
public MessageNotFoundException (string message, Exception innerException) : base (message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageNotFoundException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
public MessageNotFoundException (string message) : base (message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
//
|
||||||
|
// MessageSentEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when a message is successfully sent.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when message is successfully sent.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageSentEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageSentEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageSentEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The message that was just sent.</param>
|
||||||
|
/// <param name="response">The response from the server.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="message"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="response"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public MessageSentEventArgs (MimeMessage message, string response)
|
||||||
|
{
|
||||||
|
if (message == null)
|
||||||
|
throw new ArgumentNullException (nameof (message));
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
throw new ArgumentNullException (nameof (response));
|
||||||
|
|
||||||
|
Message = message;
|
||||||
|
Response = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message that was just sent.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message that was just sent.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message.</value>
|
||||||
|
public MimeMessage Message {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the server's response.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the server's response.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The response.</value>
|
||||||
|
public string Response {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,295 @@
|
||||||
|
//
|
||||||
|
// MessageSorter.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
using MailKit.Search;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Routines for sorting messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Routines for sorting messages.
|
||||||
|
/// </remarks>
|
||||||
|
public static class MessageSorter
|
||||||
|
{
|
||||||
|
class MessageComparer<T> : IComparer<T> where T : IMessageSummary
|
||||||
|
{
|
||||||
|
readonly IList<OrderBy> orderBy;
|
||||||
|
|
||||||
|
public MessageComparer (IList<OrderBy> orderBy)
|
||||||
|
{
|
||||||
|
this.orderBy = orderBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IComparer implementation
|
||||||
|
|
||||||
|
static int CompareDisplayNames (InternetAddressList list1, InternetAddressList list2)
|
||||||
|
{
|
||||||
|
var m1 = list1.Mailboxes.GetEnumerator ();
|
||||||
|
var m2 = list2.Mailboxes.GetEnumerator ();
|
||||||
|
bool n1 = m1.MoveNext ();
|
||||||
|
bool n2 = m2.MoveNext ();
|
||||||
|
|
||||||
|
while (n1 && n2) {
|
||||||
|
var name1 = m1.Current.Name ?? string.Empty;
|
||||||
|
var name2 = m2.Current.Name ?? string.Empty;
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
if ((cmp = string.Compare (name1, name2, StringComparison.OrdinalIgnoreCase)) != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
n1 = m1.MoveNext ();
|
||||||
|
n2 = m2.MoveNext ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return n1 ? 1 : (n2 ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CompareMailboxAddresses (InternetAddressList list1, InternetAddressList list2)
|
||||||
|
{
|
||||||
|
var m1 = list1.Mailboxes.GetEnumerator ();
|
||||||
|
var m2 = list2.Mailboxes.GetEnumerator ();
|
||||||
|
bool n1 = m1.MoveNext ();
|
||||||
|
bool n2 = m2.MoveNext ();
|
||||||
|
|
||||||
|
while (n1 && n2) {
|
||||||
|
int cmp;
|
||||||
|
|
||||||
|
if ((cmp = string.Compare (m1.Current.Address, m2.Current.Address, StringComparison.OrdinalIgnoreCase)) != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
n1 = m1.MoveNext ();
|
||||||
|
n2 = m2.MoveNext ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return n1 ? 1 : (n2 ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare (T x, T y)
|
||||||
|
{
|
||||||
|
int cmp = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < orderBy.Count; i++) {
|
||||||
|
switch (orderBy[i].Type) {
|
||||||
|
case OrderByType.Annotation:
|
||||||
|
var annotation = (OrderByAnnotation) orderBy[i];
|
||||||
|
|
||||||
|
var xannotation = x.Annotations?.FirstOrDefault (a => a.Entry == annotation.Entry);
|
||||||
|
var yannotation = y.Annotations?.FirstOrDefault (a => a.Entry == annotation.Entry);
|
||||||
|
|
||||||
|
var xvalue = xannotation?.Properties[annotation.Attribute] ?? string.Empty;
|
||||||
|
var yvalue = yannotation?.Properties[annotation.Attribute] ?? string.Empty;
|
||||||
|
|
||||||
|
cmp = string.Compare (xvalue, yvalue, StringComparison.OrdinalIgnoreCase);
|
||||||
|
break;
|
||||||
|
case OrderByType.Arrival:
|
||||||
|
cmp = x.Index.CompareTo (y.Index);
|
||||||
|
break;
|
||||||
|
case OrderByType.Cc:
|
||||||
|
cmp = CompareMailboxAddresses (x.Envelope.Cc, y.Envelope.Cc);
|
||||||
|
break;
|
||||||
|
case OrderByType.Date:
|
||||||
|
cmp = x.Date.CompareTo (y.Date);
|
||||||
|
break;
|
||||||
|
case OrderByType.DisplayFrom:
|
||||||
|
cmp = CompareDisplayNames (x.Envelope.From, y.Envelope.From);
|
||||||
|
break;
|
||||||
|
case OrderByType.From:
|
||||||
|
cmp = CompareMailboxAddresses (x.Envelope.From, y.Envelope.From);
|
||||||
|
break;
|
||||||
|
case OrderByType.ModSeq:
|
||||||
|
var xmodseq = x.ModSeq ?? 0;
|
||||||
|
var ymodseq = y.ModSeq ?? 0;
|
||||||
|
|
||||||
|
cmp = xmodseq.CompareTo (ymodseq);
|
||||||
|
break;
|
||||||
|
case OrderByType.Size:
|
||||||
|
var xsize = x.Size ?? 0;
|
||||||
|
var ysize = y.Size ?? 0;
|
||||||
|
|
||||||
|
cmp = xsize.CompareTo (ysize);
|
||||||
|
break;
|
||||||
|
case OrderByType.Subject:
|
||||||
|
var xsubject = x.Envelope.Subject ?? string.Empty;
|
||||||
|
var ysubject = y.Envelope.Subject ?? string.Empty;
|
||||||
|
|
||||||
|
cmp = string.Compare (xsubject, ysubject, StringComparison.OrdinalIgnoreCase);
|
||||||
|
break;
|
||||||
|
case OrderByType.DisplayTo:
|
||||||
|
cmp = CompareDisplayNames (x.Envelope.To, y.Envelope.To);
|
||||||
|
break;
|
||||||
|
case OrderByType.To:
|
||||||
|
cmp = CompareMailboxAddresses (x.Envelope.To, y.Envelope.To);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmp == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return orderBy[i].Order == SortOrder.Descending ? cmp * -1 : cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
static MessageSummaryItems GetMessageSummaryItems (IList<OrderBy> orderBy)
|
||||||
|
{
|
||||||
|
var items = MessageSummaryItems.None;
|
||||||
|
|
||||||
|
for (int i = 0; i < orderBy.Count; i++) {
|
||||||
|
switch (orderBy[i].Type) {
|
||||||
|
case OrderByType.Annotation:
|
||||||
|
items |= MessageSummaryItems.Annotations;
|
||||||
|
break;
|
||||||
|
case OrderByType.Arrival:
|
||||||
|
break;
|
||||||
|
case OrderByType.Cc:
|
||||||
|
case OrderByType.Date:
|
||||||
|
case OrderByType.DisplayFrom:
|
||||||
|
case OrderByType.DisplayTo:
|
||||||
|
case OrderByType.From:
|
||||||
|
case OrderByType.Subject:
|
||||||
|
case OrderByType.To:
|
||||||
|
items |= MessageSummaryItems.Envelope;
|
||||||
|
break;
|
||||||
|
case OrderByType.ModSeq:
|
||||||
|
items |= MessageSummaryItems.ModSeq;
|
||||||
|
break;
|
||||||
|
case OrderByType.Size:
|
||||||
|
items |= MessageSummaryItems.Size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sorts the messages by the specified ordering.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sorts the messages by the specified ordering.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The sorted messages.</returns>
|
||||||
|
/// <typeparam name="T">The message items must implement the <see cref="IMessageSummary"/> interface.</typeparam>
|
||||||
|
/// <param name="messages">The messages to sort.</param>
|
||||||
|
/// <param name="orderBy">The sort ordering.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="messages"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para><paramref name="messages"/> contains one or more items that is missing information needed for sorting.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="orderBy"/> is an empty list.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static IList<T> Sort<T> (this IEnumerable<T> messages, IList<OrderBy> orderBy) where T : IMessageSummary
|
||||||
|
{
|
||||||
|
if (messages == null)
|
||||||
|
throw new ArgumentNullException (nameof (messages));
|
||||||
|
|
||||||
|
if (orderBy == null)
|
||||||
|
throw new ArgumentNullException (nameof (orderBy));
|
||||||
|
|
||||||
|
if (orderBy.Count == 0)
|
||||||
|
throw new ArgumentException ("No sort order provided.", nameof (orderBy));
|
||||||
|
|
||||||
|
var requiredFields = GetMessageSummaryItems (orderBy);
|
||||||
|
var list = new List<T> ();
|
||||||
|
|
||||||
|
foreach (var message in messages) {
|
||||||
|
if ((message.Fields & requiredFields) != requiredFields)
|
||||||
|
throw new ArgumentException ("One or more messages is missing information needed for sorting.", nameof (messages));
|
||||||
|
|
||||||
|
list.Add (message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.Count < 2)
|
||||||
|
return list;
|
||||||
|
|
||||||
|
var comparer = new MessageComparer<T> (orderBy);
|
||||||
|
|
||||||
|
list.Sort (comparer);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sorts the messages by the specified ordering.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sorts the messages by the specified ordering.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The sorted messages.</returns>
|
||||||
|
/// <typeparam name="T">The message items must implement the <see cref="IMessageSummary"/> interface.</typeparam>
|
||||||
|
/// <param name="messages">The messages to sort.</param>
|
||||||
|
/// <param name="orderBy">The sort ordering.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="messages"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para><paramref name="messages"/> contains one or more items that is missing information needed for sorting.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="orderBy"/> is an empty list.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static void Sort<T> (this List<T> messages, IList<OrderBy> orderBy) where T : IMessageSummary
|
||||||
|
{
|
||||||
|
if (messages == null)
|
||||||
|
throw new ArgumentNullException (nameof (messages));
|
||||||
|
|
||||||
|
if (orderBy == null)
|
||||||
|
throw new ArgumentNullException (nameof (orderBy));
|
||||||
|
|
||||||
|
if (orderBy.Count == 0)
|
||||||
|
throw new ArgumentException ("No sort order provided.", nameof (orderBy));
|
||||||
|
|
||||||
|
var requiredFields = GetMessageSummaryItems (orderBy);
|
||||||
|
|
||||||
|
for (int i = 0; i < messages.Count; i++) {
|
||||||
|
if ((messages[i].Fields & requiredFields) != requiredFields)
|
||||||
|
throw new ArgumentException ("One or more messages is missing information needed for sorting.", nameof (messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messages.Count < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var comparer = new MessageComparer<T> (orderBy);
|
||||||
|
|
||||||
|
messages.Sort (comparer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,758 @@
|
||||||
|
//
|
||||||
|
// MessageSummary.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A summary of a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a> and
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a> methods
|
||||||
|
/// return lists of <see cref="IMessageSummary"/> items.</para>
|
||||||
|
/// <para>The properties of the <see cref="MessageSummary"/> that will be available
|
||||||
|
/// depend on the <see cref="MessageSummaryItems"/> passed to the aformentioned method.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageSummary : IMessageSummary
|
||||||
|
{
|
||||||
|
int threadableReplyDepth = -1;
|
||||||
|
string normalizedSubject;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageSummary"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageSummary"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is negative.
|
||||||
|
/// </exception>
|
||||||
|
public MessageSummary (int index)
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (index));
|
||||||
|
|
||||||
|
Keywords = new HashSet<string> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
Index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageSummary"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageSummary"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folder">The folder that the message belongs to.</param>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folder"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is negative.
|
||||||
|
/// </exception>
|
||||||
|
public MessageSummary (IMailFolder folder, int index) : this (index)
|
||||||
|
{
|
||||||
|
if (folder == null)
|
||||||
|
throw new ArgumentNullException (nameof (folder));
|
||||||
|
|
||||||
|
Folder = folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateThreadableSubject ()
|
||||||
|
{
|
||||||
|
if (normalizedSubject != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Envelope?.Subject != null) {
|
||||||
|
normalizedSubject = MessageThreader.GetThreadableSubject (Envelope.Subject, out threadableReplyDepth);
|
||||||
|
} else {
|
||||||
|
normalizedSubject = string.Empty;
|
||||||
|
threadableReplyDepth = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder that the message belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder that the message belongs to, if available.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The folder.</value>
|
||||||
|
public IMailFolder Folder {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a bitmask of fields that have been populated.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets a bitmask of fields that have been populated.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The fields that have been populated.</value>
|
||||||
|
public MessageSummaryItems Fields {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the body structure of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The body will be one of <see cref="BodyPartText"/>,
|
||||||
|
/// <see cref="BodyPartMessage"/>, <see cref="BodyPartBasic"/>,
|
||||||
|
/// or <see cref="BodyPartMultipart"/>.</para>
|
||||||
|
/// <para>This property will only be set if either the
|
||||||
|
/// <see cref="MessageSummaryItems.Body"/> flag or the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The body structure of the message.</value>
|
||||||
|
public BodyPart Body {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BodyPart GetMultipartRelatedRoot (BodyPartMultipart related)
|
||||||
|
{
|
||||||
|
string start = related.ContentType.Parameters["start"];
|
||||||
|
string contentId;
|
||||||
|
|
||||||
|
if (start == null)
|
||||||
|
return related.BodyParts.Count > 0 ? related.BodyParts[0] : null;
|
||||||
|
|
||||||
|
if ((contentId = MimeUtils.EnumerateReferences (start).FirstOrDefault ()) == null)
|
||||||
|
contentId = start;
|
||||||
|
|
||||||
|
var cid = new Uri (string.Format ("cid:{0}", contentId));
|
||||||
|
|
||||||
|
for (int i = 0; i < related.BodyParts.Count; i++) {
|
||||||
|
var basic = related.BodyParts[i] as BodyPartBasic;
|
||||||
|
|
||||||
|
if (basic != null && (basic.ContentId == contentId || basic.ContentLocation == cid))
|
||||||
|
return basic;
|
||||||
|
|
||||||
|
var multipart = related.BodyParts[i] as BodyPartMultipart;
|
||||||
|
|
||||||
|
if (multipart != null && multipart.ContentLocation == cid)
|
||||||
|
return multipart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryGetMultipartAlternativeBody (BodyPartMultipart multipart, bool html, out BodyPartText body)
|
||||||
|
{
|
||||||
|
// walk the multipart/alternative children backwards from greatest level of faithfulness to the least faithful
|
||||||
|
for (int i = multipart.BodyParts.Count - 1; i >= 0; i--) {
|
||||||
|
var multi = multipart.BodyParts[i] as BodyPartMultipart;
|
||||||
|
BodyPartText text = null;
|
||||||
|
|
||||||
|
if (multi != null) {
|
||||||
|
if (multi.ContentType.IsMimeType ("multipart", "related")) {
|
||||||
|
text = GetMultipartRelatedRoot (multi) as BodyPartText;
|
||||||
|
} else if (multi.ContentType.IsMimeType ("multipart", "alternative")) {
|
||||||
|
// Note: nested multipart/alternatives make no sense... yet here we are.
|
||||||
|
if (TryGetMultipartAlternativeBody (multi, html, out body))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = multipart.BodyParts[i] as BodyPartText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text != null && (html ? text.IsHtml : text.IsPlain)) {
|
||||||
|
body = text;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body = null;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TryGetMessageBody (BodyPartMultipart multipart, bool html, out BodyPartText body)
|
||||||
|
{
|
||||||
|
BodyPartMultipart multi;
|
||||||
|
BodyPartText text;
|
||||||
|
|
||||||
|
if (multipart.ContentType.IsMimeType ("multipart", "alternative"))
|
||||||
|
return TryGetMultipartAlternativeBody (multipart, html, out body);
|
||||||
|
|
||||||
|
if (!multipart.ContentType.IsMimeType ("multipart", "related")) {
|
||||||
|
// Note: This is probably a multipart/mixed... and if not, we can still treat it like it is.
|
||||||
|
for (int i = 0; i < multipart.BodyParts.Count; i++) {
|
||||||
|
multi = multipart.BodyParts[i] as BodyPartMultipart;
|
||||||
|
|
||||||
|
// descend into nested multiparts, if there are any...
|
||||||
|
if (multi != null) {
|
||||||
|
if (TryGetMessageBody (multi, html, out body))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// The text body should never come after a multipart.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
text = multipart.BodyParts[i] as BodyPartText;
|
||||||
|
|
||||||
|
// Look for the first non-attachment text part (realistically, the body text will
|
||||||
|
// preceed any attachments, but I'm not sure we can rely on that assumption).
|
||||||
|
if (text != null && !text.IsAttachment) {
|
||||||
|
if (html ? text.IsHtml : text.IsPlain) {
|
||||||
|
body = text;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: the first text/* part in a multipart/mixed is the text body.
|
||||||
|
// If it's not in the format we're looking for, then it doesn't exist.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Note: If the multipart/related root document is HTML, then this is the droid we are looking for.
|
||||||
|
var root = GetMultipartRelatedRoot (multipart);
|
||||||
|
|
||||||
|
text = root as BodyPartText;
|
||||||
|
|
||||||
|
if (text != null) {
|
||||||
|
body = (html ? text.IsHtml : text.IsPlain) ? text : null;
|
||||||
|
return body != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maybe the root is another multipart (like multipart/alternative)?
|
||||||
|
multi = root as BodyPartMultipart;
|
||||||
|
|
||||||
|
if (multi != null)
|
||||||
|
return TryGetMessageBody (multi, html, out body);
|
||||||
|
}
|
||||||
|
|
||||||
|
body = null;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text body part of the message if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the <c>text/plain</c> body part of the message.</para>
|
||||||
|
/// <para>This property will only be usable if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The text body if it exists; otherwise, <c>null</c>.</value>
|
||||||
|
public BodyPartText TextBody {
|
||||||
|
get {
|
||||||
|
var multipart = Body as BodyPartMultipart;
|
||||||
|
|
||||||
|
if (multipart != null) {
|
||||||
|
BodyPartText plain;
|
||||||
|
|
||||||
|
if (TryGetMessageBody (multipart, false, out plain))
|
||||||
|
return plain;
|
||||||
|
} else {
|
||||||
|
var text = Body as BodyPartText;
|
||||||
|
|
||||||
|
if (text != null && text.IsPlain)
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the html body part of the message if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the <c>text/html</c> body part of the message.</para>
|
||||||
|
/// <para>This property will only be usable if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The html body if it exists; otherwise, <c>null</c>.</value>
|
||||||
|
public BodyPartText HtmlBody {
|
||||||
|
get {
|
||||||
|
var multipart = Body as BodyPartMultipart;
|
||||||
|
|
||||||
|
if (multipart != null) {
|
||||||
|
BodyPartText html;
|
||||||
|
|
||||||
|
if (TryGetMessageBody (multipart, true, out html))
|
||||||
|
return html;
|
||||||
|
} else {
|
||||||
|
var text = Body as BodyPartText;
|
||||||
|
|
||||||
|
if (text != null && text.IsHtml)
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<BodyPartBasic> EnumerateBodyParts (BodyPart entity, bool attachmentsOnly)
|
||||||
|
{
|
||||||
|
if (entity == null)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
var multipart = entity as BodyPartMultipart;
|
||||||
|
|
||||||
|
if (multipart != null) {
|
||||||
|
foreach (var subpart in multipart.BodyParts) {
|
||||||
|
foreach (var part in EnumerateBodyParts (subpart, attachmentsOnly))
|
||||||
|
yield return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var basic = (BodyPartBasic) entity;
|
||||||
|
|
||||||
|
if (attachmentsOnly && !basic.IsAttachment)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
yield return basic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the body parts of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Traverses over the <see cref="Body"/>, enumerating all of the
|
||||||
|
/// <see cref="BodyPartBasic"/> objects.</para>
|
||||||
|
/// <para>This property will only be usable if either the
|
||||||
|
/// <see cref="MessageSummaryItems.Body"/> flag or the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The body parts.</value>
|
||||||
|
public IEnumerable<BodyPartBasic> BodyParts {
|
||||||
|
get { return EnumerateBodyParts (Body, false); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the attachments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Traverses over the <see cref="Body"/>, enumerating all of the
|
||||||
|
/// <see cref="BodyPartBasic"/> objects that have a <c>Content-Disposition</c>
|
||||||
|
/// header set to <c>"attachment"</c>.</para>
|
||||||
|
/// <para>This property will only be usable if the
|
||||||
|
/// <see cref="MessageSummaryItems.BodyStructure"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The attachments.</value>
|
||||||
|
public IEnumerable<BodyPartBasic> Attachments {
|
||||||
|
get { return EnumerateBodyParts (Body, true); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the preview text of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The preview text is a short snippet of the beginning of the message
|
||||||
|
/// text, typically shown in a mail client's message list to provide the user
|
||||||
|
/// with a sense of what the message is about.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.PreviewText"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The preview text.</value>
|
||||||
|
public string PreviewText {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the envelope of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The envelope of a message contains information such as the
|
||||||
|
/// date the message was sent, the subject of the message,
|
||||||
|
/// the sender of the message, who the message was sent to,
|
||||||
|
/// which message(s) the message may be in reply to,
|
||||||
|
/// and the message id.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Envelope"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The envelope of the message.</value>
|
||||||
|
public Envelope Envelope {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the normalized subject.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A normalized Subject header value where prefixes such as
|
||||||
|
/// "Re:", "Re[#]:", etc have been pruned.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The normalized subject.</value>
|
||||||
|
public string NormalizedSubject {
|
||||||
|
get {
|
||||||
|
UpdateThreadableSubject ();
|
||||||
|
|
||||||
|
return normalizedSubject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether or not the message is a reply.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This value should be based on whether the message subject contained any "Re:" or "Fwd:" prefixes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the message is a reply; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsReply {
|
||||||
|
get {
|
||||||
|
UpdateThreadableSubject ();
|
||||||
|
|
||||||
|
return threadableReplyDepth != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Date header value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the Date header value. If the Date header is not present, the arrival date is used.
|
||||||
|
/// If neither are known, <see cref="System.DateTimeOffset.MinValue"/> is returned.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The date.</value>
|
||||||
|
public DateTimeOffset Date {
|
||||||
|
get { return Envelope?.Date ?? InternalDate ?? DateTimeOffset.MinValue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message flags, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message flags, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Flags"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message flags.</value>
|
||||||
|
public MessageFlags? Flags {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user-defined message flags, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the user-defined message flags, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Flags"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The user-defined message flags.</value>
|
||||||
|
public HashSet<string> Keywords {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user-defined message flags, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the user-defined message flags, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Flags"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The user-defined message flags.</value>
|
||||||
|
[Obsolete ("Use Keywords instead.")]
|
||||||
|
public HashSet<string> UserFlags {
|
||||||
|
get { return Keywords; }
|
||||||
|
set { Keywords = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message annotations, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message annotations, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Annotations"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message annotations.</value>
|
||||||
|
public IList<Annotation> Annotations {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of headers, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the list of headers, if available.</para>
|
||||||
|
/// <para>This property will only be set if <see cref="MessageSummaryItems.Headers"/>
|
||||||
|
/// is specified in a call to one of the
|
||||||
|
/// <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods or specific headers are requested via a one of the Fetch or FetchAsync methods
|
||||||
|
/// that accept list of specific headers to request for each message such as
|
||||||
|
/// <see cref="IMailFolder.Fetch(System.Collections.Generic.IList<UniqueId>,MessageSummaryItems,System.Collections.Generic.IEnumerable<MimeKit.HeaderId>,System.Threading.CancellationToken)"/>.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The list of headers.</value>
|
||||||
|
public HeaderList Headers {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the internal date of the message (i.e. the "received" date), if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the internal date of the message (i.e. the "received" date), if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.InternalDate"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The internal date of the message.</value>
|
||||||
|
public DateTimeOffset? InternalDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the size of the message, in bytes, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the size of the message, in bytes, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.Size"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The size of the message.</value>
|
||||||
|
public uint? Size {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the mod-sequence value for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the mod-sequence value for the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.ModSeq"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mod-sequence value.</value>
|
||||||
|
public ulong? ModSeq {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message-ids that the message references, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message-ids that the message references, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.References"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The references.</value>
|
||||||
|
public MessageIdList References {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the globally unique identifier for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the globally unique identifier of the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.EmailId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <note type="info">This property maps to the <c>EMAILID</c> value defined in the
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The globally unique message identifier.</value>
|
||||||
|
public string EmailId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the globally unique identifier for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the globally unique identifier of the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.EmailId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <note type="info">This property maps to the <c>EMAILID</c> value defined in the
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The globally unique message identifier.</value>
|
||||||
|
[Obsolete ("Use EmailId instead.")]
|
||||||
|
public string Id {
|
||||||
|
get { return EmailId; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the globally unique thread identifier for the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the globally unique thread identifier for the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.ThreadId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <note type="info">This property maps to the <c>THREADID</c> value defined in the
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The globally unique thread identifier.</value>
|
||||||
|
public string ThreadId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique identifier of the message, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the unique identifier of the message, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.UniqueId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The uid of the message.</value>
|
||||||
|
public UniqueId UniqueId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the index of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the index of the message.</para>
|
||||||
|
/// <para>This property is always set.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The index of the message.</value>
|
||||||
|
public int Index {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region GMail extension properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the GMail message identifier, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the GMail message identifier, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.GMailMessageId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The GMail message identifier.</value>
|
||||||
|
public ulong? GMailMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the GMail thread identifier, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the GMail thread identifier, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.GMailThreadId"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The GMail thread identifier.</value>
|
||||||
|
public ulong? GMailThreadId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of GMail labels, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the list of GMail labels, if available.</para>
|
||||||
|
/// <para>This property will only be set if the
|
||||||
|
/// <see cref="MessageSummaryItems.GMailLabels"/> flag is passed to
|
||||||
|
/// one of the <a href="Overload_MailKit_IMailFolder_Fetch.htm">Fetch</a>
|
||||||
|
/// or <a href="Overload_MailKit_IMailFolder_FetchAsync.htm">FetchAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The GMail labels.</value>
|
||||||
|
public IList<string> GMailLabels {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// MessageSummaryFetchedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when a message summary has been fetched from a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when a message summary has been fetched from a folder.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageSummaryFetchedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageSummaryFetchedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageSummaryFetchedEventArgs"/>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The message summary.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="message"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public MessageSummaryFetchedEventArgs (IMessageSummary message)
|
||||||
|
{
|
||||||
|
if (message == null)
|
||||||
|
throw new ArgumentNullException (nameof (message));
|
||||||
|
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the message summary.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the message summary.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message summary.</value>
|
||||||
|
public IMessageSummary Message {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,222 @@
|
||||||
|
//
|
||||||
|
// FetchFlags.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A bitfield of <see cref="MessageSummary"/> fields.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <see cref="MessageSummaryItems"/> are used to specify which properties
|
||||||
|
/// of <see cref="MessageSummary"/> should be populated by calls to
|
||||||
|
/// <see cref="IMailFolder.Fetch(System.Collections.Generic.IList<UniqueId>, MessageSummaryItems, System.Threading.CancellationToken)"/>,
|
||||||
|
/// <see cref="IMailFolder.Fetch(System.Collections.Generic.IList<int>, MessageSummaryItems, System.Threading.CancellationToken)"/>, or
|
||||||
|
/// <see cref="IMailFolder.Fetch(int, int, MessageSummaryItems, System.Threading.CancellationToken)"/>.
|
||||||
|
/// </remarks>
|
||||||
|
[Flags]
|
||||||
|
public enum MessageSummaryItems {
|
||||||
|
/// <summary>
|
||||||
|
/// Don't fetch any summary items.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.Annotations"/>.</para>
|
||||||
|
/// <para>Fetches all <c>ANNOATION</c> values as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5257">rfc5257</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
Annotations = 1 << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.Body"/>.</para>
|
||||||
|
/// <para>Fetches the <c>BODY</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// <note type="note">Unlike <see cref="BodyStructure"/>, <c>Body</c> will not populate the
|
||||||
|
/// <see cref="BodyPart.ContentType"/> parameters nor will it populate the
|
||||||
|
/// <see cref="BodyPartBasic.ContentDisposition"/>, <see cref="BodyPartBasic.ContentLanguage"/>
|
||||||
|
/// or <see cref="BodyPartBasic.ContentLocation"/> properties of each <see cref="BodyPartBasic"/>
|
||||||
|
/// body part. This makes <c>Body</c> far less useful than <c>BodyStructure</c> especially when
|
||||||
|
/// it is desirable to determine whether or not a body part is an attachment.</note>
|
||||||
|
/// </summary>
|
||||||
|
Body = 1 << 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.Body"/> (but with more details than <see cref="Body"/>).</para>
|
||||||
|
/// <para>Fetches the <c>BODYSTRUCTURE</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// <note type="note">Unlike <see cref="Body"/>, <c>BodyStructure</c> will also populate the
|
||||||
|
/// <see cref="BodyPart.ContentType"/> parameters as well as the
|
||||||
|
/// <see cref="BodyPartBasic.ContentDisposition"/>, <see cref="BodyPartBasic.ContentLanguage"/>
|
||||||
|
/// and <see cref="BodyPartBasic.ContentLocation"/> properties of each <see cref="BodyPartBasic"/>
|
||||||
|
/// body part. The <c>Content-Disposition</c> information is especially important when trying to
|
||||||
|
/// determine whether or not a body part is an attachment, for example.</note>
|
||||||
|
/// </summary>
|
||||||
|
BodyStructure = 1 << 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.Envelope"/>.</para>
|
||||||
|
/// <para>Fetches the <c>ENVELOPE</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
Envelope = 1 << 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.Flags"/>.</para>
|
||||||
|
/// <para>Fetches the <c>FLAGS</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
Flags = 1 << 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.InternalDate"/>.</para>
|
||||||
|
/// <para>Fetches the <c>INTERNALDATE</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
InternalDate = 1 << 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.Size"/>.</para>
|
||||||
|
/// <para>Fetches the <c>RFC822.SIZE</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
Size = 1 << 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.ModSeq"/>.</para>
|
||||||
|
/// <para>Fetches the <c>MODSEQ</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc4551">rfc4551</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
ModSeq = 1 << 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetch the <see cref="IMessageSummary.References"/>.
|
||||||
|
/// </summary>
|
||||||
|
References = 1 << 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.UniqueId"/>.</para>
|
||||||
|
/// <para>Fetches the <c>UID</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
UniqueId = 1 << 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para></para>Fetch the <see cref="IMessageSummary.EmailId"/>.
|
||||||
|
/// <para>Fetches the <c>EMAILID</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">rfc8474</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
EmailId = 1 << 10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para></para>Fetch the <see cref="IMessageSummary.EmailId"/>.
|
||||||
|
/// <para>Fetches the <c>EMAILID</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">rfc8474</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete ("Use EmailId instead.")]
|
||||||
|
Id = EmailId,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.ThreadId"/>.</para>
|
||||||
|
/// <para>Fetches the <c>THREADID</c> value as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc8474">rfc8474</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
ThreadId = 1 << 11,
|
||||||
|
|
||||||
|
#region GMail extension items
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.GMailMessageId"/>.</para>
|
||||||
|
/// <para>Fetches the <c>X-GM-MSGID</c> value as defined in Google's
|
||||||
|
/// <a href="https://developers.google.com/gmail/imap/imap-extensions">IMAP extensions</a>
|
||||||
|
/// documentation.</para>
|
||||||
|
/// </summary>
|
||||||
|
GMailMessageId = 1 << 12,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.GMailThreadId"/>.</para>
|
||||||
|
/// <para>Fetches the <c>X-GM-THRID</c> value as defined in Google's
|
||||||
|
/// <a href="https://developers.google.com/gmail/imap/imap-extensions">IMAP extensions</a>
|
||||||
|
/// documentation.</para>
|
||||||
|
/// </summary>
|
||||||
|
GMailThreadId = 1 << 13,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.GMailLabels"/>.</para>
|
||||||
|
/// <para>Fetches the <c>X-GM-LABELS</c> value as defined in Google's
|
||||||
|
/// <a href="https://developers.google.com/gmail/imap/imap-extensions">IMAP extensions</a>
|
||||||
|
/// documentation.</para>
|
||||||
|
/// </summary>
|
||||||
|
GMailLabels = 1 << 14,
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the the complete list of <see cref="IMessageSummary.Headers"/> for each message.</para>
|
||||||
|
/// </summary>
|
||||||
|
Headers = 1 << 15,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Fetch the <see cref="IMessageSummary.PreviewText"/>.</para>
|
||||||
|
/// <note type="note">This property is quite expensive to calculate because it is not an
|
||||||
|
/// item that is cached on the IMAP server. Instead, MailKit must download a hunk of the
|
||||||
|
/// message body so that it can decode and parse it in order to generate a meaningful
|
||||||
|
/// text snippet. This usually involves downloading the first 512 bytes for <c>text/plain</c>
|
||||||
|
/// message bodies and the first 16 kilobytes for <c>text/html</c> message bodies. If a
|
||||||
|
/// message contains both a <c>text/plain</c> body and a <c>text/html</c> body, then the
|
||||||
|
/// <c>text/plain</c> content is used in order to reduce network traffic.</note>
|
||||||
|
/// </summary>
|
||||||
|
PreviewText = 1 << 16,
|
||||||
|
|
||||||
|
#region Macros
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>A macro for fetching the <see cref="Envelope"/>, <see cref="Flags"/>,
|
||||||
|
/// <see cref="InternalDate"/>, and <see cref="Size"/> values.</para>
|
||||||
|
/// <para>This macro maps to the equivalent <c>ALL</c> macro as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
All = Envelope | Flags | InternalDate | Size,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>A macro for fetching the <see cref="Flags"/>, <see cref="InternalDate"/>, and
|
||||||
|
/// <see cref="Size"/> values.</para>
|
||||||
|
/// <para>This macro maps to the equivalent <c>FAST</c> macro as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
Fast = Flags | InternalDate | Size,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>A macro for fetching the <see cref="Body"/>, <see cref="Envelope"/>,
|
||||||
|
/// <see cref="Flags"/>, <see cref="InternalDate"/>, and <see cref="Size"/> values.</para>
|
||||||
|
/// <para>This macro maps to the equivalent <c>FULL</c> macro as defined in
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501">rfc3501</a>.</para>
|
||||||
|
/// </summary>
|
||||||
|
Full = Body | Envelope | Flags| InternalDate | Size,
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
//
|
||||||
|
// MessageThread.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A message thread.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A message thread.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageThread
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageThread"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new message thread node.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uid">The unique identifier of the message.</param>
|
||||||
|
public MessageThread (UniqueId? uid)
|
||||||
|
{
|
||||||
|
Children = new List<MessageThread> ();
|
||||||
|
UniqueId = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageThread"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new message thread node.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The message summary.</param>
|
||||||
|
public MessageThread (IMessageSummary message)
|
||||||
|
{
|
||||||
|
Children = new List<MessageThread> ();
|
||||||
|
if (message != null && message.UniqueId.IsValid)
|
||||||
|
UniqueId = message?.UniqueId;
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message summary, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the message summary, if available.</para>
|
||||||
|
/// <note type="note">This property will only ever be set if the <see cref="MessageThread"/>
|
||||||
|
/// was created by the <see cref="MessageThreader"/>. <see cref="MessageThread"/>s that are
|
||||||
|
/// created by any of the
|
||||||
|
/// <a href="Overload_MailKit_Net_Imap_ImapFolder_Thread.htm">Thread</a> or
|
||||||
|
/// <a href="Overload_MailKit_Net_Imap_ImapFolder_ThreadAsync.htm">ThreadAsync</a>
|
||||||
|
/// methods will always be <c>null</c>.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The message summary.</value>
|
||||||
|
public IMessageSummary Message {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique identifier of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The unique identifier may be <c>null</c> if the message is missing from the
|
||||||
|
/// <see cref="IMailFolder"/> or from the list of messages provided to the
|
||||||
|
/// <see cref="MessageThreader"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The unique identifier.</value>
|
||||||
|
public UniqueId? UniqueId {
|
||||||
|
// FIXME: this shouldn't be a nullable since we can just use UniqueId.Invalid
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the children.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Each child represents a reply to the message referenced by <see cref="UniqueId"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The children.</value>
|
||||||
|
public IList<MessageThread> Children {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,603 @@
|
||||||
|
//
|
||||||
|
// MessageThreader.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
using MailKit.Search;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Threads messages according to the algorithms defined in rfc5256.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Threads messages according to the algorithms defined in rfc5256.
|
||||||
|
/// </remarks>
|
||||||
|
public static class MessageThreader
|
||||||
|
{
|
||||||
|
internal class ThreadableNode : IMessageSummary
|
||||||
|
{
|
||||||
|
public readonly List<ThreadableNode> Children = new List<ThreadableNode> ();
|
||||||
|
public IMessageSummary Message;
|
||||||
|
public ThreadableNode Parent;
|
||||||
|
|
||||||
|
public ThreadableNode (IMessageSummary message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasParent {
|
||||||
|
get { return Parent != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasChildren {
|
||||||
|
get { return Children.Count > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMailFolder Folder => null;
|
||||||
|
|
||||||
|
public MessageSummaryItems Fields {
|
||||||
|
get { return MessageSummaryItems.UniqueId | MessageSummaryItems.Envelope | MessageSummaryItems.ModSeq | MessageSummaryItems.Size; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public BodyPart Body => null;
|
||||||
|
|
||||||
|
public BodyPartText TextBody => null;
|
||||||
|
|
||||||
|
public BodyPartText HtmlBody => null;
|
||||||
|
|
||||||
|
public IEnumerable<BodyPartBasic> BodyParts => null;
|
||||||
|
|
||||||
|
public IEnumerable<BodyPartBasic> Attachments => null;
|
||||||
|
|
||||||
|
public string PreviewText => null;
|
||||||
|
|
||||||
|
public Envelope Envelope {
|
||||||
|
get { return Message != null ? Message.Envelope : Children[0].Envelope; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string NormalizedSubject {
|
||||||
|
get { return Message != null ? Message.NormalizedSubject : Children[0].NormalizedSubject; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeOffset Date {
|
||||||
|
get { return Message != null ? Message.Date : Children[0].Date; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsReply {
|
||||||
|
get { return Message != null && Message.IsReply; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageFlags? Flags => null;
|
||||||
|
|
||||||
|
public HashSet<string> Keywords => null;
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
public HashSet<string> UserFlags => null;
|
||||||
|
|
||||||
|
public IList<Annotation> Annotations {
|
||||||
|
get { return Message != null ? Message.Annotations : Children[0].Annotations; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeaderList Headers => null;
|
||||||
|
|
||||||
|
public DateTimeOffset? InternalDate => null;
|
||||||
|
|
||||||
|
public uint? Size {
|
||||||
|
get { return Message != null ? Message.Size : Children[0].Size; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong? ModSeq {
|
||||||
|
get { return Message != null ? Message.ModSeq : Children[0].ModSeq; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageIdList References {
|
||||||
|
get { return Message != null ? Message.References : Children[0].References; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string EmailId => null;
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
public string Id => null;
|
||||||
|
|
||||||
|
public string ThreadId => null;
|
||||||
|
|
||||||
|
public UniqueId UniqueId {
|
||||||
|
get { return Message != null ? Message.UniqueId : Children[0].UniqueId; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Index {
|
||||||
|
get { return Message != null ? Message.Index : Children[0].Index; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong? GMailMessageId => null;
|
||||||
|
|
||||||
|
public ulong? GMailThreadId => null;
|
||||||
|
|
||||||
|
public IList<string> GMailLabels => null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IDictionary<string, ThreadableNode> CreateIdTable (IEnumerable<IMessageSummary> messages)
|
||||||
|
{
|
||||||
|
var ids = new Dictionary<string, ThreadableNode> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
ThreadableNode node;
|
||||||
|
|
||||||
|
foreach (var message in messages) {
|
||||||
|
if (message.Envelope == null)
|
||||||
|
throw new ArgumentException ("One or more messages is missing information needed for threading.", nameof (messages));
|
||||||
|
|
||||||
|
var id = message.Envelope.MessageId;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty (id))
|
||||||
|
id = MimeUtils.GenerateMessageId ();
|
||||||
|
|
||||||
|
if (ids.TryGetValue (id, out node)) {
|
||||||
|
if (node.Message == null) {
|
||||||
|
// a previously processed message referenced this message
|
||||||
|
node.Message = message;
|
||||||
|
} else {
|
||||||
|
// a duplicate message-id, just create a dummy id and use that
|
||||||
|
id = MimeUtils.GenerateMessageId ();
|
||||||
|
node = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
// create a new ThreadContainer for this message and add it to ids
|
||||||
|
node = new ThreadableNode (message);
|
||||||
|
ids.Add (id, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadableNode parent = null;
|
||||||
|
foreach (var reference in message.References) {
|
||||||
|
ThreadableNode referenced;
|
||||||
|
|
||||||
|
if (!ids.TryGetValue (reference, out referenced)) {
|
||||||
|
// create a dummy container for the referenced message
|
||||||
|
referenced = new ThreadableNode (null);
|
||||||
|
ids.Add (reference, referenced);
|
||||||
|
}
|
||||||
|
|
||||||
|
// chain up the references, disallowing loops
|
||||||
|
if (parent != null && referenced.Parent == null && parent != referenced && !parent.Children.Contains (referenced)) {
|
||||||
|
parent.Children.Add (referenced);
|
||||||
|
referenced.Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = referenced;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't allow loops
|
||||||
|
if (parent != null && (parent == node || node.Children.Contains (parent)))
|
||||||
|
parent = null;
|
||||||
|
|
||||||
|
if (node.HasParent) {
|
||||||
|
// unlink from our old parent
|
||||||
|
node.Parent.Children.Remove (node);
|
||||||
|
node.Parent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent != null) {
|
||||||
|
// add it as a child of our new parent
|
||||||
|
parent.Children.Add (node);
|
||||||
|
node.Parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ThreadableNode CreateRoot (IDictionary<string, ThreadableNode> ids)
|
||||||
|
{
|
||||||
|
var root = new ThreadableNode (null);
|
||||||
|
|
||||||
|
foreach (var message in ids.Values) {
|
||||||
|
if (message.Parent == null)
|
||||||
|
root.Children.Add (message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PruneEmptyContainers (ThreadableNode root)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < root.Children.Count; i++) {
|
||||||
|
var node = root.Children[i];
|
||||||
|
|
||||||
|
if (node.Message == null && node.Children.Count == 0) {
|
||||||
|
// this is an empty container with no children, nuke it.
|
||||||
|
root.Children.RemoveAt (i);
|
||||||
|
i--;
|
||||||
|
} else if (node.Message == null && node.HasChildren && (node.HasParent || node.Children.Count == 1)) {
|
||||||
|
// If the Container has no Message, but does have children, remove this container but promote
|
||||||
|
// its children to this level (that is, splice them in to the current child list.)
|
||||||
|
//
|
||||||
|
// Do not promote the children if doing so would promote them to the root set -- unless there
|
||||||
|
// is only one child, in which case, do.
|
||||||
|
root.Children.RemoveAt (i);
|
||||||
|
|
||||||
|
for (int j = 0; j < node.Children.Count; j++) {
|
||||||
|
node.Children[j].Parent = node.Parent;
|
||||||
|
root.Children.Add (node.Children[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.Children.Clear ();
|
||||||
|
i--;
|
||||||
|
} else if (node.HasChildren) {
|
||||||
|
PruneEmptyContainers (node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GroupBySubject (ThreadableNode root)
|
||||||
|
{
|
||||||
|
var subjects = new Dictionary<string, ThreadableNode> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
ThreadableNode match;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < root.Children.Count; i++) {
|
||||||
|
var current = root.Children[i];
|
||||||
|
var subject = current.NormalizedSubject;
|
||||||
|
|
||||||
|
// don't thread messages with empty subjects
|
||||||
|
if (string.IsNullOrEmpty (subject))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!subjects.TryGetValue (subject, out match) ||
|
||||||
|
(current.Message == null && match.Message != null) ||
|
||||||
|
(match.Message != null && match.Message.IsReply &&
|
||||||
|
current.Message != null && !current.Message.IsReply)) {
|
||||||
|
subjects[subject] = current;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < root.Children.Count; i++) {
|
||||||
|
var current = root.Children[i];
|
||||||
|
var subject = current.NormalizedSubject;
|
||||||
|
|
||||||
|
// don't thread messages with empty subjects
|
||||||
|
if (string.IsNullOrEmpty (subject))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
match = subjects[subject];
|
||||||
|
|
||||||
|
if (match == current)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// remove the second message with the same subject
|
||||||
|
root.Children.RemoveAt (i--);
|
||||||
|
|
||||||
|
// group these messages together...
|
||||||
|
if (match.Message == null && current.Message == null) {
|
||||||
|
// If both messages are dummies, append the current message's children
|
||||||
|
// to the children of the message in the subject table (the children of
|
||||||
|
// both messages become siblings), and then delete the current message.
|
||||||
|
match.Children.AddRange (current.Children);
|
||||||
|
} else if (match.Message == null && current.Message != null) {
|
||||||
|
// If the message in the subject table is a dummy and the current message
|
||||||
|
// is not, make the current message a child of the message in the subject
|
||||||
|
// table (a sibling of its children).
|
||||||
|
match.Children.Add (current);
|
||||||
|
} else if (current.Message.IsReply && !match.Message.IsReply) {
|
||||||
|
// If the current message is a reply or forward and the message in the
|
||||||
|
// subject table is not, make the current message a child of the message
|
||||||
|
// in the subject table (a sibling of its children).
|
||||||
|
match.Children.Add (current);
|
||||||
|
} else {
|
||||||
|
// Otherwise, create a new dummy message and make both the current message
|
||||||
|
// and the message in the subject table children of the dummy. Then replace
|
||||||
|
// the message in the subject table with the dummy message.
|
||||||
|
|
||||||
|
// Note: if we re-use the node already in the subject table and the root, then
|
||||||
|
// we won't have to insert the new dummy node at the matched node's location
|
||||||
|
var dummy = match;
|
||||||
|
|
||||||
|
// clone the message already in the subject table
|
||||||
|
match = new ThreadableNode (dummy.Message);
|
||||||
|
match.Children.AddRange (dummy.Children);
|
||||||
|
|
||||||
|
// empty out the old match node (aka the new dummy node)
|
||||||
|
dummy.Children.Clear ();
|
||||||
|
dummy.Message = null;
|
||||||
|
|
||||||
|
// now add both messages to the dummy
|
||||||
|
dummy.Children.Add (match);
|
||||||
|
dummy.Children.Add (current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetThreads (ThreadableNode root, IList<MessageThread> threads, IList<OrderBy> orderBy)
|
||||||
|
{
|
||||||
|
root.Children.Sort (orderBy);
|
||||||
|
|
||||||
|
for (int i = 0; i < root.Children.Count; i++) {
|
||||||
|
var message = root.Children[i].Message;
|
||||||
|
var thread = new MessageThread (message);
|
||||||
|
|
||||||
|
GetThreads (root.Children[i], thread.Children, orderBy);
|
||||||
|
threads.Add (thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IList<MessageThread> ThreadByReferences (IEnumerable<IMessageSummary> messages, IList<OrderBy> orderBy)
|
||||||
|
{
|
||||||
|
var threads = new List<MessageThread> ();
|
||||||
|
var ids = CreateIdTable (messages);
|
||||||
|
var root = CreateRoot (ids);
|
||||||
|
|
||||||
|
PruneEmptyContainers (root);
|
||||||
|
GroupBySubject (root);
|
||||||
|
|
||||||
|
GetThreads (root, threads, orderBy);
|
||||||
|
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IList<MessageThread> ThreadBySubject (IEnumerable<IMessageSummary> messages, IList<OrderBy> orderBy)
|
||||||
|
{
|
||||||
|
var threads = new List<MessageThread> ();
|
||||||
|
var root = new ThreadableNode (null);
|
||||||
|
|
||||||
|
foreach (var message in messages) {
|
||||||
|
if (message.Envelope == null)
|
||||||
|
throw new ArgumentException ("One or more messages is missing information needed for threading.", nameof (messages));
|
||||||
|
|
||||||
|
var node = new ThreadableNode (message);
|
||||||
|
|
||||||
|
root.Children.Add (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupBySubject (root);
|
||||||
|
|
||||||
|
GetThreads (root, threads, orderBy);
|
||||||
|
|
||||||
|
return threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Thread the messages according to the specified threading algorithm.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Thread the messages according to the specified threading algorithm.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The threaded messages.</returns>
|
||||||
|
/// <param name="messages">The messages.</param>
|
||||||
|
/// <param name="algorithm">The threading algorithm.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="messages"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="algorithm"/> is not a valid threading algorithm.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="messages"/> contains one or more items that is missing information needed for threading.
|
||||||
|
/// </exception>
|
||||||
|
public static IList<MessageThread> Thread (this IEnumerable<IMessageSummary> messages, ThreadingAlgorithm algorithm)
|
||||||
|
{
|
||||||
|
return Thread (messages, algorithm, new [] { OrderBy.Arrival });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Threads the messages according to the specified threading algorithm
|
||||||
|
/// and sorts the resulting threads by the specified ordering.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Threads the messages according to the specified threading algorithm
|
||||||
|
/// and sorts the resulting threads by the specified ordering.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The threaded messages.</returns>
|
||||||
|
/// <param name="messages">The messages.</param>
|
||||||
|
/// <param name="algorithm">The threading algorithm.</param>
|
||||||
|
/// <param name="orderBy">The requested sort ordering.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="messages"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="orderBy"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="algorithm"/> is not a valid threading algorithm.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para><paramref name="messages"/> contains one or more items that is missing information needed for threading or sorting.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="orderBy"/> is an empty list.</para>
|
||||||
|
/// </exception>
|
||||||
|
public static IList<MessageThread> Thread (this IEnumerable<IMessageSummary> messages, ThreadingAlgorithm algorithm, IList<OrderBy> orderBy)
|
||||||
|
{
|
||||||
|
if (messages == null)
|
||||||
|
throw new ArgumentNullException (nameof (messages));
|
||||||
|
|
||||||
|
if (orderBy == null)
|
||||||
|
throw new ArgumentNullException (nameof (orderBy));
|
||||||
|
|
||||||
|
if (orderBy.Count == 0)
|
||||||
|
throw new ArgumentException ("No sort order provided.", nameof (orderBy));
|
||||||
|
|
||||||
|
switch (algorithm) {
|
||||||
|
case ThreadingAlgorithm.OrderedSubject: return ThreadBySubject (messages, orderBy);
|
||||||
|
case ThreadingAlgorithm.References: return ThreadByReferences (messages, orderBy);
|
||||||
|
default: throw new ArgumentOutOfRangeException (nameof (algorithm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsForward (string subject, int index)
|
||||||
|
{
|
||||||
|
return (subject[index] == 'F' || subject[index] == 'f') &&
|
||||||
|
(subject[index + 1] == 'W' || subject[index + 1] == 'w') &&
|
||||||
|
(subject[index + 2] == 'D' || subject[index + 2] == 'd') &&
|
||||||
|
subject[index + 3] == ':';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsReply (string subject, int index)
|
||||||
|
{
|
||||||
|
return (subject[index] == 'R' || subject[index] == 'r') &&
|
||||||
|
(subject[index + 1] == 'E' || subject[index + 1] == 'e');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SkipWhiteSpace (string subject, ref int index)
|
||||||
|
{
|
||||||
|
while (index < subject.Length && char.IsWhiteSpace (subject[index]))
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsMailingListName (char c)
|
||||||
|
{
|
||||||
|
return c == '-' || c == '_' || char.IsLetterOrDigit (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SkipMailingListName (string subject, ref int index)
|
||||||
|
{
|
||||||
|
while (index < subject.Length && IsMailingListName (subject[index]))
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool SkipDigits (string subject, ref int index, out int value)
|
||||||
|
{
|
||||||
|
int startIndex = index;
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
|
||||||
|
while (index < subject.Length && char.IsDigit (subject[index])) {
|
||||||
|
value = (value * 10) + (subject[index] - '0');
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index > startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the threadable subject.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the threadable subject.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The threadable subject.</returns>
|
||||||
|
/// <param name="subject">The Subject header value.</param>
|
||||||
|
/// <param name="replyDepth">The reply depth.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="subject"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public static string GetThreadableSubject (string subject, out int replyDepth)
|
||||||
|
{
|
||||||
|
if (subject == null)
|
||||||
|
throw new ArgumentNullException (nameof (subject));
|
||||||
|
|
||||||
|
replyDepth = 0;
|
||||||
|
|
||||||
|
int endIndex = subject.Length;
|
||||||
|
int startIndex = 0;
|
||||||
|
int index, count;
|
||||||
|
int left;
|
||||||
|
|
||||||
|
do {
|
||||||
|
SkipWhiteSpace (subject, ref startIndex);
|
||||||
|
index = startIndex;
|
||||||
|
|
||||||
|
if ((left = (endIndex - index)) < 3)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (left >= 4 && IsForward (subject, index)) {
|
||||||
|
// skip over the "Fwd:" prefix
|
||||||
|
startIndex = index + 4;
|
||||||
|
replyDepth++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsReply (subject, index)) {
|
||||||
|
if (subject[index + 2] == ':') {
|
||||||
|
// skip over the "Re:" prefix
|
||||||
|
startIndex = index + 3;
|
||||||
|
replyDepth++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subject[index + 2] == '[' || subject[index + 2] == '(') {
|
||||||
|
char close = subject[index + 2] == '[' ? ']' : ')';
|
||||||
|
|
||||||
|
// skip over "Re[" or "Re("
|
||||||
|
index += 3;
|
||||||
|
|
||||||
|
// if this is followed by "###]:" or "###):", then it's a condensed "Re:"
|
||||||
|
if (SkipDigits (subject, ref index, out count) && (endIndex - index) >= 2 &&
|
||||||
|
subject[index] == close && subject[index + 1] == ':') {
|
||||||
|
startIndex = index + 2;
|
||||||
|
replyDepth += count;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (subject[index] == '[' && char.IsLetterOrDigit (subject[index + 1])) {
|
||||||
|
// possibly a mailing-list prefix
|
||||||
|
index += 2;
|
||||||
|
|
||||||
|
SkipMailingListName (subject, ref index);
|
||||||
|
|
||||||
|
if ((endIndex - index) >= 1 && subject[index] == ']') {
|
||||||
|
startIndex = index + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
// trim trailing whitespace
|
||||||
|
while (endIndex > 0 && char.IsWhiteSpace (subject[endIndex - 1]))
|
||||||
|
endIndex--;
|
||||||
|
|
||||||
|
// canonicalize the remainder of the subject, condensing multiple spaces into 1
|
||||||
|
var builder = new StringBuilder ();
|
||||||
|
bool lwsp = false;
|
||||||
|
|
||||||
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
|
if (char.IsWhiteSpace (subject[i])) {
|
||||||
|
if (!lwsp) {
|
||||||
|
builder.Append (' ');
|
||||||
|
lwsp = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.Append (subject[i]);
|
||||||
|
lwsp = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var canonicalized = builder.ToString ();
|
||||||
|
|
||||||
|
if (canonicalized.Equals ("(no subject)", StringComparison.OrdinalIgnoreCase))
|
||||||
|
canonicalized = string.Empty;
|
||||||
|
|
||||||
|
return canonicalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
//
|
||||||
|
// MessagesVanishedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when a message vanishes from a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when a message vanishes from a folder.
|
||||||
|
/// </remarks>
|
||||||
|
public class MessagesVanishedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessagesVanishedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessagesVanishedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uids">The list of unique identifiers.</param>
|
||||||
|
/// <param name="earlier">If set to <c>true</c>, the messages vanished in the past as opposed to just now.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="uids"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public MessagesVanishedEventArgs (IList<UniqueId> uids, bool earlier)
|
||||||
|
{
|
||||||
|
UniqueIds = new ReadOnlyCollection<UniqueId> (uids);
|
||||||
|
Earlier = earlier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the unique identifiers of the messages that vanished.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the unique identifiers of the messages that vanished.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The unique identifiers.</value>
|
||||||
|
public IList<UniqueId> UniqueIds {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the messages vanished in the past as opposed to just now.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether the messages vanished in the past as opposed to just now.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the messages vanished earlier; otherwise, <c>false</c>.</value>
|
||||||
|
public bool Earlier {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// Metadata.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata tag and value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A metadata tag and value.
|
||||||
|
/// </remarks>
|
||||||
|
public class Metadata
|
||||||
|
{
|
||||||
|
internal string EncodedName;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Metadata"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="Metadata"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="tag">The metadata tag.</param>
|
||||||
|
/// <param name="value">The metadata value.</param>
|
||||||
|
public Metadata (MetadataTag tag, string value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
Tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the metadata tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the metadata tag.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The metadata tag.</value>
|
||||||
|
public MetadataTag Tag {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the metadata value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the metadata value.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The metadata value.</value>
|
||||||
|
public string Value {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
//
|
||||||
|
// MetadataChangedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// Event args used when a metadata changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args used when a metadata changes.
|
||||||
|
/// </remarks>
|
||||||
|
public class MetadataChangedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.MetadataChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MetadataChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="metadata">The metadata that changed.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="metadata"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
public MetadataChangedEventArgs (Metadata metadata)
|
||||||
|
{
|
||||||
|
if (metadata == null)
|
||||||
|
throw new ArgumentNullException (nameof (metadata));
|
||||||
|
|
||||||
|
Metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the metadata that changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the metadata that changed.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The metadata.</value>
|
||||||
|
public Metadata Metadata {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
//
|
||||||
|
// MetadataCollection.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A collection of metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A collection of metadata.
|
||||||
|
/// </remarks>
|
||||||
|
public class MetadataCollection : List<Metadata>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MetadataCollection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MetadataCollection"/>
|
||||||
|
/// </remarks>
|
||||||
|
public MetadataCollection ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MetadataCollection"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MetadataCollection"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="collection">A collection of metadata.</param>
|
||||||
|
public MetadataCollection (IEnumerable<Metadata> collection) : base (collection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
//
|
||||||
|
// MetadataOptions.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A set of options to use when requesting metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A set of options to use when requesting metadata.
|
||||||
|
/// </remarks>
|
||||||
|
public class MetadataOptions
|
||||||
|
{
|
||||||
|
int depth;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.MetadataOptions"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new set of options to use when requesting metadata.
|
||||||
|
/// </remarks>
|
||||||
|
public MetadataOptions ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the depth.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>When the <see cref="Depth"/> option is specified, it extends the list of metadata tag
|
||||||
|
/// values returned by the GetMetadata() call. For each <see cref="MetadataTag"/> specified in the
|
||||||
|
/// the GetMetadata() call, the method returns the value of the specified metadata tag (if it exists),
|
||||||
|
/// plus all metadata tags below the specified entry up to the specified depth.</para>
|
||||||
|
/// <para>Three values are allowed for <see cref="Depth"/>:</para>
|
||||||
|
/// <para><c>0</c> - no entries below the specified metadata tag are returned.</para>
|
||||||
|
/// <para><c>1</c> - only entries immediately below the specified metadata tag are returned.</para>
|
||||||
|
/// <para><see cref="System.Int32.MaxValue"/> - all entries below the specified metadata tag are returned.</para>
|
||||||
|
/// <para>Thus, a depth of <c>1</c> for a tag entry of <c>"/a"</c> will match <c>"/a"</c> as well as its children
|
||||||
|
/// entries (e.g., <c>"/a/b"</c>), but will not match grandchildren entries (e.g., <c>"/a/b/c"</c>).</para>
|
||||||
|
/// <para>If the Depth option is not specified, this is the same as specifying <c>0</c>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The depth.</value>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="value"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
public int Depth {
|
||||||
|
get { return depth; }
|
||||||
|
set {
|
||||||
|
if (!(value == 0 || value == 1 || value == int.MaxValue))
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (value));
|
||||||
|
|
||||||
|
depth = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the max size of the metadata tags to request.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// When specified, the <see cref="MaxSize"/> property is used to filter the metadata tags
|
||||||
|
/// returned by the GetMetadata() call to only those with a value shorter than the max size
|
||||||
|
/// specified.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The size of the max.</value>
|
||||||
|
public uint? MaxSize {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the length of the longest metadata value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the <see cref="MaxSize"/> property is specified, once the GetMetadata() call returns,
|
||||||
|
/// the <see cref="LongEntries"/> property will be set to the length of the longest metadata
|
||||||
|
/// value that exceeded the <see cref="MaxSize"/> limit, otherwise a value of <c>0</c> will
|
||||||
|
/// be set.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The length of the longest metadata value that exceeded the max size.</value>
|
||||||
|
public uint LongEntries {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,156 @@
|
||||||
|
//
|
||||||
|
// MetadataTag.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit {
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata tag.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// A metadata tag.
|
||||||
|
/// </remarks>
|
||||||
|
public struct MetadataTag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata tag for specifying the contact information for the server administrator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get the contact information of the administrator on a
|
||||||
|
/// <see cref="IMailStore"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly MetadataTag SharedAdmin = new MetadataTag ("/shared/admin");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata tag for private comments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a private comment on a <see cref="IMailFolder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly MetadataTag PrivateComment = new MetadataTag ("/private/comment");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata tag for shared comments.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set a shared comment on a <see cref="IMailStore"/>
|
||||||
|
/// or <see cref="IMailFolder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly MetadataTag SharedComment = new MetadataTag ("/shared/comment");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A metadata tag for specifying the special use of a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Used to get or set the special use of a <see cref="IMailFolder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly MetadataTag PrivateSpecialUse = new MetadataTag ("/private/specialuse");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MetadataTag"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MetadataTag"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="id">The metadata tag identifier.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="id"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="id"/> is an empty string.
|
||||||
|
/// </exception>
|
||||||
|
public MetadataTag (string id)
|
||||||
|
{
|
||||||
|
if (id == null)
|
||||||
|
throw new ArgumentNullException (nameof (id));
|
||||||
|
|
||||||
|
if (id.Length == 0)
|
||||||
|
throw new ArgumentException ("A metadata tag identifier cannot be empty.");
|
||||||
|
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the metadata tag identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the metadata tag identifier.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The metadata tag identifier.</value>
|
||||||
|
public string Id {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determine whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.MetadataTag"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Determines whether the specified <see cref="System.Object"/> is equal to the current <see cref="MailKit.MetadataTag"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="obj">The <see cref="System.Object"/> to compare with the current <see cref="MailKit.MetadataTag"/>.</param>
|
||||||
|
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to the current
|
||||||
|
/// <see cref="MailKit.MetadataTag"/>; otherwise, <c>false</c>.</returns>
|
||||||
|
public override bool Equals (object obj)
|
||||||
|
{
|
||||||
|
return obj is MetadataTag && ((MetadataTag) obj).Id == Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.MetadataTag"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serves as a hash function for a <see cref="MailKit.MetadataTag"/> object.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A hash code for this instance that is suitable for use in hashing algorithms and data structures such as a hash table.</returns>
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return Id.GetHashCode ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.MetadataTag"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Returns a <see cref="System.String"/> that represents the current <see cref="MailKit.MetadataTag"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A <see cref="System.String"/> that represents the current <see cref="MailKit.MetadataTag"/>.</returns>
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
return Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static MetadataTag Create (string id)
|
||||||
|
{
|
||||||
|
switch (id) {
|
||||||
|
case "/shared/admin": return SharedAdmin;
|
||||||
|
case "/private/comment": return PrivateComment;
|
||||||
|
case "/shared/comment": return SharedComment;
|
||||||
|
case "/private/specialuse": return PrivateSpecialUse;
|
||||||
|
default: return new MetadataTag (id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
//
|
||||||
|
// ModSeqChangedEventArgs.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event args for the <see cref="IMailFolder.ModSeqChanged"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Event args for the <see cref="IMailFolder.ModSeqChanged"/> event.
|
||||||
|
/// </remarks>
|
||||||
|
public class ModSeqChangedEventArgs : MessageEventArgs
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.ModSeqChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ModSeqChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
internal ModSeqChangedEventArgs (int index) : base (index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.MessageFlagsChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MessageFlagsChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
public ModSeqChangedEventArgs (int index, ulong modseq) : base (index)
|
||||||
|
{
|
||||||
|
ModSeq = modseq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.ModSeqChangedEventArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ModSeqChangedEventArgs"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="index">The message index.</param>
|
||||||
|
/// <param name="uid">The unique id of the message.</param>
|
||||||
|
/// <param name="modseq">The modification sequence value.</param>
|
||||||
|
public ModSeqChangedEventArgs (int index, UniqueId uid, ulong modseq) : base (index, uid)
|
||||||
|
{
|
||||||
|
ModSeq = modseq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the updated mod-sequence value of the message.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the updated mod-sequence value of the message.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mod-sequence value.</value>
|
||||||
|
public ulong ModSeq {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,965 @@
|
||||||
|
//
|
||||||
|
// AsyncImapClient.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MailKit.Security;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap
|
||||||
|
{
|
||||||
|
public partial class ImapClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable compression over the IMAP connection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously enables compression over the IMAP connection.</para>
|
||||||
|
/// <para>If the IMAP server supports the <see cref="ImapCapabilities.Compress"/> extension,
|
||||||
|
/// it is possible at any point after connecting to enable compression to reduce network
|
||||||
|
/// bandwidth usage. Ideally, this method should be called before authenticating.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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.InvalidOperationException">
|
||||||
|
/// Compression must be enabled before a folder has been selected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the COMPRESS 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 COMPRESS command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public Task CompressAsync (CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return CompressAsync (true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable the QRESYNC feature.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Enables the <a href="https://tools.ietf.org/html/rfc5162">QRESYNC</a> feature.</para>
|
||||||
|
/// <para>The QRESYNC extension improves resynchronization performance of folders by
|
||||||
|
/// querying the IMAP server for a list of changes when the folder is opened using the
|
||||||
|
/// <see cref="ImapFolder.Open(FolderAccess,uint,ulong,System.Collections.Generic.IList<UniqueId>,System.Threading.CancellationToken)"/>
|
||||||
|
/// method.</para>
|
||||||
|
/// <para>If this feature is enabled, the <see cref="MailFolder.MessageExpunged"/> event is replaced
|
||||||
|
/// with the <see cref="MailFolder.MessagesVanished"/> event.</para>
|
||||||
|
/// <para>This method needs to be called immediately after calling one of the
|
||||||
|
/// <a href="Overload_MailKit_Net_Imap_ImapClient_Authenticate.htm">Authenticate</a> methods, before
|
||||||
|
/// opening any folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Quick resynchronization needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the QRESYNC 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 ENABLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task EnableQuickResyncAsync (CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return EnableQuickResyncAsync (true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable the UTF8=ACCEPT extension.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Enables the <a href="https://tools.ietf.org/html/rfc6855">UTF8=ACCEPT</a> extension.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// UTF8=ACCEPT needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the UTF8=ACCEPT 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 ENABLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public Task EnableUTF8Async (CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return EnableUTF8Async (true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously authenticate using the specified SASL mechanism.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Authenticates using the specified SASL mechanism.</para>
|
||||||
|
/// <para>For a list of available SASL authentication mechanisms supported by the server,
|
||||||
|
/// check the <see cref="AuthenticationMechanisms"/> property after the service has been
|
||||||
|
/// connected.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="mechanism">The SASL mechanism.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="mechanism"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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.InvalidOperationException">
|
||||||
|
/// The <see cref="ImapClient"/> is already authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MailKit.Security.AuthenticationException">
|
||||||
|
/// Authentication using the supplied credentials has failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MailKit.Security.SaslException">
|
||||||
|
/// A SASL authentication error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// An IMAP command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task AuthenticateAsync (SaslMechanism mechanism, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return AuthenticateAsync (mechanism, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously authenticate using the supplied credentials.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>If the IMAP server supports one or more SASL authentication mechanisms,
|
||||||
|
/// then the SASL mechanisms that both the client and server support are tried
|
||||||
|
/// in order of greatest security to weakest security. Once a SASL
|
||||||
|
/// authentication mechanism is found that both client and server support,
|
||||||
|
/// the credentials are used to authenticate.</para>
|
||||||
|
/// <para>If the server does not support SASL or if no common SASL mechanisms
|
||||||
|
/// can be found, then LOGIN command is used as a fallback.</para>
|
||||||
|
/// <note type="tip">To prevent the usage of certain authentication mechanisms,
|
||||||
|
/// simply remove them from the <see cref="AuthenticationMechanisms"/> hash set
|
||||||
|
/// before calling this method.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="encoding">The text encoding to use for the user's credentials.</param>
|
||||||
|
/// <param name="credentials">The user's credentials.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="encoding"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="credentials"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <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.InvalidOperationException">
|
||||||
|
/// The <see cref="ImapClient"/> is already authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MailKit.Security.AuthenticationException">
|
||||||
|
/// Authentication using the supplied credentials has failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MailKit.Security.SaslException">
|
||||||
|
/// A SASL authentication error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// An IMAP command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task AuthenticateAsync (Encoding encoding, ICredentials credentials, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return AuthenticateAsync (encoding, credentials, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously establish a connection to the specified IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Establishes a connection to the specified IMAP or IMAP/S server.</para>
|
||||||
|
/// <para>If the <paramref name="port"/> has a value of <c>0</c>, then the
|
||||||
|
/// <paramref name="options"/> parameter is used to determine the default port to
|
||||||
|
/// connect to. The default port used with <see cref="SecureSocketOptions.SslOnConnect"/>
|
||||||
|
/// is <c>993</c>. All other values will use a default port of <c>143</c>.</para>
|
||||||
|
/// <para>If the <paramref name="options"/> has a value of
|
||||||
|
/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
|
||||||
|
/// to determine the default security options. If the <paramref name="port"/> has a value
|
||||||
|
/// of <c>993</c>, then the default options used will be
|
||||||
|
/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
|
||||||
|
/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
|
||||||
|
/// <para>Once a connection is established, properties such as
|
||||||
|
/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
|
||||||
|
/// populated.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadMessages"/>
|
||||||
|
/// </example>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="host">The host name to connect to.</param>
|
||||||
|
/// <param name="port">The port to connect to. If the specified port is <c>0</c>, then the default port will be used.</param>
|
||||||
|
/// <param name="options">The secure socket options to when connecting.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="host"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="port"/> is not between <c>0</c> and <c>65535</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// The <paramref name="host"/> is a zero-length string.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="ImapClient"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// The <see cref="ImapClient"/> is already connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <paramref name="options"/> was set to
|
||||||
|
/// <see cref="MailKit.Security.SecureSocketOptions.StartTls"/>
|
||||||
|
/// and the IMAP server does not support the STARTTLS extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.Net.Sockets.SocketException">
|
||||||
|
/// A socket error occurred trying to connect to the remote host.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="SslHandshakeException">
|
||||||
|
/// An error occurred during the SSL/TLS negotiations.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// An IMAP command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task ConnectAsync (string host, int port = 0, SecureSocketOptions options = SecureSocketOptions.Auto, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return ConnectAsync (host, port, options, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously establish a connection to the specified IMAP or IMAP/S server using the provided socket.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Establishes a connection to the specified IMAP or IMAP/S server using
|
||||||
|
/// the provided socket.</para>
|
||||||
|
/// <para>If the <paramref name="options"/> has a value of
|
||||||
|
/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
|
||||||
|
/// to determine the default security options. If the <paramref name="port"/> has a value
|
||||||
|
/// of <c>993</c>, then the default options used will be
|
||||||
|
/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
|
||||||
|
/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
|
||||||
|
/// <para>Once a connection is established, properties such as
|
||||||
|
/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
|
||||||
|
/// populated.</para>
|
||||||
|
/// <note type="info">With the exception of using the <paramref name="port"/> to determine the
|
||||||
|
/// default <see cref="SecureSocketOptions"/> to use when the <paramref name="options"/> value
|
||||||
|
/// is <see cref="SecureSocketOptions.Auto"/>, the <paramref name="host"/> and
|
||||||
|
/// <paramref name="port"/> parameters are only used for logging purposes.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="socket">The socket to use for the connection.</param>
|
||||||
|
/// <param name="host">The host name to connect to.</param>
|
||||||
|
/// <param name="port">The port to connect to. If the specified port is <c>0</c>, then the default port will be used.</param>
|
||||||
|
/// <param name="options">The secure socket options to when connecting.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="socket"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="host"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="port"/> is not between <c>0</c> and <c>65535</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para><paramref name="socket"/> is not connected.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// The <paramref name="host"/> is a zero-length string.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="ImapClient"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// The <see cref="ImapClient"/> is already connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <paramref name="options"/> was set to
|
||||||
|
/// <see cref="MailKit.Security.SecureSocketOptions.StartTls"/>
|
||||||
|
/// and the IMAP server does not support the STARTTLS extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="SslHandshakeException">
|
||||||
|
/// An error occurred during the SSL/TLS negotiations.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// An IMAP command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task ConnectAsync (Socket socket, string host, int port = 0, SecureSocketOptions options = SecureSocketOptions.Auto, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return ConnectAsync (socket, host, port, options, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously establish a connection to the specified IMAP or IMAP/S server using the provided stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Establishes a connection to the specified IMAP or IMAP/S server using
|
||||||
|
/// the provided stream.</para>
|
||||||
|
/// <para>If the <paramref name="options"/> has a value of
|
||||||
|
/// <see cref="SecureSocketOptions.Auto"/>, then the <paramref name="port"/> is used
|
||||||
|
/// to determine the default security options. If the <paramref name="port"/> has a value
|
||||||
|
/// of <c>993</c>, then the default options used will be
|
||||||
|
/// <see cref="SecureSocketOptions.SslOnConnect"/>. All other values will use
|
||||||
|
/// <see cref="SecureSocketOptions.StartTlsWhenAvailable"/>.</para>
|
||||||
|
/// <para>Once a connection is established, properties such as
|
||||||
|
/// <see cref="AuthenticationMechanisms"/> and <see cref="Capabilities"/> will be
|
||||||
|
/// populated.</para>
|
||||||
|
/// <note type="info">With the exception of using the <paramref name="port"/> to determine the
|
||||||
|
/// default <see cref="SecureSocketOptions"/> to use when the <paramref name="options"/> value
|
||||||
|
/// is <see cref="SecureSocketOptions.Auto"/>, the <paramref name="host"/> and
|
||||||
|
/// <paramref name="port"/> parameters are only used for logging purposes.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="stream">The stream to use for the connection.</param>
|
||||||
|
/// <param name="host">The host name to connect to.</param>
|
||||||
|
/// <param name="port">The port to connect to. If the specified port is <c>0</c>, then the default port will be used.</param>
|
||||||
|
/// <param name="options">The secure socket options to when connecting.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="stream"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="host"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="port"/> is not between <c>0</c> and <c>65535</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// The <paramref name="host"/> is a zero-length string.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="ImapClient"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// The <see cref="ImapClient"/> is already connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <paramref name="options"/> was set to
|
||||||
|
/// <see cref="MailKit.Security.SecureSocketOptions.StartTls"/>
|
||||||
|
/// and the IMAP server does not support the STARTTLS extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="SslHandshakeException">
|
||||||
|
/// An error occurred during the SSL/TLS negotiations.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// An IMAP command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
public override Task ConnectAsync (Stream stream, string host, int port = 0, SecureSocketOptions options = SecureSocketOptions.Auto, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return ConnectAsync (stream, host, port, options, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously disconnect the service.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If <paramref name="quit"/> is <c>true</c>, a <c>LOGOUT</c> command will be issued in order to disconnect cleanly.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadMessages"/>
|
||||||
|
/// </example>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="quit">If set to <c>true</c>, a <c>LOGOUT</c> command will be issued in order to disconnect cleanly.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="ImapClient"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
public override Task DisconnectAsync (bool quit, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return DisconnectAsync (quit, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously ping the IMAP server to keep the connection alive.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <c>NOOP</c> command is typically used to keep the connection with the IMAP server
|
||||||
|
/// alive. When a client goes too long (typically 30 minutes) without sending any commands to the
|
||||||
|
/// IMAP server, the IMAP server will close the connection with the client, forcing the client to
|
||||||
|
/// reconnect before it can send any more commands.</para>
|
||||||
|
/// <para>The <c>NOOP</c> command also provides a great way for a client to check for new
|
||||||
|
/// messages.</para>
|
||||||
|
/// <para>When the IMAP server receives a <c>NOOP</c> command, it will reply to the client with a
|
||||||
|
/// list of pending updates such as <c>EXISTS</c> and <c>RECENT</c> counts on the currently
|
||||||
|
/// selected folder. To receive these notifications, subscribe to the
|
||||||
|
/// <see cref="MailFolder.CountChanged"/> and <see cref="MailFolder.RecentChanged"/> events,
|
||||||
|
/// respectively.</para>
|
||||||
|
/// <para>For more information about the <c>NOOP</c> command, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501#section-6.1.2">rfc3501</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapIdleExample.cs"/>
|
||||||
|
/// </example>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </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 NOOP command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
public override Task NoOpAsync (CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return NoOpAsync (true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously toggle the <see cref="ImapClient"/> into the IDLE state.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>When a client enters the IDLE state, the IMAP server will send
|
||||||
|
/// events to the client as they occur on the selected folder. These events
|
||||||
|
/// may include notifications of new messages arriving, expunge notifications,
|
||||||
|
/// flag changes, etc.</para>
|
||||||
|
/// <para>Due to the nature of the IDLE command, a folder must be selected
|
||||||
|
/// before a client can enter into the IDLE state. This can be done by
|
||||||
|
/// opening a folder using
|
||||||
|
/// <see cref="MailKit.MailFolder.Open(FolderAccess,System.Threading.CancellationToken)"/>
|
||||||
|
/// or any of the other variants.</para>
|
||||||
|
/// <para>While the IDLE command is running, no other commands may be issued until the
|
||||||
|
/// <paramref name="doneToken"/> is cancelled.</para>
|
||||||
|
/// <note type="note">It is especially important to cancel the <paramref name="doneToken"/>
|
||||||
|
/// before cancelling the <paramref name="cancellationToken"/> when using SSL or TLS due to
|
||||||
|
/// the fact that <see cref="System.Net.Security.SslStream"/> cannot be polled.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="doneToken">The cancellation token used to return to the non-idle state.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="doneToken"/> must be cancellable (i.e. <see cref="System.Threading.CancellationToken.None"/> cannot be used).
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// A <see cref="ImapFolder"/> has not been opened.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the IDLE 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 IDLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
public Task IdleAsync (CancellationToken doneToken, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return IdleAsync (doneToken, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously request the specified notification events from the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <a href="https://tools.ietf.org/html/rfc5465">NOTIFY</a> command is used to expand
|
||||||
|
/// which notifications the client wishes to be notified about, including status notifications
|
||||||
|
/// about folders other than the currently selected folder. It can also be used to automatically
|
||||||
|
/// FETCH information about new messages that have arrived in the currently selected folder.</para>
|
||||||
|
/// <para>This, combined with <see cref="IdleAsync(CancellationToken, CancellationToken)"/>,
|
||||||
|
/// can be used to get instant notifications for changes to any of the specified folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="status"><c>true</c> if the server should immediately notify the client of the
|
||||||
|
/// selected folder's status; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="eventGroups">The specific event groups that the client would like to receive notifications for.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="eventGroups"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="eventGroups"/> is empty.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// One or more <see cref="ImapEventGroup"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the NOTIFY 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 NOTIFY command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
public Task NotifyAsync (bool status, IList<ImapEventGroup> eventGroups, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return NotifyAsync (status, eventGroups, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously disable any previously requested notification events from the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Disables any notification events requested in a prior call to
|
||||||
|
/// <see cref="NotifyAsync(bool, IList{ImapEventGroup}, CancellationToken)"/>.
|
||||||
|
/// request.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the NOTIFY 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 NOTIFY command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
public Task DisableNotifyAsync (CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return DisableNotifyAsync (true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get all of the folders within the specified namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets all of the folders within the specified namespace.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folders.</returns>
|
||||||
|
/// <param name="namespace">The namespace.</param>
|
||||||
|
/// <param name="items">The status items to pre-populate.</param>
|
||||||
|
/// <param name="subscribedOnly">If set to <c>true</c>, only subscribed folders will be listed.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="namespace"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The namespace folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied to the LIST or LSUB command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<IList<IMailFolder>> GetFoldersAsync (FolderNamespace @namespace, StatusItems items = StatusItems.None, bool subscribedOnly = false, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetFoldersAsync (@namespace, items, subscribedOnly, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the folder for the specified path.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder for the specified path.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The folder.</returns>
|
||||||
|
/// <param name="path">The folder path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="path"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotFoundException">
|
||||||
|
/// The folder could not be found.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied to the IDLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
public override async Task<IMailFolder> GetFolderAsync (string path, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException (nameof (path));
|
||||||
|
|
||||||
|
CheckDisposed ();
|
||||||
|
CheckConnected ();
|
||||||
|
CheckAuthenticated ();
|
||||||
|
|
||||||
|
return await engine.GetFolderAsync (path, true, cancellationToken).ConfigureAwait (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata value.</returns>
|
||||||
|
/// <param name="tag">The metadata tag.</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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the METADATA or METADATA-SERVER 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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<string> GetMetadataAsync (MetadataTag tag, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetMetadataAsync (tag, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The requested metadata.</returns>
|
||||||
|
/// <param name="options">The metadata options.</param>
|
||||||
|
/// <param name="tags">The metadata tags.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="options"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="tags"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the METADATA or METADATA-SERVER 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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<MetadataCollection> GetMetadataAsync (MetadataOptions options, IEnumerable<MetadataTag> tags, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return GetMetadataAsync (options, tags, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously gets the specified metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sets the specified metadata.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="metadata">The metadata.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="metadata"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the METADATA or METADATA-SERVER 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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task SetMetadataAsync (MetadataCollection metadata, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return SetMetadataAsync (metadata, true, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,628 @@
|
||||||
|
//
|
||||||
|
// IImapClient.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for an IMAP client.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Implemented by <see cref="MailKit.Net.Imap.ImapClient"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public interface IImapClient : IMailStore
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the capabilities supported by the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The capabilities will not be known until a successful connection has been made via one of
|
||||||
|
/// the <a href="Overload_MailKit_Net_Imap_ImapClient_Connect.htm">Connect</a> methods and may
|
||||||
|
/// change as a side-effect of calling one of the
|
||||||
|
/// <a href="Overload_MailKit_Net_Imap_ImapClient_Authenticate.htm">Authenticate</a>
|
||||||
|
/// methods.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The capabilities.</value>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// Capabilities cannot be enabled, they may only be disabled.
|
||||||
|
/// </exception>
|
||||||
|
ImapCapabilities Capabilities { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the maximum size of a message that can be appended to a folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the maximum size of a message, in bytes, that can be appended to a folder.</para>
|
||||||
|
/// <note type="note">If the value is not set, then the limit is unspecified.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The append limit.</value>
|
||||||
|
uint? AppendLimit { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the internationalization level supported by the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the internationalization level supported by the IMAP server.</para>
|
||||||
|
/// <para>For more information, see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc5255#section-4">section 4 of rfc5255</a>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The internationalization level.</value>
|
||||||
|
int InternationalizationLevel { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the access rights supported by the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// These rights are additional rights supported by the IMAP server beyond the standard rights
|
||||||
|
/// defined in <a href="https://tools.ietf.org/html/rfc4314#section-2.1">section 2.1 of rfc4314</a>
|
||||||
|
/// and will not be populated until the client is successfully connected.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The rights.</value>
|
||||||
|
AccessRights Rights { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not the client is currently in the IDLE state.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not the client is currently in the IDLE state.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if an IDLE command is active; otherwise, <c>false</c>.</value>
|
||||||
|
bool IsIdle { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable compression over the IMAP connection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Enables compression over the IMAP connection.</para>
|
||||||
|
/// <para>If the IMAP server supports the <see cref="ImapCapabilities.Compress"/> extension,
|
||||||
|
/// it is possible at any point after connecting to enable compression to reduce network
|
||||||
|
/// bandwidth usage. Ideally, this method should be called before authenticating.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <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.InvalidOperationException">
|
||||||
|
/// Compression must be enabled before a folder has been selected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the <see cref="ImapCapabilities.Compress"/> 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 COMPRESS command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void Compress (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable compression over the IMAP connection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously enables compression over the IMAP connection.</para>
|
||||||
|
/// <para>If the IMAP server supports the <see cref="ImapCapabilities.Compress"/> extension,
|
||||||
|
/// it is possible at any point after connecting to enable compression to reduce network
|
||||||
|
/// bandwidth usage. Ideally, this method should be called before authenticating.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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.InvalidOperationException">
|
||||||
|
/// Compression must be enabled before a folder has been selected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the COMPRESS 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 COMPRESS command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
Task CompressAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable the UTF8=ACCEPT extension.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Enables the <a href="https://tools.ietf.org/html/rfc6855">UTF8=ACCEPT</a> extension.
|
||||||
|
/// </remarks>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// UTF8=ACCEPT needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the UTF8=ACCEPT 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 ENABLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void EnableUTF8 (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable the UTF8=ACCEPT extension.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Enables the <a href="https://tools.ietf.org/html/rfc6855">UTF8=ACCEPT</a> extension.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// UTF8=ACCEPT needs to be enabled before selecting a folder.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the UTF8=ACCEPT 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 ENABLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// An IMAP protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
Task EnableUTF8Async (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <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 <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>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <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>
|
||||||
|
ImapImplementation Identify (ImapImplementation clientImplementation, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
Task<ImapImplementation> IdentifyAsync (ImapImplementation clientImplementation, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Toggle the <see cref="ImapClient"/> into the IDLE state.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>When a client enters the IDLE state, the IMAP server will send
|
||||||
|
/// events to the client as they occur on the selected folder. These events
|
||||||
|
/// may include notifications of new messages arriving, expunge notifications,
|
||||||
|
/// flag changes, etc.</para>
|
||||||
|
/// <para>Due to the nature of the IDLE command, a folder must be selected
|
||||||
|
/// before a client can enter into the IDLE state. This can be done by
|
||||||
|
/// opening a folder using
|
||||||
|
/// <see cref="MailKit.MailFolder.Open(FolderAccess,System.Threading.CancellationToken)"/>
|
||||||
|
/// or any of the other variants.</para>
|
||||||
|
/// <para>While the IDLE command is running, no other commands may be issued until the
|
||||||
|
/// <paramref name="doneToken"/> is cancelled.</para>
|
||||||
|
/// <note type="note">It is especially important to cancel the <paramref name="doneToken"/>
|
||||||
|
/// before cancelling the <paramref name="cancellationToken"/> when using SSL or TLS due to
|
||||||
|
/// the fact that <see cref="System.Net.Security.SslStream"/> cannot be polled.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapIdleExample.cs"/>
|
||||||
|
/// </example>
|
||||||
|
/// <param name="doneToken">The cancellation token used to return to the non-idle state.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="doneToken"/> must be cancellable (i.e. <see cref="System.Threading.CancellationToken.None"/> cannot be used).
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// A <see cref="ImapFolder"/> has not been opened.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the IDLE 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 IDLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
void Idle (CancellationToken doneToken, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously toggle the <see cref="ImapClient"/> into the IDLE state.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>When a client enters the IDLE state, the IMAP server will send
|
||||||
|
/// events to the client as they occur on the selected folder. These events
|
||||||
|
/// may include notifications of new messages arriving, expunge notifications,
|
||||||
|
/// flag changes, etc.</para>
|
||||||
|
/// <para>Due to the nature of the IDLE command, a folder must be selected
|
||||||
|
/// before a client can enter into the IDLE state. This can be done by
|
||||||
|
/// opening a folder using
|
||||||
|
/// <see cref="MailKit.MailFolder.Open(FolderAccess,System.Threading.CancellationToken)"/>
|
||||||
|
/// or any of the other variants.</para>
|
||||||
|
/// <para>While the IDLE command is running, no other commands may be issued until the
|
||||||
|
/// <paramref name="doneToken"/> is cancelled.</para>
|
||||||
|
/// <note type="note">It is especially important to cancel the <paramref name="doneToken"/>
|
||||||
|
/// before cancelling the <paramref name="cancellationToken"/> when using SSL or TLS due to
|
||||||
|
/// the fact that <see cref="System.Net.Security.SslStream"/> cannot be polled.</note>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="doneToken">The cancellation token used to return to the non-idle state.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="doneToken"/> must be cancellable (i.e. <see cref="System.Threading.CancellationToken.None"/> cannot be used).
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// A <see cref="ImapFolder"/> has not been opened.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the IDLE 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 IDLE command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
Task IdleAsync (CancellationToken doneToken, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request the specified notification events from the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <a href="https://tools.ietf.org/html/rfc5465">NOTIFY</a> command is used to expand
|
||||||
|
/// which notifications the client wishes to be notified about, including status notifications
|
||||||
|
/// about folders other than the currently selected folder. It can also be used to automatically
|
||||||
|
/// FETCH information about new messages that have arrived in the currently selected folder.</para>
|
||||||
|
/// <para>This, combined with <see cref="Idle(CancellationToken, CancellationToken)"/>,
|
||||||
|
/// can be used to get instant notifications for changes to any of the specified folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="status"><c>true</c> if the server should immediately notify the client of the
|
||||||
|
/// selected folder's status; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="eventGroups">The specific event groups that the client would like to receive notifications for.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="eventGroups"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="eventGroups"/> is empty.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// One or more <see cref="ImapEventGroup"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the NOTIFY 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 NOTIFY command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
void Notify (bool status, IList<ImapEventGroup> eventGroups, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously request the specified notification events from the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <a href="https://tools.ietf.org/html/rfc5465">NOTIFY</a> command is used to expand
|
||||||
|
/// which notifications the client wishes to be notified about, including status notifications
|
||||||
|
/// about folders other than the currently selected folder. It can also be used to automatically
|
||||||
|
/// FETCH information about new messages that have arrived in the currently selected folder.</para>
|
||||||
|
/// <para>This, combined with <see cref="IdleAsync(CancellationToken, CancellationToken)"/>,
|
||||||
|
/// can be used to get instant notifications for changes to any of the specified folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="status"><c>true</c> if the server should immediately notify the client of the
|
||||||
|
/// selected folder's status; otherwise, <c>false</c>.</param>
|
||||||
|
/// <param name="eventGroups">The specific event groups that the client would like to receive notifications for.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="eventGroups"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="eventGroups"/> is empty.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// One or more <see cref="ImapEventGroup"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the NOTIFY 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 NOTIFY command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
Task NotifyAsync (bool status, IList<ImapEventGroup> eventGroups, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disable any previously requested notification events from the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Disables any notification events requested in a prior call to
|
||||||
|
/// <see cref="Notify(bool, IList{ImapEventGroup}, CancellationToken)"/>.
|
||||||
|
/// request.
|
||||||
|
/// </remarks>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the NOTIFY 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 NOTIFY command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
void DisableNotify (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously disable any previously requested notification events from the IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Disables any notification events requested in a prior call to
|
||||||
|
/// <see cref="NotifyAsync(bool, IList{ImapEventGroup}, CancellationToken)"/>.
|
||||||
|
/// request.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the NOTIFY 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 NOTIFY command with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapProtocolException">
|
||||||
|
/// The server responded with an unexpected token.
|
||||||
|
/// </exception>
|
||||||
|
Task DisableNotifyAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,869 @@
|
||||||
|
//
|
||||||
|
// IImapFolder.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
using MailKit.Search;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for an IMAP folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Implemented by <see cref="MailKit.Net.Imap.ImapFolder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadMessages"/>
|
||||||
|
/// </example>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="DownloadBodyParts"/>
|
||||||
|
/// </example>
|
||||||
|
public interface IImapFolder : IMailFolder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the specified body part headers.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part headers.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part headers.</returns>
|
||||||
|
/// <param name="uid">The UID of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="uid"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested body part headers.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
HeaderList GetHeaders (UniqueId uid, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the specified body part headers.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part headers.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part headers.</returns>
|
||||||
|
/// <param name="uid">The UID of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="uid"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested body part headers.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task<HeaderList> GetHeadersAsync (UniqueId uid, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the specified body part headers.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part headers.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part headers.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested body part headers.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
HeaderList GetHeaders (int index, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the specified body part headers.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part headers.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part headers.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested body part headers.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task<HeaderList> GetHeadersAsync (int index, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the specified body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part.</returns>
|
||||||
|
/// <param name="uid">The UID of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="uid"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested message body.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
MimeEntity GetBodyPart (UniqueId uid, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the specified body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part.</returns>
|
||||||
|
/// <param name="uid">The UID of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="uid"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested message body.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task<MimeEntity> GetBodyPartAsync (UniqueId uid, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the specified body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested message.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
MimeEntity GetBodyPart (int index, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the specified body part.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the specified body part.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The body part.</returns>
|
||||||
|
/// <param name="index">The index of the message.</param>
|
||||||
|
/// <param name="partSpecifier">The body part specifier.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="partSpecifier"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <paramref name="index"/> is out of range.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="MessageNotFoundException">
|
||||||
|
/// The IMAP server did not return the requested message.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task<MimeEntity> GetBodyPartAsync (int index, string partSpecifier, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the streams for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the streams for the specified messages.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uids">The uids of the messages.</param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="uids"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="callback"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="uids"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
void GetStreams (IList<UniqueId> uids, ImapFetchStreamCallback callback, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the streams for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously gets the streams for the specified messages.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An awaitable task.</returns>
|
||||||
|
/// <param name="uids">The uids of the messages.</param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="uids"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="callback"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="uids"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task GetStreamsAsync (IList<UniqueId> uids, ImapFetchStreamAsyncCallback callback, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the streams for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the streams for the specified messages.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="indexes"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="callback"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="indexes"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
void GetStreams (IList<int> indexes, ImapFetchStreamCallback callback, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the streams for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously gets the streams for the specified messages.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An awaitable task.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="indexes"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="callback"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="indexes"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task GetStreamsAsync (IList<int> indexes, ImapFetchStreamAsyncCallback callback, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the streams for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Gets the streams for the specified messages.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="min">The minimum index.</param>
|
||||||
|
/// <param name="max">The maximum index, or <c>-1</c> to specify no upper bound.</param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="min"/> is out of range.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="max"/> is out of range.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="callback"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
void GetStreams (int min, int max, ImapFetchStreamCallback callback, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the streams for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Asynchronously gets the streams for the specified messages.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An awaitable task.</returns>
|
||||||
|
/// <param name="min">The minimum index.</param>
|
||||||
|
/// <param name="max">The maximum index, or <c>-1</c> to specify no upper bound.</param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="progress">The progress reporting mechanism.</param>
|
||||||
|
/// <exception cref="System.ArgumentOutOfRangeException">
|
||||||
|
/// <para><paramref name="min"/> is out of range.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="max"/> is out of range.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="callback"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task GetStreamsAsync (int min, int max, ImapFetchStreamAsyncCallback callback, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Search the folder for messages matching the specified query.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends a <c>UID SEARCH</c> command with the specified query passed directly to the IMAP server
|
||||||
|
/// with no interpretation by MailKit. This means that the query may contain any arguments that a
|
||||||
|
/// <c>UID SEARCH</c> command is allowed to have according to the IMAP specifications and any
|
||||||
|
/// extensions that are supported, including <c>RETURN</c> parameters.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An array of matching UIDs.</returns>
|
||||||
|
/// <param name="query">The search query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="query"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="query"/> is an empty string.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
SearchResults Search (string query, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously search the folder for messages matching the specified query.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends a <c>UID SEARCH</c> command with the specified query passed directly to the IMAP server
|
||||||
|
/// with no interpretation by MailKit. This means that the query may contain any arguments that a
|
||||||
|
/// <c>UID SEARCH</c> command is allowed to have according to the IMAP specifications and any
|
||||||
|
/// extensions that are supported, including <c>RETURN</c> parameters.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An array of matching UIDs.</returns>
|
||||||
|
/// <param name="query">The search query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="query"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="query"/> is an empty string.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task<SearchResults> SearchAsync (string query, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sort messages matching the specified query.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends a <c>UID SORT</c> command with the specified query passed directly to the IMAP server
|
||||||
|
/// with no interpretation by MailKit. This means that the query may contain any arguments that a
|
||||||
|
/// <c>UID SORT</c> command is allowed to have according to the IMAP specifications and any
|
||||||
|
/// extensions that are supported, including <c>RETURN</c> parameters.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An array of matching UIDs.</returns>
|
||||||
|
/// <param name="query">The search query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="query"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="query"/> is an empty string.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the SORT extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
SearchResults Sort (string query, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously sort messages matching the specified query.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Sends a <c>UID SORT</c> command with the specified query passed directly to the IMAP server
|
||||||
|
/// with no interpretation by MailKit. This means that the query may contain any arguments that a
|
||||||
|
/// <c>UID SORT</c> command is allowed to have according to the IMAP specifications and any
|
||||||
|
/// extensions that are supported, including <c>RETURN</c> parameters.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An array of matching UIDs.</returns>
|
||||||
|
/// <param name="query">The search query.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="query"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="query"/> is an empty string.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The IMAP server does not support the SORT extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
Task<SearchResults> SortAsync (string query, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
//
|
||||||
|
// ImapCallbacks.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A callback used when fetching message streams.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>This callback is meant to be used with the various
|
||||||
|
/// <a href="Overload_MailKit_Net_Imap_ImapFolder_GetStreams.htm">GetStreams</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <para>Once this callback returns, the stream argument will be disposed, so
|
||||||
|
/// it is important to consume the stream right away and not add it to a queue
|
||||||
|
/// for later processing.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folder">The IMAP folder that the message belongs to.</param>
|
||||||
|
/// <param name="index">The index of the message in the folder.</param>
|
||||||
|
/// <param name="uid">The UID of the message in the folder.</param>
|
||||||
|
/// <param name="stream">The raw message (or part) stream.</param>
|
||||||
|
public delegate void ImapFetchStreamCallback (ImapFolder folder, int index, UniqueId uid, Stream stream);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An asynchronous callback used when fetching message streams.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>This callback is meant to be used with the various
|
||||||
|
/// <a href="Overload_MailKit_Net_Imap_ImapFolder_GetStreamsAsync.htm">GetStreamsAsync</a>
|
||||||
|
/// methods.</para>
|
||||||
|
/// <para>Once this callback returns, the stream argument will be disposed, so
|
||||||
|
/// it is important to consume the stream right away and not add it to a queue
|
||||||
|
/// for later processing.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An awaitable task context.</returns>
|
||||||
|
/// <param name="folder">The IMAP folder that the message belongs to.</param>
|
||||||
|
/// <param name="index">The index of the message in the folder.</param>
|
||||||
|
/// <param name="uid">The UID of the message in the folder.</param>
|
||||||
|
/// <param name="stream">The raw message (or part) stream.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
public delegate Task ImapFetchStreamAsyncCallback (ImapFolder folder, int index, UniqueId uid, Stream stream, CancellationToken cancellationToken);
|
||||||
|
}
|
|
@ -0,0 +1,348 @@
|
||||||
|
//
|
||||||
|
// ImapCapabilities.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// Capabilities supported by an IMAP server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Capabilities are read as part of the response to the <c>CAPABILITY</c> command that
|
||||||
|
/// is issued during the connection and authentication phases of the
|
||||||
|
/// <see cref="ImapClient"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
[Flags]
|
||||||
|
public enum ImapCapabilities : ulong {
|
||||||
|
/// <summary>
|
||||||
|
/// The server does not support any additional extensions.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server implements the core IMAP4 commands.
|
||||||
|
/// </summary>
|
||||||
|
IMAP4 = 1L << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server implements the core IMAP4rev1 commands.
|
||||||
|
/// </summary>
|
||||||
|
IMAP4rev1 = 1L << 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server implements the core IMAP4rev2 commands.
|
||||||
|
/// </summary>
|
||||||
|
IMAP4rev2 = 1L << 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <c>STATUS</c> command.
|
||||||
|
/// </summary>
|
||||||
|
Status = 1L << 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the ACL extension defined in <a href="https://tools.ietf.org/html/rfc2086">rfc2086</a>
|
||||||
|
/// and <a href="https://tools.ietf.org/html/rfc4314">rfc4314</a>.
|
||||||
|
/// </summary>
|
||||||
|
Acl = 1L << 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2087">QUOTA</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Quota = 1L << 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2088">LITERAL+</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
LiteralPlus = 1L << 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2177">IDLE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Idle = 1L << 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2193">MAILBOX-REFERRALS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
MailboxReferrals = 1L << 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the server supports the <a href="https://tools.ietf.org/html/rfc2221">LOGIN-REFERRALS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
LoginReferrals = 1L << 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2342">NAMESPACE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Namespace = 1L << 10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2971">ID</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Id = 1L << 11,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc3348">CHILDREN</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Children = 1L << 12,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc3501">LOGINDISABLED</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
LoginDisabled = 1L << 13,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc3501">STARTTLS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
StartTLS = 1L << 14,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc3502">MULTIAPPEND</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
MultiAppend = 1L << 15,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc3516">BINARY</a> content extension.
|
||||||
|
/// </summary>
|
||||||
|
Binary = 1L << 16,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc3691">UNSELECT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Unselect = 1L << 17,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc4315">UIDPLUS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
UidPlus = 1L << 18,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc4469">CATENATE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Catenate = 1L << 19,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc4551">CONDSTORE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
CondStore = 1L << 20,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc4731">ESEARCH</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
ESearch = 1L << 21,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc4959">SASL-IR</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
SaslIR = 1L << 22,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc4978">COMPRESS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Compress = 1L << 23,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5032">WITHIN</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Within = 1L << 24,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5161">ENABLE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Enable = 1L << 25,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5162">QRESYNC</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
QuickResync = 1L << 26,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5182">SEARCHRES</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
SearchResults = 1L << 27,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5256">SORT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Sort = 1L << 28,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5256">THREAD</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Thread = 1L << 29,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5257">ANNOTATE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Annotate = 1L << 30,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5258">LIST-EXTENDED</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
ListExtended = 1L << 31,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5259">CONVERT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Convert = 1L << 32,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5255">LANGUAGE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Language = 1L << 33,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5255">I18NLEVEL</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
I18NLevel = 1L << 34,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5267">ESORT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
ESort = 1L << 35,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5267">CONTEXT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Context = 1L << 36,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5464">METADATA</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Metadata = 1L << 37,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5464">METADATA-SERVER</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
MetadataServer = 1L << 38,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5465">NOTIFY</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Notify = 1L << 39,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5466">FILTERS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Filters = 1L << 40,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5819">LIST-STATUS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
ListStatus = 1L << 41,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc5957">SORT=DISPLAY</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
SortDisplay = 1L << 42,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6154">CREATE-SPECIAL-USE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
CreateSpecialUse = 1L << 43,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6154">SPECIAL-USE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
SpecialUse = 1L << 44,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6203">SEARCH=FUZZY</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
FuzzySearch = 1L << 45,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6237">MULTISEARCH</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
MultiSearch = 1L << 46,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6851">MOVE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Move = 1L << 47,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6855">UTF8=ACCEPT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
UTF8Accept = 1L << 48,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6855">UTF8=ONLY</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
UTF8Only = 1L << 49,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc7888">LITERAL-</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
LiteralMinus = 1L << 50,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc7889">APPENDLIMIT</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
AppendLimit = 1L << 51,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc8437">UNAUTHENTICATE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Unauthenticate = 1L << 52,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc8438">STATUS=SIZE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
StatusSize = 1L << 53,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc8440">LIST-MYRIGHTS</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
ListMyRights = 1L << 54,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc8474">OBJECTID</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
ObjectID = 1L << 55,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc8508">REPLACE</a> extension.
|
||||||
|
/// </summary>
|
||||||
|
Replace = 1L << 56,
|
||||||
|
|
||||||
|
#region GMail Extensions
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://developers.google.com/gmail/imap_extensions">XLIST</a> extension (GMail).
|
||||||
|
/// </summary>
|
||||||
|
XList = 1L << 60,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://developers.google.com/gmail/imap_extensions">X-GM-EXT1</a> extension (GMail).
|
||||||
|
/// </summary>
|
||||||
|
GMailExt1 = 1L << 61
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,918 @@
|
||||||
|
//
|
||||||
|
// ImapCommand.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
using MimeKit.IO;
|
||||||
|
using MimeKit.Utils;
|
||||||
|
|
||||||
|
using SslStream = MailKit.Net.SslStream;
|
||||||
|
using NetworkStream = MailKit.Net.NetworkStream;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP continuation handler.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// All exceptions thrown by the handler are considered fatal and will
|
||||||
|
/// force-disconnect the connection. If a non-fatal error occurs, set
|
||||||
|
/// it on the <see cref="ImapCommand.Exception"/> property.
|
||||||
|
/// </remarks>
|
||||||
|
delegate Task ImapContinuationHandler (ImapEngine engine, ImapCommand ic, string text, bool doAsync);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP untagged response handler.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Most IMAP commands return their results in untagged responses.</para>
|
||||||
|
/// </remarks>
|
||||||
|
delegate Task ImapUntaggedHandler (ImapEngine engine, ImapCommand ic, int index, bool doAsync);
|
||||||
|
|
||||||
|
delegate void ImapCommandResetHandler (ImapCommand ic);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IMAP command status.
|
||||||
|
/// </summary>
|
||||||
|
enum ImapCommandStatus {
|
||||||
|
Created,
|
||||||
|
Queued,
|
||||||
|
Active,
|
||||||
|
Complete,
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ImapLiteralType {
|
||||||
|
String,
|
||||||
|
//Stream,
|
||||||
|
MimeMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ImapStringType {
|
||||||
|
Atom,
|
||||||
|
QString,
|
||||||
|
Literal,
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP IDLE context.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An IMAP IDLE command does not work like normal commands. Unlike most commands,
|
||||||
|
/// the IDLE command does not end until the client sends a separate "DONE" command.</para>
|
||||||
|
/// <para>In order to facilitate this, the way this works is that the consumer of MailKit's
|
||||||
|
/// IMAP APIs provides a 'doneToken' which signals to the command-processing loop to
|
||||||
|
/// send the "DONE" command. Since, like every other IMAP command, it is also necessary to
|
||||||
|
/// provide a means of cancelling the IDLE command, it becomes necessary to link the
|
||||||
|
/// 'doneToken' and the 'cancellationToken' together.</para>
|
||||||
|
/// </remarks>
|
||||||
|
sealed class ImapIdleContext : IDisposable
|
||||||
|
{
|
||||||
|
static readonly byte[] DoneCommand = Encoding.ASCII.GetBytes ("DONE\r\n");
|
||||||
|
CancellationTokenRegistration registration;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapIdleContext"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.Net.Imap.ImapIdleContext"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine.</param>
|
||||||
|
/// <param name="doneToken">The done token.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
public ImapIdleContext (ImapEngine engine, CancellationToken doneToken, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
CancellationToken = cancellationToken;
|
||||||
|
DoneToken = doneToken;
|
||||||
|
Engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the engine.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the engine.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The engine.</value>
|
||||||
|
public ImapEngine Engine {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the cancellation token.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Get the cancellation token.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The cancellation token.</value>
|
||||||
|
public CancellationToken CancellationToken {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the done token.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the done token.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The done token.</value>
|
||||||
|
public CancellationToken DoneToken {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if false
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not cancellation has been requested.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not cancellation has been requested.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if cancellation has been requested; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsCancellationRequested {
|
||||||
|
get { return CancellationToken.IsCancellationRequested; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not the IDLE command should be ended.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not the IDLE command should be ended.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if the IDLE command should end; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsDoneRequested {
|
||||||
|
get { return DoneToken.IsCancellationRequested; }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void IdleComplete ()
|
||||||
|
{
|
||||||
|
if (Engine.State == ImapEngineState.Idle) {
|
||||||
|
try {
|
||||||
|
Engine.Stream.Write (DoneCommand, 0, DoneCommand.Length, CancellationToken);
|
||||||
|
Engine.Stream.Flush (CancellationToken);
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Engine.State = ImapEngineState.Selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback method to be used as the ImapCommand's ContinuationHandler.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Callback method to be used as the ImapCommand's ContinuationHandler.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The ImapEngine.</param>
|
||||||
|
/// <param name="ic">The ImapCommand.</param>
|
||||||
|
/// <param name="text">The text.</param>
|
||||||
|
/// <param name="doAsync"><c>true</c> if the command is being run asynchronously; otherwise, <c>false</c>.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task ContinuationHandler (ImapEngine engine, ImapCommand ic, string text, bool doAsync)
|
||||||
|
{
|
||||||
|
Engine.State = ImapEngineState.Idle;
|
||||||
|
|
||||||
|
registration = DoneToken.Register (IdleComplete);
|
||||||
|
|
||||||
|
return Task.FromResult (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases all resource used by the <see cref="MailKit.Net.Imap.ImapIdleContext"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="MailKit.Net.Imap.ImapIdleContext"/>. The
|
||||||
|
/// <see cref="Dispose"/> method leaves the <see cref="MailKit.Net.Imap.ImapIdleContext"/> in an unusable state. After
|
||||||
|
/// calling <see cref="Dispose"/>, you must release all references to the
|
||||||
|
/// <see cref="MailKit.Net.Imap.ImapIdleContext"/> so the garbage collector can reclaim the memory that the
|
||||||
|
/// <see cref="MailKit.Net.Imap.ImapIdleContext"/> was occupying.</remarks>
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
registration.Dispose ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP literal object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The literal can be a string, byte[], Stream, or a MimeMessage.
|
||||||
|
/// </remarks>
|
||||||
|
class ImapLiteral
|
||||||
|
{
|
||||||
|
public readonly ImapLiteralType Type;
|
||||||
|
public readonly object Literal;
|
||||||
|
readonly FormatOptions format;
|
||||||
|
readonly Action<int> update;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapLiteral"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.Net.Imap.ImapLiteral"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="action">The progress update action.</param>
|
||||||
|
public ImapLiteral (FormatOptions options, MimeMessage message, Action<int> action = null)
|
||||||
|
{
|
||||||
|
format = options.Clone ();
|
||||||
|
format.NewLineFormat = NewLineFormat.Dos;
|
||||||
|
|
||||||
|
update = action;
|
||||||
|
|
||||||
|
Type = ImapLiteralType.MimeMessage;
|
||||||
|
Literal = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapLiteral"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.Net.Imap.ImapLiteral"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="literal">The literal.</param>
|
||||||
|
public ImapLiteral (FormatOptions options, byte[] literal)
|
||||||
|
{
|
||||||
|
format = options.Clone ();
|
||||||
|
format.NewLineFormat = NewLineFormat.Dos;
|
||||||
|
|
||||||
|
Type = ImapLiteralType.String;
|
||||||
|
Literal = literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the length of the literal, in bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the length of the literal, in bytes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The length.</value>
|
||||||
|
public long Length {
|
||||||
|
get {
|
||||||
|
if (Type == ImapLiteralType.String)
|
||||||
|
return ((byte[]) Literal).Length;
|
||||||
|
|
||||||
|
using (var measure = new MeasuringStream ()) {
|
||||||
|
//if (Type == ImapLiteralType.Stream) {
|
||||||
|
// var stream = (Stream) Literal;
|
||||||
|
// stream.CopyTo (measure, 4096);
|
||||||
|
// stream.Position = 0;
|
||||||
|
|
||||||
|
// return measure.Length;
|
||||||
|
//}
|
||||||
|
|
||||||
|
((MimeMessage) Literal).WriteTo (format, measure);
|
||||||
|
|
||||||
|
return measure.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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.Stream) {
|
||||||
|
// 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);
|
||||||
|
// }
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A partial IMAP command.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// IMAP commands that contain literal strings are broken up into multiple parts
|
||||||
|
/// in case the IMAP server does not support the LITERAL+ extension. These parts
|
||||||
|
/// are then sent individually as we receive "+" responses from the server.
|
||||||
|
/// </remarks>
|
||||||
|
class ImapCommandPart
|
||||||
|
{
|
||||||
|
public readonly byte[] Command;
|
||||||
|
public readonly ImapLiteral Literal;
|
||||||
|
public readonly bool WaitForContinuation;
|
||||||
|
|
||||||
|
public ImapCommandPart (byte[] command, ImapLiteral literal, bool wait = true)
|
||||||
|
{
|
||||||
|
WaitForContinuation = wait;
|
||||||
|
Command = command;
|
||||||
|
Literal = literal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP command.
|
||||||
|
/// </summary>
|
||||||
|
class ImapCommand
|
||||||
|
{
|
||||||
|
static readonly byte[] UTF8LiteralTokenPrefix = Encoding.ASCII.GetBytes ("UTF8 (~{");
|
||||||
|
static readonly byte[] LiteralTokenSuffix = { (byte) '}', (byte) '\r', (byte) '\n' };
|
||||||
|
static readonly byte[] Nil = { (byte) 'N', (byte) 'I', (byte) 'L' };
|
||||||
|
static readonly byte[] NewLine = { (byte) '\r', (byte) '\n' };
|
||||||
|
static readonly byte[] LiteralTokenPrefix = { (byte) '{' };
|
||||||
|
|
||||||
|
public Dictionary<string, ImapUntaggedHandler> UntaggedHandlers { get; private set; }
|
||||||
|
public ImapContinuationHandler ContinuationHandler { get; set; }
|
||||||
|
public CancellationToken CancellationToken { get; private set; }
|
||||||
|
public ImapCommandStatus Status { get; internal set; }
|
||||||
|
public ImapCommandResponse Response { get; internal set; }
|
||||||
|
public ITransferProgress Progress { get; internal set; }
|
||||||
|
public Exception Exception { get; internal set; }
|
||||||
|
public readonly List<ImapResponseCode> RespCodes;
|
||||||
|
public string ResponseText { get; internal set; }
|
||||||
|
public ImapFolder Folder { get; private set; }
|
||||||
|
public object UserData { get; internal set; }
|
||||||
|
public bool ListReturnsSubscribed { get; internal set; }
|
||||||
|
public bool Logout { get; private set; }
|
||||||
|
public bool Lsub { get; internal set; }
|
||||||
|
public string Tag { get; private set; }
|
||||||
|
public bool Bye { get; internal set; }
|
||||||
|
|
||||||
|
readonly List<ImapCommandPart> parts = new List<ImapCommandPart> ();
|
||||||
|
readonly ImapEngine Engine;
|
||||||
|
long totalSize, nwritten;
|
||||||
|
int current;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine that will be sending the command.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="folder">The IMAP folder that the command operates on.</param>
|
||||||
|
/// <param name="options">The formatting options.</param>
|
||||||
|
/// <param name="format">The command format.</param>
|
||||||
|
/// <param name="args">The command arguments.</param>
|
||||||
|
public ImapCommand (ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, FormatOptions options, string format, params object[] args)
|
||||||
|
{
|
||||||
|
UntaggedHandlers = new Dictionary<string, ImapUntaggedHandler> (StringComparer.OrdinalIgnoreCase);
|
||||||
|
Logout = format.Equals ("LOGOUT\r\n", StringComparison.Ordinal);
|
||||||
|
RespCodes = new List<ImapResponseCode> ();
|
||||||
|
CancellationToken = cancellationToken;
|
||||||
|
Response = ImapCommandResponse.None;
|
||||||
|
Status = ImapCommandStatus.Created;
|
||||||
|
Engine = engine;
|
||||||
|
Folder = folder;
|
||||||
|
|
||||||
|
using (var builder = new MemoryStream ()) {
|
||||||
|
byte[] buf, utf8 = new byte[8];
|
||||||
|
int argc = 0;
|
||||||
|
string str;
|
||||||
|
|
||||||
|
for (int i = 0; i < format.Length; i++) {
|
||||||
|
if (format[i] == '%') {
|
||||||
|
switch (format[++i]) {
|
||||||
|
case '%': // a literal %
|
||||||
|
builder.WriteByte ((byte) '%');
|
||||||
|
break;
|
||||||
|
case 'd': // an integer
|
||||||
|
str = ((int) args[argc++]).ToString (CultureInfo.InvariantCulture);
|
||||||
|
buf = Encoding.ASCII.GetBytes (str);
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
break;
|
||||||
|
case 'u': // an unsigned integer
|
||||||
|
str = ((uint) args[argc++]).ToString (CultureInfo.InvariantCulture);
|
||||||
|
buf = Encoding.ASCII.GetBytes (str);
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
str = (string) args[argc++];
|
||||||
|
buf = Encoding.ASCII.GetBytes (str);
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
break;
|
||||||
|
case 'F': // an ImapFolder
|
||||||
|
var utf7 = ((ImapFolder) args[argc++]).EncodedName;
|
||||||
|
AppendString (options, true, builder, utf7);
|
||||||
|
break;
|
||||||
|
case 'L': // a MimeMessage or a byte[]
|
||||||
|
var arg = args[argc++];
|
||||||
|
ImapLiteral literal;
|
||||||
|
byte[] prefix;
|
||||||
|
|
||||||
|
if (arg is MimeMessage message) {
|
||||||
|
prefix = options.International ? UTF8LiteralTokenPrefix : LiteralTokenPrefix;
|
||||||
|
literal = new ImapLiteral (options, message, UpdateProgress);
|
||||||
|
} else {
|
||||||
|
literal = new ImapLiteral (options, (byte[]) arg);
|
||||||
|
prefix = LiteralTokenPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
var length = literal.Length;
|
||||||
|
bool wait = true;
|
||||||
|
|
||||||
|
builder.Write (prefix, 0, prefix.Length);
|
||||||
|
buf = Encoding.ASCII.GetBytes (length.ToString (CultureInfo.InvariantCulture));
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
|
||||||
|
if (CanUseNonSynchronizedLiteral (Engine, length)) {
|
||||||
|
builder.WriteByte ((byte) '+');
|
||||||
|
wait = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Write (LiteralTokenSuffix, 0, LiteralTokenSuffix.Length);
|
||||||
|
|
||||||
|
totalSize += length;
|
||||||
|
|
||||||
|
parts.Add (new ImapCommandPart (builder.ToArray (), literal, wait));
|
||||||
|
builder.SetLength (0);
|
||||||
|
|
||||||
|
if (prefix == UTF8LiteralTokenPrefix)
|
||||||
|
builder.WriteByte ((byte) ')');
|
||||||
|
break;
|
||||||
|
case 'S': // a string which may need to be quoted or made into a literal
|
||||||
|
AppendString (options, true, builder, (string) args[argc++]);
|
||||||
|
break;
|
||||||
|
case 'Q': // similar to %S but string must be quoted at a minimum
|
||||||
|
AppendString (options, false, builder, (string) args[argc++]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException ();
|
||||||
|
}
|
||||||
|
} else if (format[i] < 128) {
|
||||||
|
builder.WriteByte ((byte) format[i]);
|
||||||
|
} else {
|
||||||
|
int nchars = char.IsSurrogate (format[i]) ? 2 : 1;
|
||||||
|
int nbytes = Encoding.UTF8.GetBytes (format, i, nchars, utf8, 0);
|
||||||
|
builder.Write (utf8, 0, nbytes);
|
||||||
|
i += nchars - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.Add (new ImapCommandPart (builder.ToArray (), null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommand"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.Net.Imap.ImapCommand"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine that will be sending the command.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <param name="folder">The IMAP folder that the command operates on.</param>
|
||||||
|
/// <param name="format">The command format.</param>
|
||||||
|
/// <param name="args">The command arguments.</param>
|
||||||
|
public ImapCommand (ImapEngine engine, CancellationToken cancellationToken, ImapFolder folder, string format, params object[] args)
|
||||||
|
: this (engine, cancellationToken, folder, FormatOptions.Default, format, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int EstimateCommandLength (ImapEngine engine, FormatOptions options, string format, params object[] args)
|
||||||
|
{
|
||||||
|
const int EstimatedTagLength = 10;
|
||||||
|
var eoln = false;
|
||||||
|
int length = 0;
|
||||||
|
int argc = 0;
|
||||||
|
string str;
|
||||||
|
|
||||||
|
for (int i = 0; i < format.Length; i++) {
|
||||||
|
if (format[i] == '%') {
|
||||||
|
switch (format[++i]) {
|
||||||
|
case '%': // a literal %
|
||||||
|
length++;
|
||||||
|
break;
|
||||||
|
case 'd': // an integer
|
||||||
|
str = ((int) args[argc++]).ToString (CultureInfo.InvariantCulture);
|
||||||
|
length += str.Length;
|
||||||
|
break;
|
||||||
|
case 'u': // an unsigned integer
|
||||||
|
str = ((uint) args[argc++]).ToString (CultureInfo.InvariantCulture);
|
||||||
|
length += str.Length;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
str = (string) args[argc++];
|
||||||
|
length += str.Length;
|
||||||
|
break;
|
||||||
|
case 'F': // an ImapFolder
|
||||||
|
var utf7 = ((ImapFolder) args[argc++]).EncodedName;
|
||||||
|
length += EstimateStringLength (engine, options, true, utf7, out eoln);
|
||||||
|
break;
|
||||||
|
case 'L': // a MimeMessage or a byte[]
|
||||||
|
var arg = args[argc++];
|
||||||
|
byte[] prefix;
|
||||||
|
long len;
|
||||||
|
|
||||||
|
if (arg is MimeMessage message) {
|
||||||
|
prefix = options.International ? UTF8LiteralTokenPrefix : LiteralTokenPrefix;
|
||||||
|
var literal = new ImapLiteral (options, message, null);
|
||||||
|
len = literal.Length;
|
||||||
|
} else {
|
||||||
|
len = ((byte[]) arg).Length;
|
||||||
|
prefix = LiteralTokenPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
length += prefix.Length;
|
||||||
|
length += Encoding.ASCII.GetByteCount (len.ToString (CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
|
if (CanUseNonSynchronizedLiteral (engine, len))
|
||||||
|
length++;
|
||||||
|
|
||||||
|
length += LiteralTokenSuffix.Length;
|
||||||
|
|
||||||
|
if (prefix == UTF8LiteralTokenPrefix)
|
||||||
|
length++;
|
||||||
|
|
||||||
|
eoln = true;
|
||||||
|
break;
|
||||||
|
case 'S': // a string which may need to be quoted or made into a literal
|
||||||
|
length += EstimateStringLength (engine, options, true, (string) args[argc++], out eoln);
|
||||||
|
break;
|
||||||
|
case 'Q': // similar to %S but string must be quoted at a minimum
|
||||||
|
length += EstimateStringLength (engine, options, false, (string) args[argc++], out eoln);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eoln)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return length + EstimatedTagLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int EstimateCommandLength (ImapEngine engine, string format, params object[] args)
|
||||||
|
{
|
||||||
|
return EstimateCommandLength (engine, FormatOptions.Default, format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateProgress (int n)
|
||||||
|
{
|
||||||
|
nwritten += n;
|
||||||
|
|
||||||
|
if (Progress != null)
|
||||||
|
Progress.Report (nwritten, totalSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsAtom (char c)
|
||||||
|
{
|
||||||
|
return c < 128 && !char.IsControl (c) && "(){ \t%*\\\"]".IndexOf (c) == -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsQuotedSafe (ImapEngine engine, char c)
|
||||||
|
{
|
||||||
|
return (c < 128 || engine.UTF8Enabled) && !char.IsControl (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ImapStringType GetStringType (ImapEngine engine, string value, bool allowAtom)
|
||||||
|
{
|
||||||
|
var type = allowAtom ? ImapStringType.Atom : ImapStringType.QString;
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return ImapStringType.Nil;
|
||||||
|
|
||||||
|
if (value.Length == 0)
|
||||||
|
return ImapStringType.QString;
|
||||||
|
|
||||||
|
for (int i = 0; i < value.Length; i++) {
|
||||||
|
if (!IsAtom (value[i])) {
|
||||||
|
if (!IsQuotedSafe (engine, value[i]))
|
||||||
|
return ImapStringType.Literal;
|
||||||
|
|
||||||
|
type = ImapStringType.QString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CanUseNonSynchronizedLiteral (ImapEngine engine, long length)
|
||||||
|
{
|
||||||
|
return (engine.Capabilities & ImapCapabilities.LiteralPlus) != 0 ||
|
||||||
|
(length <= 4096 && (engine.Capabilities & ImapCapabilities.LiteralMinus) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int EstimateStringLength (ImapEngine engine, FormatOptions options, bool allowAtom, string value, out bool eoln)
|
||||||
|
{
|
||||||
|
eoln = false;
|
||||||
|
|
||||||
|
switch (GetStringType (engine, value, allowAtom)) {
|
||||||
|
case ImapStringType.Literal:
|
||||||
|
var literal = Encoding.UTF8.GetByteCount (value);
|
||||||
|
var plus = CanUseNonSynchronizedLiteral (engine, literal);
|
||||||
|
int length = "{}\r\n".Length;
|
||||||
|
|
||||||
|
length += literal.ToString (CultureInfo.InvariantCulture).Length;
|
||||||
|
if (plus)
|
||||||
|
length++;
|
||||||
|
|
||||||
|
eoln = true;
|
||||||
|
|
||||||
|
return length++;
|
||||||
|
case ImapStringType.QString:
|
||||||
|
return Encoding.UTF8.GetByteCount (MimeUtils.Quote (value));
|
||||||
|
case ImapStringType.Nil:
|
||||||
|
return Nil.Length;
|
||||||
|
default:
|
||||||
|
return value.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendString (FormatOptions options, bool allowAtom, MemoryStream builder, string value)
|
||||||
|
{
|
||||||
|
byte[] buf;
|
||||||
|
|
||||||
|
switch (GetStringType (Engine, value, allowAtom)) {
|
||||||
|
case ImapStringType.Literal:
|
||||||
|
var literal = Encoding.UTF8.GetBytes (value);
|
||||||
|
var plus = CanUseNonSynchronizedLiteral (Engine, literal.Length);
|
||||||
|
var length = literal.Length.ToString (CultureInfo.InvariantCulture);
|
||||||
|
buf = Encoding.ASCII.GetBytes (length);
|
||||||
|
|
||||||
|
builder.WriteByte ((byte) '{');
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
if (plus)
|
||||||
|
builder.WriteByte ((byte) '+');
|
||||||
|
builder.WriteByte ((byte) '}');
|
||||||
|
builder.WriteByte ((byte) '\r');
|
||||||
|
builder.WriteByte ((byte) '\n');
|
||||||
|
|
||||||
|
if (plus) {
|
||||||
|
builder.Write (literal, 0, literal.Length);
|
||||||
|
} else {
|
||||||
|
parts.Add (new ImapCommandPart (builder.ToArray (), new ImapLiteral (options, literal)));
|
||||||
|
builder.SetLength (0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ImapStringType.QString:
|
||||||
|
buf = Encoding.UTF8.GetBytes (MimeUtils.Quote (value));
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
break;
|
||||||
|
case ImapStringType.Atom:
|
||||||
|
buf = Encoding.UTF8.GetBytes (value);
|
||||||
|
builder.Write (buf, 0, buf.Length);
|
||||||
|
break;
|
||||||
|
case ImapStringType.Nil:
|
||||||
|
builder.Write (Nil, 0, Nil.Length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers the untagged handler for the specified atom token.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="atom">The atom token.</param>
|
||||||
|
/// <param name="handler">The handler.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="atom"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="handler"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Untagged handlers must be registered before the command has been queued.
|
||||||
|
/// </exception>
|
||||||
|
public void RegisterUntaggedHandler (string atom, ImapUntaggedHandler handler)
|
||||||
|
{
|
||||||
|
if (atom == null)
|
||||||
|
throw new ArgumentNullException (nameof (atom));
|
||||||
|
|
||||||
|
if (handler == null)
|
||||||
|
throw new ArgumentNullException (nameof (handler));
|
||||||
|
|
||||||
|
if (Status != ImapCommandStatus.Created)
|
||||||
|
throw new InvalidOperationException ("Untagged handlers must be registered before the command has been queued.");
|
||||||
|
|
||||||
|
UntaggedHandlers.Add (atom, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the next part of the command to the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <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 async Task<bool> StepAsync (bool doAsync)
|
||||||
|
{
|
||||||
|
var supportsLiteralPlus = (Engine.Capabilities & ImapCapabilities.LiteralPlus) != 0;
|
||||||
|
var idle = UserData as ImapIdleContext;
|
||||||
|
var result = ImapCommandResponse.None;
|
||||||
|
ImapToken token;
|
||||||
|
|
||||||
|
// construct and write the command tag if this is the initial state
|
||||||
|
if (current == 0) {
|
||||||
|
Tag = string.Format (CultureInfo.InvariantCulture, "{0}{1:D8}", Engine.TagPrefix, Engine.Tag++);
|
||||||
|
|
||||||
|
var buf = Encoding.ASCII.GetBytes (Tag + " ");
|
||||||
|
|
||||||
|
if (doAsync)
|
||||||
|
await Engine.Stream.WriteAsync (buf, 0, buf.Length, CancellationToken).ConfigureAwait (false);
|
||||||
|
else
|
||||||
|
Engine.Stream.Write (buf, 0, buf.Length, CancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
var command = parts[current].Command;
|
||||||
|
|
||||||
|
if (doAsync)
|
||||||
|
await Engine.Stream.WriteAsync (command, 0, command.Length, CancellationToken).ConfigureAwait (false);
|
||||||
|
else
|
||||||
|
Engine.Stream.Write (command, 0, command.Length, CancellationToken);
|
||||||
|
|
||||||
|
// if the server doesn't support LITERAL+ (or LITERAL-), we'll need to wait
|
||||||
|
// for a "+" response before writing out the any literals...
|
||||||
|
if (parts[current].WaitForContinuation)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// otherwise, we can write out any and all literal tokens we have...
|
||||||
|
await parts[current].Literal.WriteToAsync (Engine.Stream, doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
|
||||||
|
if (current + 1 >= parts.Count)
|
||||||
|
break;
|
||||||
|
|
||||||
|
current++;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
if (doAsync)
|
||||||
|
await Engine.Stream.FlushAsync (CancellationToken).ConfigureAwait (false);
|
||||||
|
else
|
||||||
|
Engine.Stream.Flush (CancellationToken);
|
||||||
|
|
||||||
|
// now we need to read the response...
|
||||||
|
do {
|
||||||
|
if (Engine.State == ImapEngineState.Idle) {
|
||||||
|
int timeout = Timeout.Infinite;
|
||||||
|
|
||||||
|
if (Engine.Stream.CanTimeout) {
|
||||||
|
timeout = Engine.Stream.ReadTimeout;
|
||||||
|
Engine.Stream.ReadTimeout = Timeout.Infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
token = await Engine.ReadTokenAsync (doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
} finally {
|
||||||
|
if (Engine.Stream.IsConnected && Engine.Stream.CanTimeout)
|
||||||
|
Engine.Stream.ReadTimeout = timeout;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
token = await Engine.ReadTokenAsync (doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.Type == ImapTokenType.Atom && token.Value.ToString () == "+") {
|
||||||
|
// we've gotten a continuation response from the server
|
||||||
|
var text = (await Engine.ReadLineAsync (doAsync, CancellationToken).ConfigureAwait (false)).Trim ();
|
||||||
|
|
||||||
|
// if we've got a Literal pending, the '+' means we can send it now...
|
||||||
|
if (!supportsLiteralPlus && parts[current].Literal != null) {
|
||||||
|
await parts[current].Literal.WriteToAsync (Engine.Stream, doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContinuationHandler != null) {
|
||||||
|
await ContinuationHandler (Engine, this, text, doAsync).ConfigureAwait (false);
|
||||||
|
} else if (doAsync) {
|
||||||
|
await Engine.Stream.WriteAsync (NewLine, 0, NewLine.Length, CancellationToken).ConfigureAwait (false);
|
||||||
|
await Engine.Stream.FlushAsync (CancellationToken).ConfigureAwait (false);
|
||||||
|
} else {
|
||||||
|
Engine.Stream.Write (NewLine, 0, NewLine.Length, CancellationToken);
|
||||||
|
Engine.Stream.Flush (CancellationToken);
|
||||||
|
}
|
||||||
|
} else if (token.Type == ImapTokenType.Asterisk) {
|
||||||
|
// we got an untagged response, let the engine handle this...
|
||||||
|
await Engine.ProcessUntaggedResponseAsync (doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
} else if (token.Type == ImapTokenType.Atom && (string) token.Value == Tag) {
|
||||||
|
// the next token should be "OK", "NO", or "BAD"
|
||||||
|
token = await Engine.ReadTokenAsync (doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
|
||||||
|
ImapEngine.AssertToken (token, ImapTokenType.Atom, "Syntax error in tagged response. Unexpected token: {0}", token);
|
||||||
|
|
||||||
|
string atom = (string) token.Value;
|
||||||
|
|
||||||
|
switch (atom) {
|
||||||
|
case "BAD": result = ImapCommandResponse.Bad; break;
|
||||||
|
case "OK": result = ImapCommandResponse.Ok; break;
|
||||||
|
case "NO": result = ImapCommandResponse.No; break;
|
||||||
|
default: throw ImapEngine.UnexpectedToken ("Syntax error in tagged response. Unexpected token: {0}", token);
|
||||||
|
}
|
||||||
|
|
||||||
|
token = await Engine.ReadTokenAsync (doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
if (token.Type == ImapTokenType.OpenBracket) {
|
||||||
|
var code = await Engine.ParseResponseCodeAsync (true, doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
RespCodes.Add (code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.Type != ImapTokenType.Eoln) {
|
||||||
|
// consume the rest of the line...
|
||||||
|
var line = await Engine.ReadLineAsync (doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
ResponseText = (((string) token.Value) + line).TrimEnd ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (token.Type == ImapTokenType.OpenBracket) {
|
||||||
|
// Note: this is a work-around for broken IMAP servers like Office365.com that
|
||||||
|
// return RESP-CODES that are not preceded by "* OK " such as the example in
|
||||||
|
// issue #115 (https://github.com/jstedfast/MailKit/issues/115).
|
||||||
|
var code = await Engine.ParseResponseCodeAsync (false, doAsync, CancellationToken).ConfigureAwait (false);
|
||||||
|
RespCodes.Add (code);
|
||||||
|
} else {
|
||||||
|
// no clue what we got...
|
||||||
|
throw ImapEngine.UnexpectedToken ("Syntax error in response. Unexpected token: {0}", token);
|
||||||
|
}
|
||||||
|
} while (Status == ImapCommandStatus.Active);
|
||||||
|
|
||||||
|
if (Status == ImapCommandStatus.Active) {
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if (current >= parts.Count || result != ImapCommandResponse.None) {
|
||||||
|
Status = ImapCommandStatus.Complete;
|
||||||
|
Response = result;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
//
|
||||||
|
// ImapCommandException.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if SERIALIZABLE
|
||||||
|
using System.Security;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An exception that is thrown when an IMAP command returns NO or BAD.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The exception that is thrown when an IMAP command fails. Unlike a <see cref="ImapProtocolException"/>,
|
||||||
|
/// a <see cref="ImapCommandException"/> does not require the <see cref="ImapClient"/> to be reconnected.
|
||||||
|
/// </remarks>
|
||||||
|
#if SERIALIZABLE
|
||||||
|
[Serializable]
|
||||||
|
#endif
|
||||||
|
public class ImapCommandException : CommandException
|
||||||
|
{
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapCommandException"/> from the serialized data.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
[SecuritySafeCritical]
|
||||||
|
protected ImapCommandException (SerializationInfo info, StreamingContext context) : base (info, context)
|
||||||
|
{
|
||||||
|
Response = (ImapCommandResponse) info.GetValue ("Response", typeof (ImapCommandResponse));
|
||||||
|
ResponseText = info.GetString ("ResponseText");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new <see cref="ImapCommandException"/> based on the specified command name and <see cref="ImapCommand"/> state.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Create a new <see cref="ImapCommandException"/> based on the specified command name and <see cref="ImapCommand"/> state.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>A new command exception.</returns>
|
||||||
|
/// <param name="command">The command name.</param>
|
||||||
|
/// <param name="ic">The command state.</param>
|
||||||
|
internal static ImapCommandException Create (string command, ImapCommand ic)
|
||||||
|
{
|
||||||
|
var result = ic.Response.ToString ().ToUpperInvariant ();
|
||||||
|
string message, reason = null;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty (ic.ResponseText)) {
|
||||||
|
for (int i = ic.RespCodes.Count - 1; i >= 0; i--) {
|
||||||
|
if (ic.RespCodes[i].IsError && !string.IsNullOrEmpty (ic.RespCodes[i].Message)) {
|
||||||
|
reason = ic.RespCodes[i].Message;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reason = ic.ResponseText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty (reason))
|
||||||
|
message = string.Format ("The IMAP server replied to the '{0}' command with a '{1}' response: {2}", command, result, reason);
|
||||||
|
else
|
||||||
|
message = string.Format ("The IMAP server replied to the '{0}' command with a '{1}' response.", command, result);
|
||||||
|
|
||||||
|
return ic.Exception != null ? new ImapCommandException (ic.Response, reason, message, ic.Exception) : new ImapCommandException (ic.Response, reason, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapCommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="response">The IMAP command response.</param>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="responseText">The human-readable response text.</param>
|
||||||
|
/// <param name="innerException">The inner exception.</param>
|
||||||
|
public ImapCommandException (ImapCommandResponse response, string responseText, string message, Exception innerException) : base (message, innerException)
|
||||||
|
{
|
||||||
|
ResponseText = responseText;
|
||||||
|
Response = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapCommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="response">The IMAP command response.</param>
|
||||||
|
/// <param name="responseText">The human-readable response text.</param>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
public ImapCommandException (ImapCommandResponse response, string responseText, string message) : base (message)
|
||||||
|
{
|
||||||
|
ResponseText = responseText;
|
||||||
|
Response = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapCommandException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapCommandException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="response">The IMAP command response.</param>
|
||||||
|
/// <param name="responseText">The human-readable response text.</param>
|
||||||
|
public ImapCommandException (ImapCommandResponse response, string responseText)
|
||||||
|
{
|
||||||
|
ResponseText = responseText;
|
||||||
|
Response = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the IMAP command response.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the IMAP command response.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The IMAP command response.</value>
|
||||||
|
public ImapCommandResponse Response {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the human-readable IMAP command response text.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the human-readable IMAP command response text.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The response text.</value>
|
||||||
|
public string ResponseText {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, sets the <see cref="System.Runtime.Serialization.SerializationInfo"/>
|
||||||
|
/// with information about the exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Serializes the state of the <see cref="FolderNotFoundException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
[SecurityCritical]
|
||||||
|
public override void GetObjectData (SerializationInfo info, StreamingContext context)
|
||||||
|
{
|
||||||
|
base.GetObjectData (info, context);
|
||||||
|
|
||||||
|
info.AddValue ("Response", Response, typeof (ImapCommandResponse));
|
||||||
|
info.AddValue ("ResponseText", ResponseText);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// ImapCommandResult.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An enumeration of possible IMAP command responses.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An enumeration of possible IMAP command responses.
|
||||||
|
/// </remarks>
|
||||||
|
public enum ImapCommandResponse {
|
||||||
|
/// <summary>
|
||||||
|
/// No IMAP command response yet.
|
||||||
|
/// </summary>
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The command resulted in an "OK" response.
|
||||||
|
/// </summary>
|
||||||
|
Ok,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The command resulted in a "NO" response.
|
||||||
|
/// </summary>
|
||||||
|
No,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The command resulted in a "BAD" response.
|
||||||
|
/// </summary>
|
||||||
|
Bad
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
//
|
||||||
|
// ImapEncoding.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
static class ImapEncoding
|
||||||
|
{
|
||||||
|
const string utf7_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
|
||||||
|
|
||||||
|
static readonly byte[] utf7_rank = {
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255, 62, 63,255,255,255,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,255,255,255,
|
||||||
|
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
|
||||||
|
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
|
||||||
|
};
|
||||||
|
|
||||||
|
public static string Decode (string text)
|
||||||
|
{
|
||||||
|
var decoded = new StringBuilder ();
|
||||||
|
bool shifted = false;
|
||||||
|
int bits = 0, v = 0;
|
||||||
|
int index = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (index < text.Length) {
|
||||||
|
c = text[index++];
|
||||||
|
|
||||||
|
if (shifted) {
|
||||||
|
if (c == '-') {
|
||||||
|
// shifted back out of modified UTF-7
|
||||||
|
shifted = false;
|
||||||
|
bits = v = 0;
|
||||||
|
} else if (c > 127) {
|
||||||
|
// invalid UTF-7
|
||||||
|
return text;
|
||||||
|
} else {
|
||||||
|
byte rank = utf7_rank[(byte) c];
|
||||||
|
|
||||||
|
if (rank == 0xff) {
|
||||||
|
// invalid UTF-7
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = (v << 6) | rank;
|
||||||
|
bits += 6;
|
||||||
|
|
||||||
|
if (bits >= 16) {
|
||||||
|
char u = (char) ((v >> (bits - 16)) & 0xffff);
|
||||||
|
decoded.Append (u);
|
||||||
|
bits -= 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (c == '&' && index < text.Length) {
|
||||||
|
if (text[index] == '-') {
|
||||||
|
decoded.Append ('&');
|
||||||
|
index++;
|
||||||
|
} else {
|
||||||
|
// shifted into modified UTF-7
|
||||||
|
shifted = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
decoded.Append (c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoded.ToString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Utf7ShiftOut (StringBuilder output, int u, int bits)
|
||||||
|
{
|
||||||
|
if (bits > 0) {
|
||||||
|
int x = (u << (6 - bits)) & 0x3f;
|
||||||
|
output.Append (utf7_alphabet[x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.Append ('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Encode (string text)
|
||||||
|
{
|
||||||
|
var encoded = new StringBuilder ();
|
||||||
|
bool shifted = false;
|
||||||
|
int bits = 0, u = 0;
|
||||||
|
|
||||||
|
for (int index = 0; index < text.Length; index++) {
|
||||||
|
char c = text[index];
|
||||||
|
|
||||||
|
if (c >= 0x20 && c < 0x7f) {
|
||||||
|
// characters with octet values 0x20-0x25 and 0x27-0x7e
|
||||||
|
// represent themselves while 0x26 ("&") is represented
|
||||||
|
// by the two-octet sequence "&-"
|
||||||
|
|
||||||
|
if (shifted) {
|
||||||
|
Utf7ShiftOut (encoded, u, bits);
|
||||||
|
shifted = false;
|
||||||
|
bits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 0x26)
|
||||||
|
encoded.Append ("&-");
|
||||||
|
else
|
||||||
|
encoded.Append (c);
|
||||||
|
} else {
|
||||||
|
// base64 encode
|
||||||
|
if (!shifted) {
|
||||||
|
encoded.Append ('&');
|
||||||
|
shifted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u = (u << 16) | (c & 0xffff);
|
||||||
|
bits += 16;
|
||||||
|
|
||||||
|
while (bits >= 6) {
|
||||||
|
int x = (u >> (bits - 6)) & 0x3f;
|
||||||
|
encoded.Append (utf7_alphabet[x]);
|
||||||
|
bits -= 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shifted)
|
||||||
|
Utf7ShiftOut (encoded, u, bits);
|
||||||
|
|
||||||
|
return encoded.ToString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,692 @@
|
||||||
|
//
|
||||||
|
// ImapFolderFetch.cs
|
||||||
|
//
|
||||||
|
// Authors: Steffen Kieß <s-kiess@web.de>
|
||||||
|
// Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using MimeKit;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event group used with the NOTIFY command.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An IMAP event group used with the NOTIFY command.
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class ImapEventGroup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEventGroup"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEventGroup"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="mailboxFilter">The mailbox filter.</param>
|
||||||
|
/// <param name="events">The list of IMAP events.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="mailboxFilter"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="events"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public ImapEventGroup (ImapMailboxFilter mailboxFilter, IList<ImapEvent> events)
|
||||||
|
{
|
||||||
|
if (mailboxFilter == null)
|
||||||
|
throw new ArgumentNullException (nameof (mailboxFilter));
|
||||||
|
|
||||||
|
if (events == null)
|
||||||
|
throw new ArgumentNullException (nameof (events));
|
||||||
|
|
||||||
|
MailboxFilter = mailboxFilter;
|
||||||
|
Events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the mailbox filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the mailbox filter.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The mailbox filter.</value>
|
||||||
|
public ImapMailboxFilter MailboxFilter {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the list of IMAP events.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the list of IMAP events.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The events.</value>
|
||||||
|
public IList<ImapEvent> Events {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format the IMAP NOTIFY command for this particular IMAP event group.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Formats the IMAP NOTIFY command for this particular IMAP event group.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine.</param>
|
||||||
|
/// <param name="command">The IMAP command builder.</param>
|
||||||
|
/// <param name="args">The IMAP command argument builder.</param>
|
||||||
|
/// <param name="notifySelectedNewExpunge">Gets set to <c>true</c> if the NOTIFY command requests the MessageNew or
|
||||||
|
/// MessageExpunged events for a SELECTED or SELECTED-DELAYED mailbox filter; otherwise it is left unchanged.</param>
|
||||||
|
internal void Format (ImapEngine engine, StringBuilder command, IList<object> args, ref bool notifySelectedNewExpunge)
|
||||||
|
{
|
||||||
|
bool isSelectedFilter = MailboxFilter == ImapMailboxFilter.Selected || MailboxFilter == ImapMailboxFilter.SelectedDelayed;
|
||||||
|
|
||||||
|
command.Append ("(");
|
||||||
|
MailboxFilter.Format (engine, command, args);
|
||||||
|
command.Append (" ");
|
||||||
|
|
||||||
|
if (Events.Count > 0) {
|
||||||
|
var haveAnnotationChange = false;
|
||||||
|
var haveMessageExpunge = false;
|
||||||
|
var haveMessageNew = false;
|
||||||
|
var haveFlagChange = false;
|
||||||
|
|
||||||
|
command.Append ("(");
|
||||||
|
|
||||||
|
for (int i = 0; i < Events.Count; i++) {
|
||||||
|
var @event = Events[i];
|
||||||
|
|
||||||
|
if (isSelectedFilter && !@event.IsMessageEvent)
|
||||||
|
throw new InvalidOperationException ("Only message events may be specified when SELECTED or SELECTED-DELAYED is used.");
|
||||||
|
|
||||||
|
if (@event is ImapEvent.MessageNew)
|
||||||
|
haveMessageNew = true;
|
||||||
|
else if (@event == ImapEvent.MessageExpunge)
|
||||||
|
haveMessageExpunge = true;
|
||||||
|
else if (@event == ImapEvent.FlagChange)
|
||||||
|
haveFlagChange = true;
|
||||||
|
else if (@event == ImapEvent.AnnotationChange)
|
||||||
|
haveAnnotationChange = true;
|
||||||
|
|
||||||
|
if (i > 0)
|
||||||
|
command.Append (" ");
|
||||||
|
|
||||||
|
@event.Format (engine, command, args, isSelectedFilter);
|
||||||
|
}
|
||||||
|
command.Append (")");
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc5465#section-5
|
||||||
|
if ((haveMessageNew && !haveMessageExpunge) || (!haveMessageNew && haveMessageExpunge))
|
||||||
|
throw new InvalidOperationException ("If MessageNew or MessageExpunge is specified, both must be specified.");
|
||||||
|
|
||||||
|
if ((haveFlagChange || haveAnnotationChange) && (!haveMessageNew || !haveMessageExpunge))
|
||||||
|
throw new InvalidOperationException ("If FlagChange and/or AnnotationChange are specified, MessageNew and MessageExpunge must also be specified.");
|
||||||
|
|
||||||
|
notifySelectedNewExpunge = (haveMessageNew || haveMessageExpunge) && MailboxFilter == ImapMailboxFilter.Selected;
|
||||||
|
} else {
|
||||||
|
command.Append ("NONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
command.Append (")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter for use with the NOTIFY command.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An IMAP mailbox filter for use with the NOTIFY command.
|
||||||
|
/// </remarks>
|
||||||
|
public class ImapMailboxFilter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter specifying that the client wants immediate notifications for
|
||||||
|
/// the currently selected folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <c>SELECTED</c> mailbox specifier requires the server to send immediate
|
||||||
|
/// notifications for the currently selected mailbox about all specified
|
||||||
|
/// message events.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapMailboxFilter Selected = new ImapMailboxFilter ("SELECTED");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter specifying the currently selected folder but delays notifications
|
||||||
|
/// until a command has been issued.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <c>SELECTED-DELAYED</c> mailbox specifier requires the server to delay a
|
||||||
|
/// <see cref="ImapEvent.MessageExpunge"/> event until the client issues a command that allows
|
||||||
|
/// returning information about expunged messages (see
|
||||||
|
/// <a href="https://tools.ietf.org/html/rfc3501#section-7.4.1">Section 7.4.1 of RFC3501]</a>
|
||||||
|
/// for more details), for example, till a <c>NOOP</c> or an <c>IDLE</c> command has been issued.
|
||||||
|
/// When <c>SELECTED-DELAYED</c> is specified, the server MAY also delay returning other message
|
||||||
|
/// events until the client issues one of the commands specified above, or it MAY return them
|
||||||
|
/// immediately.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapMailboxFilter SelectedDelayed = new ImapMailboxFilter ("SELECTED-DELAYED");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter specifying the currently selected folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <c>INBOXES</c> mailbox specifier refers to all selectable mailboxes in the user's
|
||||||
|
/// personal namespace(s) to which messages may be delivered by a Message Delivery Agent (MDA).
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the IMAP server cannot easily compute this set, it MUST treat <see cref="Inboxes"/>
|
||||||
|
/// as equivalent to <see cref="Personal"/>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapMailboxFilter Inboxes = new ImapMailboxFilter ("INBOXES");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter specifying all selectable folders within the user's personal namespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The <c>PERSONAL</c> mailbox specifier refers to all selectable folders within the user's personal namespace.
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapMailboxFilter Personal = new ImapMailboxFilter ("PERSONAL");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter that refers to all subscribed folders.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <c>SUBSCRIBED</c> mailbox specifier refers to all folders subscribed to by the user.</para>
|
||||||
|
/// <para>If the subscription list changes, the server MUST reevaluate the list.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapMailboxFilter Subscribed = new ImapMailboxFilter ("SUBSCRIBED");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter that specifies a list of folders to receive notifications about.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An IMAP mailbox filter that specifies a list of folders to receive notifications about.
|
||||||
|
/// </remarks>
|
||||||
|
public class Mailboxes : ImapMailboxFilter
|
||||||
|
{
|
||||||
|
readonly ImapFolder[] folders;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Mailboxes"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Mailboxes"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folders">The list of folders to watch for events.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folders"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para>The list of <paramref name="folders"/> is empty.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The list of <paramref name="folders"/> contains folders that are not of
|
||||||
|
/// type <see cref="ImapFolder"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public Mailboxes (IList<IMailFolder> folders) : this ("MAILBOXES", folders)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Mailboxes"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Mailboxes"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folders">The list of folders to watch for events.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folders"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para>The list of <paramref name="folders"/> is empty.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The list of <paramref name="folders"/> contains folders that are not of
|
||||||
|
/// type <see cref="ImapFolder"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public Mailboxes (params IMailFolder[] folders) : this ("MAILBOXES", folders)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Mailboxes"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Mailboxes"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="name">The name of the mailbox filter.</param>
|
||||||
|
/// <param name="folders">The list of folders to watch for events.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folders"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para>The list of <paramref name="folders"/> is empty.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The list of <paramref name="folders"/> contains folders that are not of
|
||||||
|
/// type <see cref="ImapFolder"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
internal Mailboxes (string name, IList<IMailFolder> folders) : base (name)
|
||||||
|
{
|
||||||
|
if (folders == null)
|
||||||
|
throw new ArgumentNullException (nameof (folders));
|
||||||
|
|
||||||
|
if (folders.Count == 0)
|
||||||
|
throw new ArgumentException ("Must supply at least one folder.", nameof (folders));
|
||||||
|
|
||||||
|
this.folders = new ImapFolder[folders.Count];
|
||||||
|
for (int i = 0; i < folders.Count; i++) {
|
||||||
|
if (!(folders[i] is ImapFolder folder))
|
||||||
|
throw new ArgumentException ("All folders must be ImapFolders.", nameof (folders));
|
||||||
|
|
||||||
|
this.folders[i] = folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Formats the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine.</param>
|
||||||
|
/// <param name="command">The IMAP command builder.</param>
|
||||||
|
/// <param name="args">The IMAP command argument builder.</param>
|
||||||
|
internal override void Format (ImapEngine engine, StringBuilder command, IList<object> args)
|
||||||
|
{
|
||||||
|
command.Append (Name);
|
||||||
|
command.Append (' ');
|
||||||
|
|
||||||
|
// FIXME: should we verify that each ImapFolder belongs to this ImapEngine?
|
||||||
|
|
||||||
|
if (folders.Length == 1) {
|
||||||
|
command.Append ("%F");
|
||||||
|
args.Add (folders[0]);
|
||||||
|
} else {
|
||||||
|
command.Append ("(");
|
||||||
|
|
||||||
|
for (int i = 0; i < folders.Length; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
command.Append (" ");
|
||||||
|
command.Append ("%F");
|
||||||
|
args.Add (folders[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
command.Append (")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP mailbox filter that specifies a list of folder subtrees to get notifications about.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The client will receive notifications for each specified folder plus all selectable
|
||||||
|
/// folders that are subordinate to any of the specified folders.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public class Subtree : Mailboxes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Subtree"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Subtree"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folders">The list of folders to watch for events.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folders"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para>The list of <paramref name="folders"/> is empty.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The list of <paramref name="folders"/> contains folders that are not of
|
||||||
|
/// type <see cref="ImapFolder"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public Subtree (IList<IMailFolder> folders) : base ("SUBTREE", folders)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Subtree"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter.Subtree"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="folders">The list of folders to watch for events.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="folders"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <para>The list of <paramref name="folders"/> is empty.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The list of <paramref name="folders"/> contains folders that are not of
|
||||||
|
/// type <see cref="ImapFolder"/>.</para>
|
||||||
|
/// </exception>
|
||||||
|
public Subtree (params IMailFolder[] folders) : base ("SUBTREE", folders)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapMailboxFilter"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="name">The name of the mailbox filter.</param>
|
||||||
|
internal ImapMailboxFilter (string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the mailbox filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the name of the mailbox filter.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Formats the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine.</param>
|
||||||
|
/// <param name="command">The IMAP command builder.</param>
|
||||||
|
/// <param name="args">The IMAP command argument builder.</param>
|
||||||
|
internal virtual void Format (ImapEngine engine, StringBuilder command, IList<object> args)
|
||||||
|
{
|
||||||
|
command.Append (Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP notification event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// An IMAP notification event.
|
||||||
|
/// </remarks>
|
||||||
|
public class ImapEvent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for expunged messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>If the expunged message or messages are in the selected mailbox, the server notifies the client
|
||||||
|
/// using <see cref="IMailFolder.MessageExpunged"/> (or <see cref="IMailFolder.MessagesVanished"/> if
|
||||||
|
/// the <a href="https://tools.ietf.org/html/rfc5162">QRESYNC</a> extension has been enabled via
|
||||||
|
/// <see cref="ImapClient.EnableQuickResync(System.Threading.CancellationToken)"/> or
|
||||||
|
/// <see cref="ImapClient.EnableQuickResyncAsync(System.Threading.CancellationToken)"/>).</para>
|
||||||
|
/// <para>If the expunged message or messages are in another mailbox, the <see cref="IMailFolder.UidNext"/>
|
||||||
|
/// and <see cref="IMailFolder.Count"/> properties will be updated and the appropriate
|
||||||
|
/// <see cref="IMailFolder.UidNextChanged"/> and <see cref="IMailFolder.CountChanged"/> events will be
|
||||||
|
/// emitted for the relevant folder. If the <a href="https://tools.ietf.org/html/rfc5162">QRESYNC</a>
|
||||||
|
/// extension is enabled, the <see cref="IMailFolder.HighestModSeq"/> property will also be updated and
|
||||||
|
/// the <see cref="IMailFolder.HighestModSeqChanged"/> event will be emitted.</para>
|
||||||
|
/// <note type="note">if a client requests <see cref="MessageExpunge"/> with the <see cref="ImapMailboxFilter.Selected"/>
|
||||||
|
/// mailbox specifier, the meaning of a message index can change at any time, so the client cannot use
|
||||||
|
/// message indexes in commands anymore. The client MUST use API variants that take <see cref="UniqueId"/> or
|
||||||
|
/// a <see cref="IList{UniqueId}"/>. The meaning of <c>*</c>* can also change when messages are added or expunged.
|
||||||
|
/// A client wishing to keep using message indexes can either use the <see cref="ImapMailboxFilter.SelectedDelayed"/>
|
||||||
|
/// mailbox specifier or can avoid using the <see cref="MessageExpunge"/> event entirely.</note>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent MessageExpunge = new ImapEvent ("MessageExpunge", true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for message flag changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>If the <see cref="FlagChange"/> notification arrives for a message located in the currently selected
|
||||||
|
/// folder, then that folder will emit a <see cref="IMailFolder.MessageFlagsChanged"/> event as well as a
|
||||||
|
/// <see cref="IMailFolder.MessageSummaryFetched"/> event with an appropriately populated
|
||||||
|
/// <see cref="IMessageSummary"/>.</para>
|
||||||
|
/// <para>On the other hand, if the <see cref="FlagChange"/> notification arrives for a message that is not
|
||||||
|
/// located in the currently selected folder, then the events that are emitted will depend on the
|
||||||
|
/// <see cref="ImapCapabilities"/> of the IMAP server.</para>
|
||||||
|
/// <para>If the server supports the <see cref="ImapCapabilities.CondStore"/> capability (or the
|
||||||
|
/// <see cref="ImapCapabilities.QuickResync"/> capability and the client has enabled it via
|
||||||
|
/// <see cref="ImapClient.EnableQuickResync(System.Threading.CancellationToken)"/>), then the
|
||||||
|
/// <see cref="IMailFolder.HighestModSeqChanged"/> event will be emitted as well as the
|
||||||
|
/// <see cref="IMailFolder.UidValidityChanged"/> event (if the latter has changed). If the number of
|
||||||
|
/// seen messages has changed, then the <see cref="IMailFolder.UnreadChanged"/> event may also be emitted.</para>
|
||||||
|
/// <para>If the server does not support either the <see cref="ImapCapabilities.CondStore"/> capability nor
|
||||||
|
/// the <see cref="ImapCapabilities.QuickResync"/> capability and the client has not enabled the later capability
|
||||||
|
/// via <see cref="ImapClient.EnableQuickResync(System.Threading.CancellationToken)"/>, then the server may choose
|
||||||
|
/// only to notify the client of <see cref="IMailFolder.UidValidity"/> changes by emitting the
|
||||||
|
/// <see cref="IMailFolder.UidValidityChanged"/> event.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent FlagChange = new ImapEvent ("FlagChange", true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for message annotation changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>If the <see cref="AnnotationChange"/> notification arrives for a message located in the currently selected
|
||||||
|
/// folder, then that folder will emit a <see cref="IMailFolder.AnnotationsChanged"/> event as well as a
|
||||||
|
/// <see cref="IMailFolder.MessageSummaryFetched"/> event with an appropriately populated
|
||||||
|
/// <see cref="IMessageSummary"/>.</para>
|
||||||
|
/// <para>On the other hand, if the <see cref="AnnotationChange"/> notification arrives for a message that is not
|
||||||
|
/// located in the currently selected folder, then the events that are emitted will depend on the
|
||||||
|
/// <see cref="ImapCapabilities"/> of the IMAP server.</para>
|
||||||
|
/// <para>If the server supports the <see cref="ImapCapabilities.CondStore"/> capability (or the
|
||||||
|
/// <see cref="ImapCapabilities.QuickResync"/> capability and the client has enabled it via
|
||||||
|
/// <see cref="ImapClient.EnableQuickResync(System.Threading.CancellationToken)"/>), then the
|
||||||
|
/// <see cref="IMailFolder.HighestModSeqChanged"/> event will be emitted as well as the
|
||||||
|
/// <see cref="IMailFolder.UidValidityChanged"/> event (if the latter has changed). If the number of
|
||||||
|
/// seen messages has changed, then the <see cref="IMailFolder.UnreadChanged"/> event may also be emitted.</para>
|
||||||
|
/// <para>If the server does not support either the <see cref="ImapCapabilities.CondStore"/> capability nor
|
||||||
|
/// the <see cref="ImapCapabilities.QuickResync"/> capability and the client has not enabled the later capability
|
||||||
|
/// via <see cref="ImapClient.EnableQuickResync(System.Threading.CancellationToken)"/>, then the server may choose
|
||||||
|
/// only to notify the client of <see cref="IMailFolder.UidValidity"/> changes by emitting the
|
||||||
|
/// <see cref="IMailFolder.UidValidityChanged"/> event.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent AnnotationChange = new ImapEvent ("AnnotationChange", true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AN IMAP event notification for folders that have been created, deleted, or renamed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>These notifications are sent if an affected mailbox name was created, deleted, or renamed.</para>
|
||||||
|
/// <para>As these notifications are received by the client, the apropriate will be emitted:
|
||||||
|
/// <see cref="MailStore.FolderCreated"/>, <see cref="IMailFolder.Deleted"/>, or
|
||||||
|
/// <see cref="IMailFolder.Renamed"/>, respectively.</para>
|
||||||
|
/// <note type="info">If the server supports <see cref="ImapCapabilities.Acl"/>, granting or revocation of the
|
||||||
|
/// <see cref="AccessRight.LookupFolder"/> right to the current user on the affected folder will also be
|
||||||
|
/// considered folder creation or deletion, respectively. If a folder is created or deleted, the folder itself
|
||||||
|
/// and its direct parent (whether it is an existing folder or not) are considered to be affected.</note>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent MailboxName = new ImapEvent ("MailboxName", false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for folders who have had their subscription status changed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>This event requests that the server notifies the client of any subscription changes,
|
||||||
|
/// causing the <see cref="IMailFolder.Subscribed"/> or <see cref="IMailFolder.Unsubscribed"/>
|
||||||
|
/// events to be emitted accordingly on the affected <see cref="IMailFolder"/>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent SubscriptionChange = new ImapEvent ("SubscriptionChange", false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for changes to folder metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Support for this event type is OPTIONAL unless <see cref="ImapCapabilities.Metadata"/> is supported
|
||||||
|
/// by the server, in which case support for this event type is REQUIRED.</para>
|
||||||
|
/// <para>If the server does support this event, then the <see cref="IMailFolder.MetadataChanged"/> event
|
||||||
|
/// will be emitted whenever metadata changes for any folder included in the <see cref="ImapMailboxFilter"/>.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent MailboxMetadataChange = new ImapEvent ("MailboxMetadataChange", false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for changes to server metadata.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Support for this event type is OPTIONAL unless <see cref="ImapCapabilities.Metadata"/> is supported
|
||||||
|
/// by the server, in which case support for this event type is REQUIRED.</para>
|
||||||
|
/// <para>If the server does support this event, then the <see cref="IMailStore.MetadataChanged"/> event
|
||||||
|
/// will be emitted whenever metadata changes.</para>
|
||||||
|
/// </remarks>
|
||||||
|
public static readonly ImapEvent ServerMetadataChange = new ImapEvent ("ServerMetadataChange", false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="name">The name of the IMAP event.</param>
|
||||||
|
/// <param name="isMessageEvent"><c>true</c> if the event is a message event; otherwise, <c>false</c>.</param>
|
||||||
|
internal ImapEvent (string name, bool isMessageEvent)
|
||||||
|
{
|
||||||
|
IsMessageEvent = isMessageEvent;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get whether or not this <see cref="T:MailKit.Net.Imap.ImapEvent"/> is a message event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets whether or not this <see cref="T:MailKit.Net.Imap.ImapEvent"/> is a message event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if is message event; otherwise, <c>false</c>.</value>
|
||||||
|
internal bool IsMessageEvent {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the IMAP event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the name of the IMAP event.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the IMAP event.</value>
|
||||||
|
public string Name {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Formats the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine.</param>
|
||||||
|
/// <param name="command">The IMAP command builder.</param>
|
||||||
|
/// <param name="args">The IMAP command argument builder.</param>
|
||||||
|
/// <param name="isSelectedFilter"><c>true</c> if the event is being registered for a
|
||||||
|
/// <see cref="ImapMailboxFilter.Selected"/> or <see cref="ImapMailboxFilter.SelectedDelayed"/>
|
||||||
|
/// mailbox filter.</param>
|
||||||
|
internal virtual void Format (ImapEngine engine, StringBuilder command, IList<object> args, bool isSelectedFilter)
|
||||||
|
{
|
||||||
|
command.Append (Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP event notification for new or appended messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An IMAP event notification for new or appended messages.</para>
|
||||||
|
/// <para>If the new or appended message is in the selected folder, the folder will emit the
|
||||||
|
/// <see cref="IMailFolder.CountChanged"/> event, followed by a
|
||||||
|
/// <see cref="IMailFolder.MessageSummaryFetched"/> event containing the information requested by the client.</para>
|
||||||
|
/// <note type="note">These events will not be emitted for any message created by the client on this particular folder
|
||||||
|
/// as a result of, for example, a call to
|
||||||
|
/// <see cref="IMailFolder.Append(MimeMessage, MessageFlags, System.Threading.CancellationToken, ITransferProgress)"/>
|
||||||
|
/// or <see cref="IMailFolder.CopyTo(IList{UniqueId}, IMailFolder, System.Threading.CancellationToken)"/>.</note>
|
||||||
|
/// </remarks>
|
||||||
|
public class MessageNew : ImapEvent
|
||||||
|
{
|
||||||
|
readonly MessageSummaryItems items;
|
||||||
|
readonly HashSet<string> headers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent.MessageNew"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent.MessageNew"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="items">The message summary items to automatically retrieve for new messages.</param>
|
||||||
|
public MessageNew (MessageSummaryItems items = MessageSummaryItems.None) : base ("MessageNew", true)
|
||||||
|
{
|
||||||
|
headers = ImapFolder.EmptyHeaderFields;
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent.MessageNew"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent.MessageNew"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="items">The message summary items to automatically retrieve for new messages.</param>
|
||||||
|
/// <param name="headers">Additional message headers to retrieve for new messages.</param>
|
||||||
|
public MessageNew (MessageSummaryItems items, HashSet<HeaderId> headers) : this (items)
|
||||||
|
{
|
||||||
|
this.headers = ImapUtils.GetUniqueHeaders (headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent.MessageNew"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="T:MailKit.Net.Imap.ImapEvent.MessageNew"/> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="items">The message summary items to automatically retrieve for new messages.</param>
|
||||||
|
/// <param name="headers">Additional message headers to retrieve for new messages.</param>
|
||||||
|
public MessageNew (MessageSummaryItems items, HashSet<string> headers) : this (items)
|
||||||
|
{
|
||||||
|
this.headers = ImapUtils.GetUniqueHeaders (headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Format the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Formats the IMAP NOTIFY command for this particular IMAP mailbox filter.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="engine">The IMAP engine.</param>
|
||||||
|
/// <param name="command">The IMAP command builder.</param>
|
||||||
|
/// <param name="args">The IMAP command argument builder.</param>
|
||||||
|
/// <param name="isSelectedFilter"><c>true</c> if the event is being registered for a
|
||||||
|
/// <see cref="ImapMailboxFilter.Selected"/> or <see cref="ImapMailboxFilter.SelectedDelayed"/>
|
||||||
|
/// mailbox filter.</param>
|
||||||
|
internal override void Format (ImapEngine engine, StringBuilder command, IList<object> args, bool isSelectedFilter)
|
||||||
|
{
|
||||||
|
command.Append (Name);
|
||||||
|
|
||||||
|
if (items == MessageSummaryItems.None && headers.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!isSelectedFilter)
|
||||||
|
throw new InvalidOperationException ("The MessageNew event cannot have any parameters for mailbox filters other than SELECTED and SELECTED-DELAYED.");
|
||||||
|
|
||||||
|
var xitems = items;
|
||||||
|
bool previewText;
|
||||||
|
|
||||||
|
command.Append (" ");
|
||||||
|
command.Append (ImapFolder.FormatSummaryItems (engine, ref xitems, headers, out previewText, isNotify: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,567 @@
|
||||||
|
//
|
||||||
|
// ImapFolderAnnotations.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap
|
||||||
|
{
|
||||||
|
public partial class ImapFolder
|
||||||
|
{
|
||||||
|
async Task<IList<UniqueId>> StoreAsync (IList<UniqueId> uids, ulong? modseq, IList<Annotation> annotations, bool doAsync, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (uids == null)
|
||||||
|
throw new ArgumentNullException (nameof (uids));
|
||||||
|
|
||||||
|
if (modseq.HasValue && !supportsModSeq)
|
||||||
|
throw new NotSupportedException ("The ImapFolder does not support mod-sequences.");
|
||||||
|
|
||||||
|
if (annotations == null)
|
||||||
|
throw new ArgumentNullException (nameof (annotations));
|
||||||
|
|
||||||
|
CheckState (true, true);
|
||||||
|
|
||||||
|
if (AnnotationAccess == AnnotationAccess.None)
|
||||||
|
throw new NotSupportedException ("The ImapFolder does not support annotations.");
|
||||||
|
|
||||||
|
if (uids.Count == 0 || annotations.Count == 0)
|
||||||
|
return new UniqueId[0];
|
||||||
|
|
||||||
|
var builder = new StringBuilder ("UID STORE %s ");
|
||||||
|
var values = new List<object> ();
|
||||||
|
UniqueIdSet unmodified = null;
|
||||||
|
|
||||||
|
if (modseq.HasValue)
|
||||||
|
builder.AppendFormat (CultureInfo.InvariantCulture, "(UNCHANGEDSINCE {0}) ", modseq.Value);
|
||||||
|
|
||||||
|
ImapUtils.FormatAnnotations (builder, annotations, values, true);
|
||||||
|
builder.Append ("\r\n");
|
||||||
|
|
||||||
|
var command = builder.ToString ();
|
||||||
|
var args = values.ToArray ();
|
||||||
|
|
||||||
|
foreach (var ic in Engine.QueueCommands (cancellationToken, this, command, uids, args)) {
|
||||||
|
await Engine.RunAsync (ic, doAsync).ConfigureAwait (false);
|
||||||
|
|
||||||
|
ProcessResponseCodes (ic, null);
|
||||||
|
|
||||||
|
if (ic.Response != ImapCommandResponse.Ok)
|
||||||
|
throw ImapCommandException.Create ("STORE", ic);
|
||||||
|
|
||||||
|
ProcessUnmodified (ic, ref unmodified, modseq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unmodified == null)
|
||||||
|
return new UniqueId[0];
|
||||||
|
|
||||||
|
return unmodified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store the annotations for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Stores the annotations for the specified messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="uids">The UIDs of the messages.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="uids"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="uids"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The <see cref="ImapFolder"/> does not support annotations.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override void Store (IList<UniqueId> uids, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
StoreAsync (uids, null, annotations, false, cancellationToken).GetAwaiter ().GetResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously store the annotations for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously stores the annotations for the specified messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="uids">The UIDs of the messages.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="uids"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="uids"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The <see cref="ImapFolder"/> does not support annotations.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task StoreAsync (IList<UniqueId> uids, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return StoreAsync (uids, null, annotations, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Stores the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The unique IDs of the messages that were not updated.</returns>
|
||||||
|
/// <param name="uids">The UIDs of the messages.</param>
|
||||||
|
/// <param name="modseq">The mod-sequence value.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="uids"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="uids"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support annotations.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support mod-sequences.</para>
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override IList<UniqueId> Store (IList<UniqueId> uids, ulong modseq, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return StoreAsync (uids, modseq, annotations, false, cancellationToken).GetAwaiter ().GetResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously store the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously stores the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The unique IDs of the messages that were not updated.</returns>
|
||||||
|
/// <param name="uids">The UIDs of the messages.</param>
|
||||||
|
/// <param name="modseq">The mod-sequence value.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="uids"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="uids"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support annotations.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support mod-sequences.</para>
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<IList<UniqueId>> StoreAsync (IList<UniqueId> uids, ulong modseq, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return StoreAsync (uids, modseq, annotations, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<IList<int>> StoreAsync (IList<int> indexes, ulong? modseq, IList<Annotation> annotations, bool doAsync, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (indexes == null)
|
||||||
|
throw new ArgumentNullException (nameof (indexes));
|
||||||
|
|
||||||
|
if (modseq.HasValue && !supportsModSeq)
|
||||||
|
throw new NotSupportedException ("The ImapFolder does not support mod-sequences.");
|
||||||
|
|
||||||
|
if (annotations == null)
|
||||||
|
throw new ArgumentNullException (nameof (annotations));
|
||||||
|
|
||||||
|
CheckState (true, true);
|
||||||
|
|
||||||
|
if (AnnotationAccess == AnnotationAccess.None)
|
||||||
|
throw new NotSupportedException ("The ImapFolder does not support annotations.");
|
||||||
|
|
||||||
|
if (indexes.Count == 0 || annotations.Count == 0)
|
||||||
|
return new int[0];
|
||||||
|
|
||||||
|
var set = ImapUtils.FormatIndexSet (indexes);
|
||||||
|
var builder = new StringBuilder ("STORE ");
|
||||||
|
var values = new List<object> ();
|
||||||
|
|
||||||
|
builder.AppendFormat ("{0} ", set);
|
||||||
|
|
||||||
|
if (modseq.HasValue)
|
||||||
|
builder.AppendFormat (CultureInfo.InvariantCulture, "(UNCHANGEDSINCE {0}) ", modseq.Value);
|
||||||
|
|
||||||
|
ImapUtils.FormatAnnotations (builder, annotations, values, true);
|
||||||
|
builder.Append ("\r\n");
|
||||||
|
|
||||||
|
var command = builder.ToString ();
|
||||||
|
var args = values.ToArray ();
|
||||||
|
|
||||||
|
var ic = Engine.QueueCommand (cancellationToken, this, command, args);
|
||||||
|
|
||||||
|
await Engine.RunAsync (ic, doAsync).ConfigureAwait (false);
|
||||||
|
|
||||||
|
ProcessResponseCodes (ic, null);
|
||||||
|
|
||||||
|
if (ic.Response != ImapCommandResponse.Ok)
|
||||||
|
throw ImapCommandException.Create ("STORE", ic);
|
||||||
|
|
||||||
|
return GetUnmodified (ic, modseq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store the annotations for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Stores the annotations for the specified messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="indexes"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="indexes"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The <see cref="ImapFolder"/> does not support annotations.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override void Store (IList<int> indexes, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
StoreAsync (indexes, null, annotations, false, cancellationToken).GetAwaiter ().GetResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously store the annotations for the specified messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously stores the annotations for the specified messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="indexes"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="indexes"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The <see cref="ImapFolder"/> does not support annotations.
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task StoreAsync (IList<int> indexes, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return StoreAsync (indexes, null, annotations, true, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Stores the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The indexes of the messages that were not updated.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="modseq">The mod-sequence value.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="indexes"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="indexes"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support annotations.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support mod-sequences.</para>
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override IList<int> Store (IList<int> indexes, ulong modseq, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return StoreAsync (indexes, modseq, annotations, false, cancellationToken).GetAwaiter ().GetResult ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously store the annotations for the specified messages only if their mod-sequence value is less than the specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Asynchronously stores the annotations for the specified messages only if their mod-sequence value is less than the specified value.s
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The indexes of the messages that were not updated.</returns>
|
||||||
|
/// <param name="indexes">The indexes of the messages.</param>
|
||||||
|
/// <param name="modseq">The mod-sequence value.</param>
|
||||||
|
/// <param name="annotations">The annotations to store.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <para><paramref name="indexes"/> is <c>null</c>.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para><paramref name="annotations"/> is <c>null</c>.</para>
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// One or more of the <paramref name="indexes"/> is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <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="ServiceNotAuthenticatedException">
|
||||||
|
/// The <see cref="ImapClient"/> is not authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="FolderNotOpenException">
|
||||||
|
/// The <see cref="ImapFolder"/> is not currently open in read-write mode.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Cannot store annotations without any properties defined.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support annotations.</para>
|
||||||
|
/// <para>-or-</para>
|
||||||
|
/// <para>The <see cref="ImapFolder"/> does not support mod-sequences.</para>
|
||||||
|
/// </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="ImapProtocolException">
|
||||||
|
/// The server's response contained unexpected tokens.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ImapCommandException">
|
||||||
|
/// The server replied with a NO or BAD response.
|
||||||
|
/// </exception>
|
||||||
|
public override Task<IList<int>> StoreAsync (IList<int> indexes, ulong modseq, IList<Annotation> annotations, CancellationToken cancellationToken = default (CancellationToken))
|
||||||
|
{
|
||||||
|
return StoreAsync (indexes, modseq, annotations, true, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
//
|
||||||
|
// ImapFolderInfo.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor arguments for <see cref="ImapFolder"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Constructor arguments for <see cref="ImapFolder"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public sealed class ImapFolderConstructorArgs
|
||||||
|
{
|
||||||
|
internal readonly string EncodedName;
|
||||||
|
internal readonly ImapEngine Engine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapFolderConstructorArgs"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="engine">The IMAP command engine.</param>
|
||||||
|
/// <param name="encodedName">The encoded name.</param>
|
||||||
|
/// <param name="attributes">The attributes.</param>
|
||||||
|
/// <param name="delim">The directory separator.</param>
|
||||||
|
internal ImapFolderConstructorArgs (ImapEngine engine, string encodedName, FolderAttributes attributes, char delim) : this ()
|
||||||
|
{
|
||||||
|
FullName = engine.DecodeMailboxName (encodedName);
|
||||||
|
Name = GetBaseName (FullName, delim);
|
||||||
|
DirectorySeparator = delim;
|
||||||
|
EncodedName = encodedName;
|
||||||
|
Attributes = attributes;
|
||||||
|
Engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImapFolderConstructorArgs ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the folder attributes.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the folder attributes.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The folder attributes.</value>
|
||||||
|
public FolderAttributes Attributes {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the directory separator.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the directory separator.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The directory separator.</value>
|
||||||
|
public char DirectorySeparator {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the full name of the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is the equivalent of the full path of a file on a file system.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The full name of the folder.</value>
|
||||||
|
public string FullName {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the name of the folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is the equivalent of the file name of a file on the file system.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the folder.</value>
|
||||||
|
public string Name {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string GetBaseName (string fullName, char delim)
|
||||||
|
{
|
||||||
|
var names = fullName.Split (new [] { delim }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
return names.Length > 0 ? names[names.Length - 1] : fullName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,217 @@
|
||||||
|
//
|
||||||
|
// ImapImplementation.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// The details of an IMAP client or server implementation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Allows an IMAP client and server to share their implementation details
|
||||||
|
/// with each other for the purposes of debugging.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
public class ImapImplementation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapImplementation"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="MailKit.Net.Imap.ImapImplementation"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
public ImapImplementation ()
|
||||||
|
{
|
||||||
|
Properties = new Dictionary<string, string> ();
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetProperty (string property)
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
|
||||||
|
Properties.TryGetValue (property, out value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the identification properties.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets the dictionary of raw identification properties.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The properties.</value>
|
||||||
|
public Dictionary<string, string> Properties {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the name of the program.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the name of the program.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The program name.</value>
|
||||||
|
public string Name {
|
||||||
|
get { return GetProperty ("name"); }
|
||||||
|
set { Properties["name"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the version of the program.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the version of the program.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\ImapExamples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The program version.</value>
|
||||||
|
public string Version {
|
||||||
|
get { return GetProperty ("version"); }
|
||||||
|
set { Properties["version"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the name of the operating system.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the name of the operating system.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the operation system.</value>
|
||||||
|
public string OS {
|
||||||
|
get { return GetProperty ("os"); }
|
||||||
|
set { Properties["os"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the version of the operating system.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the version of the operating system.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The version of the operation system.</value>
|
||||||
|
public string OSVersion {
|
||||||
|
get { return GetProperty ("os-version"); }
|
||||||
|
set { Properties["os-version"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the name of the vendor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the name of the vendor.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The name of the vendor.</value>
|
||||||
|
public string Vendor {
|
||||||
|
get { return GetProperty ("vendor"); }
|
||||||
|
set { Properties["vendor"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the support URL.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the support URL.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The support URL.</value>
|
||||||
|
public string SupportUrl {
|
||||||
|
get { return GetProperty ("support-url"); }
|
||||||
|
set { Properties["support-url"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the postal address of the vendor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the postal address of the vendor.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The postal address.</value>
|
||||||
|
public string Address {
|
||||||
|
get { return GetProperty ("address"); }
|
||||||
|
set { Properties["address"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the release date of the program.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the release date of the program.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The release date.</value>
|
||||||
|
public string ReleaseDate {
|
||||||
|
get { return GetProperty ("date"); }
|
||||||
|
set { Properties["date"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the command used to start the program.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the command used to start the program.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The command used to start the program.</value>
|
||||||
|
public string Command {
|
||||||
|
get { return GetProperty ("command"); }
|
||||||
|
set { Properties["command"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the command-line arguments used to start the program.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets the command-line arguments used to start the program.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The command-line arguments used to start the program.</value>
|
||||||
|
public string Arguments {
|
||||||
|
get { return GetProperty ("arguments"); }
|
||||||
|
set { Properties["arguments"] = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the environment variables available to the program.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Get or set the environment variables available to the program.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The environment variables.</value>
|
||||||
|
public string Environment {
|
||||||
|
get { return GetProperty ("environment"); }
|
||||||
|
set { Properties["environment"] = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
//
|
||||||
|
// ImapException.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
#if SERIALIZABLE
|
||||||
|
using System.Security;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
/// <summary>
|
||||||
|
/// An IMAP protocol exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The exception that is thrown when there is an error communicating with an IMAP server. An
|
||||||
|
/// <see cref="ImapProtocolException"/> is typically fatal and requires the <see cref="ImapClient"/>
|
||||||
|
/// to be reconnected.
|
||||||
|
/// </remarks>
|
||||||
|
#if SERIALIZABLE
|
||||||
|
[Serializable]
|
||||||
|
#endif
|
||||||
|
public class ImapProtocolException : ProtocolException
|
||||||
|
{
|
||||||
|
#if SERIALIZABLE
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapProtocolException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapProtocolException"/> from the serialized data.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="info">The serialization info.</param>
|
||||||
|
/// <param name="context">The streaming context.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="info"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
[SecuritySafeCritical]
|
||||||
|
protected ImapProtocolException (SerializationInfo info, StreamingContext context) : base (info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapProtocolException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapProtocolException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
/// <param name="innerException">An inner exception.</param>
|
||||||
|
public ImapProtocolException (string message, Exception innerException) : base (message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapProtocolException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapProtocolException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="message">The error message.</param>
|
||||||
|
public ImapProtocolException (string message) : base (message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapProtocolException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Creates a new <see cref="ImapProtocolException"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public ImapProtocolException ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether or not this exception was thrown due to an unexpected token.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Gets or sets whether or not this exception was thrown due to an unexpected token.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value><c>true</c> if an unexpected token was encountered; otherwise, <c>false</c>.</value>
|
||||||
|
internal bool UnexpectedToken {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,373 @@
|
||||||
|
//
|
||||||
|
// ImapResponseCode.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
enum ImapResponseCodeType : byte {
|
||||||
|
Alert,
|
||||||
|
BadCharset,
|
||||||
|
Capability,
|
||||||
|
NewName,
|
||||||
|
Parse,
|
||||||
|
PermanentFlags,
|
||||||
|
ReadOnly,
|
||||||
|
ReadWrite,
|
||||||
|
TryCreate,
|
||||||
|
UidNext,
|
||||||
|
UidValidity,
|
||||||
|
Unseen,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc2221:
|
||||||
|
Referral,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc3516,
|
||||||
|
UnknownCte,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc4315:
|
||||||
|
AppendUid,
|
||||||
|
CopyUid,
|
||||||
|
UidNotSticky,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc4467:
|
||||||
|
UrlMech,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc4469:
|
||||||
|
BadUrl,
|
||||||
|
TooBig,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc4551:
|
||||||
|
HighestModSeq,
|
||||||
|
Modified,
|
||||||
|
NoModSeq,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc4978:
|
||||||
|
CompressionActive,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5162:
|
||||||
|
Closed,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5182:
|
||||||
|
NotSaved,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5255:
|
||||||
|
BadComparator,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5257:
|
||||||
|
Annotate,
|
||||||
|
Annotations,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5259:
|
||||||
|
MaxConvertMessages,
|
||||||
|
MaxConvertParts,
|
||||||
|
TempFail,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5267:
|
||||||
|
NoUpdate,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5464:
|
||||||
|
Metadata,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5465:
|
||||||
|
NotificationOverflow,
|
||||||
|
BadEvent,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5466:
|
||||||
|
UndefinedFilter,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc5530:
|
||||||
|
Unavailable,
|
||||||
|
AuthenticationFailed,
|
||||||
|
AuthorizationFailed,
|
||||||
|
Expired,
|
||||||
|
PrivacyRequired,
|
||||||
|
ContactAdmin,
|
||||||
|
NoPerm,
|
||||||
|
InUse,
|
||||||
|
ExpungeIssued,
|
||||||
|
Corruption,
|
||||||
|
ServerBug,
|
||||||
|
ClientBug,
|
||||||
|
CanNot,
|
||||||
|
Limit,
|
||||||
|
OverQuota,
|
||||||
|
AlreadyExists,
|
||||||
|
NonExistent,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc6154:
|
||||||
|
UseAttr,
|
||||||
|
|
||||||
|
// RESP-CODES introduced in rfc8474:
|
||||||
|
MailboxId,
|
||||||
|
|
||||||
|
Unknown = 255
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImapResponseCode
|
||||||
|
{
|
||||||
|
public readonly ImapResponseCodeType Type;
|
||||||
|
public bool IsTagged, IsError;
|
||||||
|
public string Message;
|
||||||
|
|
||||||
|
internal ImapResponseCode (ImapResponseCodeType type, bool isError)
|
||||||
|
{
|
||||||
|
IsError = isError;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImapResponseCode Create (ImapResponseCodeType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ImapResponseCodeType.Alert: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.BadCharset: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.Capability: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.NewName: return new NewNameResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Parse: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.PermanentFlags: return new PermanentFlagsResponseCode (type);
|
||||||
|
case ImapResponseCodeType.ReadOnly: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.ReadWrite: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.TryCreate: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.UidNext: return new UidNextResponseCode (type);
|
||||||
|
case ImapResponseCodeType.UidValidity: return new UidValidityResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Unseen: return new UnseenResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Referral: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.UnknownCte: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.AppendUid: return new AppendUidResponseCode (type);
|
||||||
|
case ImapResponseCodeType.CopyUid: return new CopyUidResponseCode (type);
|
||||||
|
case ImapResponseCodeType.UidNotSticky: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.UrlMech: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.BadUrl: return new BadUrlResponseCode (type);
|
||||||
|
case ImapResponseCodeType.TooBig: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.HighestModSeq: return new HighestModSeqResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Modified: return new ModifiedResponseCode (type);
|
||||||
|
case ImapResponseCodeType.NoModSeq: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.CompressionActive: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.Closed: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.NotSaved: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.BadComparator: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.Annotate: return new AnnotateResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Annotations: return new AnnotationsResponseCode (type);
|
||||||
|
case ImapResponseCodeType.MaxConvertMessages: return new MaxConvertResponseCode (type);
|
||||||
|
case ImapResponseCodeType.MaxConvertParts: return new MaxConvertResponseCode (type);
|
||||||
|
case ImapResponseCodeType.TempFail: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.NoUpdate: return new NoUpdateResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Metadata: return new MetadataResponseCode (type);
|
||||||
|
case ImapResponseCodeType.NotificationOverflow: return new ImapResponseCode (type, false);
|
||||||
|
case ImapResponseCodeType.BadEvent: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.UndefinedFilter: return new UndefinedFilterResponseCode (type);
|
||||||
|
case ImapResponseCodeType.Unavailable: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.AuthenticationFailed: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.AuthorizationFailed: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.Expired: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.PrivacyRequired: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.ContactAdmin: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.NoPerm: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.InUse: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.ExpungeIssued: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.Corruption: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.ServerBug: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.ClientBug: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.CanNot: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.Limit: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.OverQuota: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.AlreadyExists: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.NonExistent: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.UseAttr: return new ImapResponseCode (type, true);
|
||||||
|
case ImapResponseCodeType.MailboxId: return new MailboxIdResponseCode (type);
|
||||||
|
default: return new ImapResponseCode (type, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NewNameResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public string OldName;
|
||||||
|
public string NewName;
|
||||||
|
|
||||||
|
internal NewNameResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PermanentFlagsResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public MessageFlags Flags;
|
||||||
|
|
||||||
|
internal PermanentFlagsResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UidNextResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public UniqueId Uid;
|
||||||
|
|
||||||
|
internal UidNextResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UidValidityResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public uint UidValidity;
|
||||||
|
|
||||||
|
internal UidValidityResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnseenResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public int Index;
|
||||||
|
|
||||||
|
internal UnseenResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppendUidResponseCode : UidValidityResponseCode
|
||||||
|
{
|
||||||
|
public UniqueIdSet UidSet;
|
||||||
|
|
||||||
|
internal AppendUidResponseCode (ImapResponseCodeType type) : base (type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CopyUidResponseCode : UidValidityResponseCode
|
||||||
|
{
|
||||||
|
public UniqueIdSet SrcUidSet, DestUidSet;
|
||||||
|
|
||||||
|
internal CopyUidResponseCode (ImapResponseCodeType type) : base (type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BadUrlResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public string BadUrl;
|
||||||
|
|
||||||
|
internal BadUrlResponseCode (ImapResponseCodeType type) : base (type, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HighestModSeqResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public ulong HighestModSeq;
|
||||||
|
|
||||||
|
internal HighestModSeqResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModifiedResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public UniqueIdSet UidSet;
|
||||||
|
|
||||||
|
internal ModifiedResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaxConvertResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public uint MaxConvert;
|
||||||
|
|
||||||
|
internal MaxConvertResponseCode (ImapResponseCodeType type) : base (type, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoUpdateResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public string Tag;
|
||||||
|
|
||||||
|
internal NoUpdateResponseCode (ImapResponseCodeType type) : base (type, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AnnotateResponseCodeSubType
|
||||||
|
{
|
||||||
|
TooBig,
|
||||||
|
TooMany
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotateResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public AnnotateResponseCodeSubType SubType;
|
||||||
|
|
||||||
|
internal AnnotateResponseCode (ImapResponseCodeType type) : base (type, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnnotationsResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public AnnotationAccess Access;
|
||||||
|
public AnnotationScope Scopes;
|
||||||
|
public uint MaxSize;
|
||||||
|
|
||||||
|
internal AnnotationsResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MetadataResponseCodeSubType
|
||||||
|
{
|
||||||
|
LongEntries,
|
||||||
|
MaxSize,
|
||||||
|
TooMany,
|
||||||
|
NoPrivate
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetadataResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public MetadataResponseCodeSubType SubType;
|
||||||
|
public uint Value;
|
||||||
|
|
||||||
|
internal MetadataResponseCode (ImapResponseCodeType type) : base (type, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UndefinedFilterResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
internal UndefinedFilterResponseCode (ImapResponseCodeType type) : base (type, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MailboxIdResponseCode : ImapResponseCode
|
||||||
|
{
|
||||||
|
public string MailboxId;
|
||||||
|
|
||||||
|
internal MailboxIdResponseCode (ImapResponseCodeType type) : base (type, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// ImapSearchQueryOptimizer.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using MailKit.Search;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
class ImapSearchQueryOptimizer : ISearchQueryOptimizer
|
||||||
|
{
|
||||||
|
#region ISearchQueryOptimizer implementation
|
||||||
|
|
||||||
|
public SearchQuery Reduce (SearchQuery expr)
|
||||||
|
{
|
||||||
|
if (expr.Term == SearchTerm.And) {
|
||||||
|
var and = (BinarySearchQuery) expr;
|
||||||
|
|
||||||
|
if (and.Left.Term == SearchTerm.All)
|
||||||
|
return and.Right.Optimize (this);
|
||||||
|
|
||||||
|
if (and.Right.Term == SearchTerm.All)
|
||||||
|
return and.Left.Optimize (this);
|
||||||
|
} else if (expr.Term == SearchTerm.Or) {
|
||||||
|
var or = (BinarySearchQuery) expr;
|
||||||
|
|
||||||
|
if (or.Left.Term == SearchTerm.All)
|
||||||
|
return SearchQuery.All;
|
||||||
|
|
||||||
|
if (or.Right.Term == SearchTerm.All)
|
||||||
|
return SearchQuery.All;
|
||||||
|
} else if (expr.Term == SearchTerm.Not) {
|
||||||
|
var unary = (UnarySearchQuery) expr;
|
||||||
|
|
||||||
|
switch (unary.Operand.Term) {
|
||||||
|
case SearchTerm.Not: return ((UnarySearchQuery) unary.Operand).Operand.Optimize (this);
|
||||||
|
case SearchTerm.NotAnswered: return SearchQuery.Answered;
|
||||||
|
case SearchTerm.Answered: return SearchQuery.NotAnswered;
|
||||||
|
case SearchTerm.NotDeleted: return SearchQuery.Deleted;
|
||||||
|
case SearchTerm.Deleted: return SearchQuery.NotDeleted;
|
||||||
|
case SearchTerm.NotDraft: return SearchQuery.Draft;
|
||||||
|
case SearchTerm.Draft: return SearchQuery.NotDraft;
|
||||||
|
case SearchTerm.NotFlagged: return SearchQuery.Flagged;
|
||||||
|
case SearchTerm.Flagged: return SearchQuery.NotFlagged;
|
||||||
|
case SearchTerm.NotRecent: return SearchQuery.Recent;
|
||||||
|
case SearchTerm.Recent: return SearchQuery.NotRecent;
|
||||||
|
case SearchTerm.NotSeen: return SearchQuery.Seen;
|
||||||
|
case SearchTerm.Seen: return SearchQuery.NotSeen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unary.Operand.Term == SearchTerm.Keyword)
|
||||||
|
return new TextSearchQuery (SearchTerm.NotKeyword, ((TextSearchQuery) unary.Operand).Text);
|
||||||
|
|
||||||
|
if (unary.Operand.Term == SearchTerm.NotKeyword)
|
||||||
|
return new TextSearchQuery (SearchTerm.Keyword, ((TextSearchQuery) unary.Operand).Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,80 @@
|
||||||
|
//
|
||||||
|
// ImapToken.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Imap {
|
||||||
|
enum ImapTokenType {
|
||||||
|
NoData = -7,
|
||||||
|
Error = -6,
|
||||||
|
Nil = -5,
|
||||||
|
Atom = -4,
|
||||||
|
Flag = -3,
|
||||||
|
QString = -2,
|
||||||
|
Literal = -1,
|
||||||
|
|
||||||
|
// character tokens:
|
||||||
|
Eoln = (int) '\n',
|
||||||
|
OpenParen = (int) '(',
|
||||||
|
CloseParen = (int) ')',
|
||||||
|
Asterisk = (int) '*',
|
||||||
|
OpenBracket = (int) '[',
|
||||||
|
CloseBracket = (int) ']',
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImapToken
|
||||||
|
{
|
||||||
|
public readonly ImapTokenType Type;
|
||||||
|
public readonly object Value;
|
||||||
|
|
||||||
|
public ImapToken (ImapTokenType type, object value = null)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
Type = type;
|
||||||
|
|
||||||
|
//System.Console.WriteLine ("token: {0}", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString ()
|
||||||
|
{
|
||||||
|
switch (Type) {
|
||||||
|
case ImapTokenType.NoData: return "<no data>";
|
||||||
|
case ImapTokenType.Nil: return "NIL";
|
||||||
|
case ImapTokenType.Atom: return "[atom: " + (string) Value + "]";
|
||||||
|
case ImapTokenType.Flag: return "[flag: " + (string) Value + "]";
|
||||||
|
case ImapTokenType.QString: return "[qstring: \"" + (string) Value + "\"]";
|
||||||
|
case ImapTokenType.Literal: return "{" + (int) Value + "}";
|
||||||
|
case ImapTokenType.Eoln: return "'\\n'";
|
||||||
|
case ImapTokenType.OpenParen: return "'('";
|
||||||
|
case ImapTokenType.CloseParen: return "')'";
|
||||||
|
case ImapTokenType.Asterisk: return "'*'";
|
||||||
|
case ImapTokenType.OpenBracket: return "'['";
|
||||||
|
case ImapTokenType.CloseBracket: return "']'";
|
||||||
|
default: return string.Format (CultureInfo.InvariantCulture, "[{0}: '{1}']", Type, Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,298 @@
|
||||||
|
//
|
||||||
|
// NetworkStream.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MailKit.Net
|
||||||
|
{
|
||||||
|
class NetworkStream : Stream
|
||||||
|
{
|
||||||
|
SocketAsyncEventArgs send;
|
||||||
|
SocketAsyncEventArgs recv;
|
||||||
|
bool ownsSocket;
|
||||||
|
bool connected;
|
||||||
|
|
||||||
|
public NetworkStream (Socket socket, bool ownsSocket)
|
||||||
|
{
|
||||||
|
send = new SocketAsyncEventArgs ();
|
||||||
|
send.Completed += AsyncOperationCompleted;
|
||||||
|
send.AcceptSocket = socket;
|
||||||
|
|
||||||
|
recv = new SocketAsyncEventArgs ();
|
||||||
|
recv.Completed += AsyncOperationCompleted;
|
||||||
|
recv.AcceptSocket = socket;
|
||||||
|
|
||||||
|
this.ownsSocket = ownsSocket;
|
||||||
|
connected = socket.Connected;
|
||||||
|
Socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
~NetworkStream ()
|
||||||
|
{
|
||||||
|
Dispose (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Socket Socket {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DataAvailable {
|
||||||
|
get { return connected && Socket.Available > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead {
|
||||||
|
get { return connected; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanWrite {
|
||||||
|
get { return connected; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanSeek {
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanTimeout {
|
||||||
|
get { return connected; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Length {
|
||||||
|
get { throw new NotSupportedException (); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Position {
|
||||||
|
get { throw new NotSupportedException (); }
|
||||||
|
set { throw new NotSupportedException (); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int ReadTimeout {
|
||||||
|
get {
|
||||||
|
int timeout = Socket.ReceiveTimeout;
|
||||||
|
|
||||||
|
return timeout == 0 ? Timeout.Infinite : timeout;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if (value <= 0 && value != Timeout.Infinite)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (value));
|
||||||
|
|
||||||
|
Socket.ReceiveTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int WriteTimeout {
|
||||||
|
get {
|
||||||
|
int timeout = Socket.SendTimeout;
|
||||||
|
|
||||||
|
return timeout == 0 ? Timeout.Infinite : timeout;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if (value <= 0 && value != Timeout.Infinite)
|
||||||
|
throw new ArgumentOutOfRangeException (nameof (value));
|
||||||
|
|
||||||
|
Socket.SendTimeout = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AsyncOperationCompleted (object sender, SocketAsyncEventArgs args)
|
||||||
|
{
|
||||||
|
var tcs = (TaskCompletionSource<bool>) args.UserToken;
|
||||||
|
|
||||||
|
if (args.SocketError == SocketError.Success) {
|
||||||
|
tcs.TrySetResult (true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcs.TrySetException (new SocketException ((int) args.SocketError));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disconnect ()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Socket.Dispose ();
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
connected = false;
|
||||||
|
send.Dispose ();
|
||||||
|
send = null;
|
||||||
|
recv.Dispose ();
|
||||||
|
recv = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return Socket.Receive (buffer, offset, count, SocketFlags.None);
|
||||||
|
} catch (SocketException ex) {
|
||||||
|
throw new IOException (ex.Message, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<int> ReadAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested ();
|
||||||
|
|
||||||
|
var tcs = new TaskCompletionSource<bool> ();
|
||||||
|
|
||||||
|
using (var timeout = new CancellationTokenSource (ReadTimeout)) {
|
||||||
|
using (var linked = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken, timeout.Token)) {
|
||||||
|
using (var registration = linked.Token.Register (() => tcs.TrySetCanceled (), false)) {
|
||||||
|
recv.SetBuffer (buffer, offset, count);
|
||||||
|
recv.UserToken = tcs;
|
||||||
|
|
||||||
|
if (!Socket.ReceiveAsync (recv))
|
||||||
|
AsyncOperationCompleted (null, recv);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await tcs.Task.ConfigureAwait (false);
|
||||||
|
return recv.BytesTransferred;
|
||||||
|
} catch (OperationCanceledException) {
|
||||||
|
if (Socket.Connected)
|
||||||
|
Socket.Shutdown (SocketShutdown.Both);
|
||||||
|
|
||||||
|
Disconnect ();
|
||||||
|
throw;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Disconnect ();
|
||||||
|
if (ex is SocketException)
|
||||||
|
throw new IOException (ex.Message, ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write (byte[] buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Socket.Send (buffer, offset, count, SocketFlags.None);
|
||||||
|
} catch (SocketException ex) {
|
||||||
|
throw new IOException (ex.Message, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task WriteAsync (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested ();
|
||||||
|
|
||||||
|
var tcs = new TaskCompletionSource<bool> ();
|
||||||
|
|
||||||
|
using (var timeout = new CancellationTokenSource (WriteTimeout)) {
|
||||||
|
using (var linked = CancellationTokenSource.CreateLinkedTokenSource (cancellationToken, timeout.Token)) {
|
||||||
|
using (var registration = linked.Token.Register (() => tcs.TrySetCanceled (), false)) {
|
||||||
|
send.SetBuffer (buffer, offset, count);
|
||||||
|
send.UserToken = tcs;
|
||||||
|
|
||||||
|
if (!Socket.SendAsync (send))
|
||||||
|
AsyncOperationCompleted (null, send);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await tcs.Task.ConfigureAwait (false);
|
||||||
|
} catch (OperationCanceledException) {
|
||||||
|
if (Socket.Connected)
|
||||||
|
Socket.Shutdown (SocketShutdown.Both);
|
||||||
|
|
||||||
|
Disconnect ();
|
||||||
|
throw;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Disconnect ();
|
||||||
|
if (ex is SocketException)
|
||||||
|
throw new IOException (ex.Message, ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task FlushAsync (CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.FromResult (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek (long offset, SeekOrigin origin)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength (long value)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkStream Get (Stream stream)
|
||||||
|
{
|
||||||
|
if (stream is CompressedStream compressed)
|
||||||
|
stream = compressed.InnerStream;
|
||||||
|
|
||||||
|
if (stream is SslStream ssl)
|
||||||
|
stream = ssl.InnerStream;
|
||||||
|
|
||||||
|
return stream as NetworkStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Poll (SelectMode mode, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!cancellationToken.CanBeCanceled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
cancellationToken.ThrowIfCancellationRequested ();
|
||||||
|
// wait 1/4 second and then re-check for cancellation
|
||||||
|
} while (!Socket.Poll (250000, mode));
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose (bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing) {
|
||||||
|
if (ownsSocket && connected) {
|
||||||
|
ownsSocket = false;
|
||||||
|
Disconnect ();
|
||||||
|
} else {
|
||||||
|
send?.Dispose ();
|
||||||
|
send = null;
|
||||||
|
|
||||||
|
recv?.Dispose ();
|
||||||
|
recv = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose (disposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,309 @@
|
||||||
|
//
|
||||||
|
// IPop3Client.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Pop3 {
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for a POP3 client.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Implemented by <see cref="MailKit.Net.Pop3.Pop3Client"/>.
|
||||||
|
/// </remarks>
|
||||||
|
public interface IPop3Client : IMailSpool
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the capabilities supported by the POP3 server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The capabilities will not be known until a successful connection has been made
|
||||||
|
/// and may change once the client is authenticated.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\Pop3Examples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The capabilities.</value>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// Capabilities cannot be enabled, they may only be disabled.
|
||||||
|
/// </exception>
|
||||||
|
Pop3Capabilities Capabilities { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the expiration policy.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>If the server supports the EXPIRE capability (<see cref="Pop3Capabilities.Expire"/>), the value
|
||||||
|
/// of the <see cref="ExpirePolicy"/> property will reflect the value advertized by the server.</para>
|
||||||
|
/// <para>A value of <c>-1</c> indicates that messages will never expire.</para>
|
||||||
|
/// <para>A value of <c>0</c> indicates that messages that have been retrieved during the current session
|
||||||
|
/// will be purged immediately after the connection is closed via the <c>QUIT</c> command.</para>
|
||||||
|
/// <para>Values larger than <c>0</c> indicate the minimum number of days that the server will retain
|
||||||
|
/// messages which have been retrieved.</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\Pop3Examples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The expiration policy.</value>
|
||||||
|
int ExpirePolicy { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the implementation details of the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the server advertizes its implementation details, this value will be set to a string containing the
|
||||||
|
/// information details provided by the server.
|
||||||
|
/// </remarks>
|
||||||
|
/// <value>The implementation details.</value>
|
||||||
|
string Implementation { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the minimum delay, in milliseconds, between logins.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the server supports the LOGIN-DELAY capability (<see cref="Pop3Capabilities.LoginDelay"/>), this value
|
||||||
|
/// will be set to the minimum number of milliseconds that the client must wait between logins.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\Pop3Examples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
/// <value>The login delay.</value>
|
||||||
|
int LoginDelay { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable UTF8 mode.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The POP3 UTF8 extension allows the client to retrieve messages in the UTF-8 encoding and
|
||||||
|
/// may also allow the user to authenticate using a UTF-8 encoded username or password.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="Pop3Client"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="Pop3Client"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// The <see cref="Pop3Client"/> has already been authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The POP3 server does not support the UTF8 extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3CommandException">
|
||||||
|
/// The POP3 command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3ProtocolException">
|
||||||
|
/// A POP3 protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void EnableUTF8 (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously enable UTF8 mode.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The POP3 UTF8 extension allows the client to retrieve messages in the UTF-8 encoding and
|
||||||
|
/// may also allow the user to authenticate using a UTF-8 encoded username or password.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="Pop3Client"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="Pop3Client"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// The <see cref="Pop3Client"/> has already been authenticated.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The POP3 server does not support the UTF8 extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3CommandException">
|
||||||
|
/// The POP3 command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3ProtocolException">
|
||||||
|
/// A POP3 protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
Task EnableUTF8Async (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the list of languages supported by the POP3 server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the POP3 server supports the LANG extension, it is possible to
|
||||||
|
/// query the list of languages supported by the POP3 server that can
|
||||||
|
/// be used for error messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The supported languages.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="Pop3Client"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="Pop3Client"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The POP3 server does not support the LANG extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3CommandException">
|
||||||
|
/// The POP3 command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3ProtocolException">
|
||||||
|
/// A POP3 protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
IList<Pop3Language> GetLanguages (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously get the list of languages supported by the POP3 server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the POP3 server supports the LANG extension, it is possible to
|
||||||
|
/// query the list of languages supported by the POP3 server that can
|
||||||
|
/// be used for error messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>The supported languages.</returns>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="Pop3Client"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="Pop3Client"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The POP3 server does not support the LANG extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3CommandException">
|
||||||
|
/// The POP3 command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3ProtocolException">
|
||||||
|
/// A POP3 protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
Task<IList<Pop3Language>> GetLanguagesAsync (CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the language used by the POP3 server for error messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the POP3 server supports the LANG extension, it is possible to
|
||||||
|
/// set the language used by the POP3 server for error messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="lang">The language code.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="lang"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="lang"/> is empty.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="Pop3Client"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="Pop3Client"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The POP3 server does not support the LANG extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3CommandException">
|
||||||
|
/// The POP3 command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3ProtocolException">
|
||||||
|
/// A POP3 protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
void SetLanguage (string lang, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronously set the language used by the POP3 server for error messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If the POP3 server supports the LANG extension, it is possible to
|
||||||
|
/// set the language used by the POP3 server for error messages.
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>An asynchronous task context.</returns>
|
||||||
|
/// <param name="lang">The language code.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <exception cref="System.ArgumentNullException">
|
||||||
|
/// <paramref name="lang"/> is <c>null</c>.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ArgumentException">
|
||||||
|
/// <paramref name="lang"/> is empty.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">
|
||||||
|
/// The <see cref="Pop3Client"/> has been disposed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="ServiceNotConnectedException">
|
||||||
|
/// The <see cref="Pop3Client"/> is not connected.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.OperationCanceledException">
|
||||||
|
/// The operation was canceled via the cancellation token.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NotSupportedException">
|
||||||
|
/// The POP3 server does not support the LANG extension.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.IO.IOException">
|
||||||
|
/// An I/O error occurred.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3CommandException">
|
||||||
|
/// The POP3 command failed.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="Pop3ProtocolException">
|
||||||
|
/// A POP3 protocol error occurred.
|
||||||
|
/// </exception>
|
||||||
|
Task SetLanguageAsync (string lang, CancellationToken cancellationToken = default (CancellationToken));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
//
|
||||||
|
// Pop3Capabilities.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Pop3 {
|
||||||
|
/// <summary>
|
||||||
|
/// Capabilities supported by a POP3 server.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Capabilities are read as part of the response to the <c>CAPA</c> command that
|
||||||
|
/// is issued during the connection and authentication phases of the
|
||||||
|
/// <see cref="Pop3Client"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <example>
|
||||||
|
/// <code language="c#" source="Examples\Pop3Examples.cs" region="Capabilities"/>
|
||||||
|
/// </example>
|
||||||
|
[Flags]
|
||||||
|
public enum Pop3Capabilities : uint {
|
||||||
|
/// <summary>
|
||||||
|
/// The server does not support any additional extensions.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports <a href="https://tools.ietf.org/html/rfc1939#page-15">APOP</a>
|
||||||
|
/// authentication.
|
||||||
|
/// </summary>
|
||||||
|
Apop = 1 << 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2449">EXPIRE</a> extension
|
||||||
|
/// and defines the expiration policy for messages (see <see cref="Pop3Client.ExpirePolicy"/>).
|
||||||
|
/// </summary>
|
||||||
|
Expire = 1 << 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2449">LOGIN-DELAY</a> extension,
|
||||||
|
/// allowing the server to specify to the client a minimum number of seconds between login attempts
|
||||||
|
/// (see <see cref="Pop3Client.LoginDelay"/>).
|
||||||
|
/// </summary>
|
||||||
|
LoginDelay = 1 << 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2449">PIPELINING</a> extension,
|
||||||
|
/// allowing the client to batch multiple requests to the server at at time.
|
||||||
|
/// </summary>
|
||||||
|
Pipelining = 1 << 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2449">RESP-CODES</a> extension,
|
||||||
|
/// allowing the server to provide clients with extended information in error responses.
|
||||||
|
/// </summary>
|
||||||
|
ResponseCodes = 1 << 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2449">SASL</a> authentication
|
||||||
|
/// extension, allowing the client to authenticate using the advertized authentication mechanisms
|
||||||
|
/// (see <see cref="Pop3Client.AuthenticationMechanisms"/>).
|
||||||
|
/// </summary>
|
||||||
|
Sasl = 1 << 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc2595">STLS</a> extension,
|
||||||
|
/// allowing clients to switch to an encrypted SSL/TLS connection after connecting.
|
||||||
|
/// </summary>
|
||||||
|
StartTLS = 1 << 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc1939#page-11">TOP</a> command,
|
||||||
|
/// allowing clients to fetch the headers plus an arbitrary number of lines.
|
||||||
|
/// </summary>
|
||||||
|
Top = 1 << 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc1939#page-12">UIDL</a> command,
|
||||||
|
/// allowing the client to refer to messages via a UID as opposed to a sequence ID.
|
||||||
|
/// </summary>
|
||||||
|
UIDL = 1 << 8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc1939#page-13">USER</a>
|
||||||
|
/// authentication command, allowing the client to authenticate via a plain-text username
|
||||||
|
/// and password command (not recommended unless no other authentication mechanisms exist).
|
||||||
|
/// </summary>
|
||||||
|
User = 1 << 9,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6856">UTF8</a> extension,
|
||||||
|
/// allowing clients to retrieve messages in the UTF-8 encoding.
|
||||||
|
/// </summary>
|
||||||
|
UTF8 = 1 << 10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6856">UTF8=USER</a> extension,
|
||||||
|
/// allowing clients to authenticate using UTF-8 encoded usernames and passwords.
|
||||||
|
/// </summary>
|
||||||
|
UTF8User = 1 << 11,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The server supports the <a href="https://tools.ietf.org/html/rfc6856">LANG</a> extension,
|
||||||
|
/// allowing clients to specify which language the server should use for error strings.
|
||||||
|
/// </summary>
|
||||||
|
Lang = 1 << 12,
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
||||||
|
//
|
||||||
|
// Pop3Command.cs
|
||||||
|
//
|
||||||
|
// Author: Jeffrey Stedfast <jestedfa@microsoft.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013-2020 .NET Foundation and Contributors
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MailKit.Net.Pop3 {
|
||||||
|
/// <summary>
|
||||||
|
/// POP3 command handler.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// All exceptions thrown by the handler are considered fatal and will
|
||||||
|
/// force-disconnect the connection. If a non-fatal error occurs, set
|
||||||
|
/// it on the <see cref="Pop3Command.Exception"/> property.
|
||||||
|
/// </remarks>
|
||||||
|
delegate Task Pop3CommandHandler (Pop3Engine engine, Pop3Command pc, string text, bool doAsync);
|
||||||
|
|
||||||
|
enum Pop3CommandStatus {
|
||||||
|
Queued = -5,
|
||||||
|
Active = -4,
|
||||||
|
Continue = -3,
|
||||||
|
ProtocolError = -2,
|
||||||
|
Error = -1,
|
||||||
|
Ok = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class Pop3Command
|
||||||
|
{
|
||||||
|
public CancellationToken CancellationToken { get; private set; }
|
||||||
|
public Pop3CommandHandler Handler { get; private set; }
|
||||||
|
public Encoding Encoding { get; private set; }
|
||||||
|
public string Command { get; private set; }
|
||||||
|
public int Id { get; internal set; }
|
||||||
|
|
||||||
|
// output
|
||||||
|
public Pop3CommandStatus Status { get; internal set; }
|
||||||
|
public ProtocolException Exception { get; set; }
|
||||||
|
public string StatusText { get; set; }
|
||||||
|
|
||||||
|
public Pop3Command (CancellationToken cancellationToken, Pop3CommandHandler handler, Encoding encoding, string format, params object[] args)
|
||||||
|
{
|
||||||
|
Command = string.Format (CultureInfo.InvariantCulture, format, args);
|
||||||
|
CancellationToken = cancellationToken;
|
||||||
|
Encoding = encoding;
|
||||||
|
Handler = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue