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