Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactoring, Cleanup, Comments

3.4.0.1
  • Loading branch information...
commit 3676780f1b2cee7b192b504c3408a1118e0f9dd9 1 parent b385ec7
@smiley22 authored
View
10 AuthMethod.cs
@@ -6,13 +6,11 @@ namespace S22.Imap {
/// </summary>
public enum AuthMethod {
/// <summary>
- /// Automatically selects the most-secure authentication mechanism
- /// supported by the server.
+ /// Automatically selects the most-secure authentication mechanism supported by the server.
/// </summary>
Auto,
/// <summary>
- /// Login using plaintext password authentication. This is
- /// the default supported by most servers.
+ /// Login using plaintext password authentication; This is supported by most servers.
/// </summary>
Login,
/// <summary>
@@ -44,8 +42,8 @@ public enum AuthMethod {
/// </summary>
Ntlmv2,
/// <summary>
- /// Login using the NTLM/NTLMv2 authentication mechanism via
- /// Microsoft's Security Support Provider Interface (SSPI).
+ /// Login using the NTLM/NTLMv2 authentication mechanism via Microsoft's Security Support
+ /// Provider Interface (SSPI).
/// </summary>
NtlmOverSspi,
/// <summary>
View
15 Exceptions.cs
@@ -3,9 +3,9 @@
namespace S22.Imap {
/// <summary>
- /// The exception is thrown when an unexpected response is received from the server.
+ /// The exception that is thrown when an unexpected response is received from the server.
/// </summary>
- [Serializable()]
+ [Serializable]
public class BadServerResponseException : Exception {
/// <summary>
/// Initializes a new instance of the BadServerResponseException class
@@ -40,10 +40,9 @@ protected BadServerResponseException(SerializationInfo info, StreamingContext co
}
/// <summary>
- /// This exception is thrown when the supplied credentials in a login attempt were rejected
- /// by the server.
+ /// The exception that is thrown when the supplied credentials were rejected by the server.
/// </summary>
- [Serializable()]
+ [Serializable]
public class InvalidCredentialsException : Exception {
/// <summary>
/// Initializes a new instance of the InvalidCredentialsException class
@@ -78,10 +77,10 @@ protected InvalidCredentialsException(SerializationInfo info, StreamingContext c
}
/// <summary>
- /// This exception is thrown when a client has not authenticated with the server and
- /// attempts to call a method which can only be called in an authenticated context.
+ /// The exception that is thrown when a client has not authenticated with the server and
+ /// attempts to call a method which can only be called when authenticated.
/// </summary>
- [Serializable()]
+ [Serializable]
public class NotAuthenticatedException : Exception {
/// <summary>
/// Initializes a new instance of the NotAuthenticatedException class
View
18 FetchOptions.cs
@@ -2,8 +2,7 @@
namespace S22.Imap {
/// <summary>
- /// Fetch options that can be used with the GetMessage and GetMessages methods
- /// to selectively retrieve parts of a mail message while skipping others.
+ /// Defines the different means by which mail messages may be fetched from the server.
/// </summary>
public enum FetchOptions {
/// <summary>
@@ -11,20 +10,19 @@ public enum FetchOptions {
/// </summary>
Normal,
/// <summary>
- /// Only the mail message headers will be retrieved, while the actual content will
- /// not be downloaded. If this option is specified, only the header fields of the
- /// returned MailMessage object will be initialized.
+ /// Only the mail message headers will be retrieved, while the actual content will not be
+ /// downloaded. If this option is specified, only the header fields of the returned MailMessage
+ /// object will be initialized.
/// </summary>
HeadersOnly,
/// <summary>
- /// Retrieves the mail message, but will only download content that has a
- /// content-type of text. This will retrieve text as well as html representations,
- /// but no inline content or attachments.
+ /// Retrieves the mail message, but will only download content that has a content-type of text.
+ /// This will retrieve text as well as HTML representation, while skipping inline content and
+ /// attachments.
/// </summary>
TextOnly,
/// <summary>
- /// Retrieves the mail message, but skips any content that has been marked as
- /// attachment.
+ /// Retrieves the mail message, but skips any content that is an attachment.
/// </summary>
NoAttachments
}
View
9 IImapClient.cs
@@ -9,13 +9,12 @@ namespace S22.Imap {
/// </summary>
public interface IImapClient : IDisposable {
/// <summary>
- /// The default mailbox to operate on, when no specific mailbox name is indicated
- /// to methods that operate on mailboxes. The default value for this property is "INBOX".
+ /// The default mailbox to operate on.
/// </summary>
- /// <exception cref="ArgumentNullException">The value specified for a set operation is
+ /// <exception cref="ArgumentNullException">The property is being set and the value is
/// null.</exception>
- /// <exception cref="ArgumentException">The value specified for a set operation is equal
- /// to the empty string.</exception>
+ /// <exception cref="ArgumentException">The property is being set and the value is the empty
+ /// string.</exception>
/// <remarks>The default value for this property is "INBOX" which is a special name reserved
/// to mean "the primary mailbox for this user on this server".</remarks>
string DefaultMailbox { get; set; }
View
15 IdleEvents.cs
@@ -2,8 +2,7 @@
namespace S22.Imap {
/// <summary>
- /// Provides data for IMAP idle notification events, such as the NewMessage and
- /// MessageDelete events.
+ /// Provides data for IMAP idle notification events.
/// </summary>
public class IdleMessageEventArgs : EventArgs {
/// <summary>
@@ -11,12 +10,10 @@ public class IdleMessageEventArgs : EventArgs {
/// MessageCount attribute to the value of the <paramref name="MessageCount"/>
/// parameter.
/// </summary>
- /// <param name="MessageCount">The number of messages in the selected
+ /// <param name="MessageCount">The number of messages in the selected mailbox.</param>
+ /// <param name="MessageUID"> The unique identifier (UID) of the newest message in the
/// mailbox.</param>
- /// <param name="MessageUID"> The unique identifier (UID) of the newest
- /// message in the mailbox.</param>
- /// <param name="Client">The instance of the ImapClient class that raised
- /// the event.</param>
+ /// <param name="Client">The instance of the ImapClient class that raised the event.</param>
internal IdleMessageEventArgs(uint MessageCount, uint MessageUID,
ImapClient Client) {
this.MessageCount = MessageCount;
@@ -35,8 +32,8 @@ public class IdleMessageEventArgs : EventArgs {
/// <summary>
/// The unique identifier (UID) of the newest message in the mailbox.
/// </summary>
- /// <remarks>The UID can be passed to the GetMessage method in order to retrieve
- /// the mail message from the server.</remarks>
+ /// <remarks>The UID can be passed to the GetMessage method in order to retrieve the mail
+ /// message from the server.</remarks>
public uint MessageUID {
get;
private set;
View
27 ImapClient.cs
@@ -46,13 +46,12 @@ public class ImapClient : IImapClient
static readonly TraceSource ts = new TraceSource("S22.Imap");
/// <summary>
- /// The default mailbox to operate on, when no specific mailbox name is indicated
- /// to methods that operate on mailboxes. The default value for this property is "INBOX".
+ /// The default mailbox to operate on.
/// </summary>
- /// <exception cref="ArgumentNullException">The value specified for a set operation is
+ /// <exception cref="ArgumentNullException">The property is being set and the value is
/// null.</exception>
- /// <exception cref="ArgumentException">The value specified for a set operation is equal
- /// to the empty string.</exception>
+ /// <exception cref="ArgumentException">The property is being set and the value is the empty
+ /// string.</exception>
/// <remarks>The default value for this property is "INBOX" which is a special name reserved
/// to mean "the primary mailbox for this user on this server".</remarks>
public string DefaultMailbox {
@@ -218,7 +217,7 @@ public class ImapClient : IImapClient
sslStream.AuthenticateAsClient(hostname);
stream = sslStream;
}
- // Server issues an untagged OK greeting upon connect.
+ // The server issues an untagged OK greeting upon connect.
string greeting = GetResponse();
if (!IsResponseOK(greeting))
throw new BadServerResponseException(greeting);
@@ -840,7 +839,6 @@ public class ImapClient : IImapClient
if (mailbox == null)
mailbox = defaultMailbox;
MailboxStatus status = GetMailboxStatus(mailbox);
-
// Collect quota information if the server supports it.
UInt64 used = 0, free = 0;
if (Supports("QUOTA")) {
@@ -854,10 +852,9 @@ public class ImapClient : IImapClient
}
// Try to collect special-use flags.
IEnumerable<MailboxFlag> flags = GetMailboxFlags(mailbox);
-
ResumeIdling();
- return new MailboxInfo(mailbox, flags, status.Messages,
- status.Unread, status.NextUID, used, free);
+ return new MailboxInfo(mailbox, flags, status.Messages, status.Unread, status.NextUID,
+ used, free);
}
}
@@ -901,8 +898,7 @@ public class ImapClient : IImapClient
string response = SendCommandGetResponse(tag + command + " \"\" " +
Util.UTF7Encode(mailbox).QuoteString());
while (response.StartsWith("*")) {
- Match m = Regex.Match(response,
- "\\* X?LIST \\((.*)\\)\\s+\"([^\"]+)\"\\s+(.+)");
+ Match m = Regex.Match(response, "\\* X?LIST \\((.*)\\)\\s+\"([^\"]+)\"\\s+(.+)");
if (m.Success) {
string[] flags = m.Groups[1].Value.Split(' ');
foreach (string f in flags) {
@@ -1301,8 +1297,8 @@ public class ImapClient : IImapClient
string response = SendCommandGetResponse(tag + "APPEND " +
Util.UTF7Encode(mailbox).QuoteString() + (seen ? @" (\Seen)" : "") +
" {" + mime822.Length + "}");
- // The server is required to send a continuation response before we can go ahead with the
- // actual message data.
+ // The server must send a continuation response before we can go ahead with the actual
+ // message data.
if (!response.StartsWith("+"))
throw new BadServerResponseException(response);
response = SendCommandGetResponse(mime822);
@@ -1420,8 +1416,7 @@ public class ImapClient : IImapClient
PauseIdling();
SelectMailbox(mailbox);
string tag = GetTag();
- string response = SendCommandGetResponse(tag + "UID FETCH " + uid +
- " (BODYSTRUCTURE)");
+ string response = SendCommandGetResponse(tag + "UID FETCH " + uid + " (BODYSTRUCTURE)");
string structure = String.Empty;
while (response.StartsWith("*")) {
Match m = Regex.Match(response,
View
7 MIMEPart.cs
@@ -3,13 +3,12 @@
namespace S22.Imap {
/// <summary>
- /// Represents a part of a MIME multi-part message. Each part consists
- /// of its own content header and a content body.
+ /// Represents a part of a MIME multi-part message. Each part consists of its own content header
+ /// and a content body.
/// </summary>
internal class MIMEPart {
/// <summary>
- /// A collection containing the content header information as
- /// key-value pairs.
+ /// A collection containing the content header information as key-value pairs.
/// </summary>
public NameValueCollection header {
get;
View
150 MailMessage.cs
@@ -9,21 +9,21 @@
namespace S22.Imap {
/// <summary>
- /// Adds extension methods to the MailMessage class of the .Net Framework.
- /// These are only used internally and are not visible outside of the
- /// S22.Imap assembly.
+ /// Adds extension methods to the MailMessage class of the .NET Framework.
/// </summary>
+ /// <remarks>
+ /// These are only used internally and are not visible outside of the S22.Imap assembly.
+ /// </remarks>
internal static class MailMessageExtension {
/// <summary>
- /// Constructs a textual representation of a mail message from the specified
- /// MailMessage instance compliant with the RFC822 and MIME standards.
+ /// Constructs a textual representation of a mail message from the specified MailMessage
+ /// instance compliant with the RFC822 and MIME standards.
/// </summary>
- /// <param name="message">The MailMessage instance to construct the
- /// textual representation from.</param>
- /// <returns>An RFC822/MIME-compliant string describing a mail
- /// message.</returns>
- /// <exception cref="InvalidOperationException">Thrown if the From
- /// property is null or is not properly initialized.</exception>
+ /// <param name="message">The MailMessage instance to construct the textual representation
+ /// from.</param>
+ /// <returns>An RFC822/MIME-compliant string representing the specified mail message.</returns>
+ /// <exception cref="InvalidOperationException">The From property is null or has not been
+ /// properly initialized.</exception>
internal static string ToMIME822(this MailMessage message) {
NameValueCollection header = BuildHeader(message);
StringBuilder builder = new StringBuilder();
@@ -49,13 +49,11 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Builds a RFC822/MIME-compliant mail header from the specified
- /// MailMessage instance and returns it as a NameValueCollection.
+ /// Builds a RFC822/MIME-compliant mail header from the specified MailMessage instance and
+ /// returns it as a NameValueCollection.
/// </summary>
- /// <param name="m">The MailMessage instance to build the header
- /// from.</param>
- /// <returns>A NameValueCollection representing the RFC822/MIME
- /// mail header fields.</returns>
+ /// <param name="m">The MailMessage instance to build the header from.</param>
+ /// <returns>A NameValueCollection representing the RFC822/MIME mail header fields.</returns>
static NameValueCollection BuildHeader(MailMessage m) {
string[] ignore = new string[] {
"MIME-Version", "Date", "Subject", "From", "To", "Cc", "Bcc",
@@ -71,7 +69,7 @@ internal static class MailMessageExtension {
{ "Importance", ImportanceMap[m.Priority] }
};
if (m.From == null)
- throw new InvalidOperationException("The From property must not be null");
+ throw new InvalidOperationException("The From property must not be null.");
header.Add("From", m.From.To822Address());
if (m.Subject != null)
header.Add("Subject", m.Subject.IsASCII() ? m.Subject : Base64Encode(m.Subject));
@@ -105,9 +103,8 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// A map for mapping the values of the MailPriority enumeration to
- /// their corresponding MIME priority values as defined in
- /// RFC2156.
+ /// A map for mapping the values of the MailPriority enumeration to their corresponding MIME
+ /// priority values as defined in RFC2156.
/// </summary>
static Dictionary<MailPriority, string> PriorityMap =
new Dictionary<MailPriority, string>() {
@@ -117,9 +114,8 @@ internal static class MailMessageExtension {
};
/// <summary>
- /// A map for mapping the values of the MailPriority enumeration to
- /// their corresponding MIME importance values as defined in
- /// RFC2156.
+ /// A map for mapping the values of the MailPriority enumeration to their corresponding MIME
+ /// importance values as defined in RFC2156.
/// </summary>
static Dictionary<MailPriority, string> ImportanceMap =
new Dictionary<MailPriority, string>() {
@@ -131,9 +127,9 @@ internal static class MailMessageExtension {
/// <summary>
/// Takes a unicode string and encodes it using Q-encoding.
/// </summary>
- /// <param name="s">The string to encode</param>
- /// <returns>The input string encoded as Q-encoded string containing
- /// only ASCII characters.</returns>
+ /// <param name="s">The string to encode.</param>
+ /// <returns>The input string encoded as Q-encoded string containing only ASCII
+ /// characters.</returns>
static string QEncode(string s) {
StringBuilder builder = new StringBuilder("=?UTF-8?Q?");
char[] chars = Encoding.Unicode.GetChars(Encoding.Unicode.GetBytes(s));
@@ -152,8 +148,8 @@ internal static class MailMessageExtension {
/// Takes a unicode string and encodes it using Base64-encoding.
/// </summary>
/// <param name="s">The string to encode.</param>
- /// <returns>The input string encoded as Base64-encoded string
- /// containing only ASCII characters.</returns>
+ /// <returns>The input string encoded as Base64-encoded string containing only ASCII
+ /// characters.</returns>
static string Base64Encode(string s) {
StringBuilder builder = new StringBuilder("=?UTF-8?B?");
string b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(s));
@@ -161,13 +157,11 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Creates an address string from the specified MailAddress instance in
- /// compliance with the address specification as outlined in RFC2822 under
- /// section 3.4
+ /// Creates an address string from the specified MailAddress instance in compliance with the
+ /// address specification as outlined in RFC2822 under section 3.4
/// </summary>
- /// <param name="address">The MailAddress instance to create the address
- /// string from.</param>
- /// <returns>An address string as is used in RFC822 mail headers</returns>
+ /// <param name="address">The MailAddress instance to create the address string from.</param>
+ /// <returns>An address string as is used in RFC822 mail headers.</returns>
internal static string To822Address(this MailAddress address) {
if (!String.IsNullOrEmpty(address.DisplayName)) {
string name = address.DisplayName.IsASCII() ?
@@ -179,28 +173,25 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Generates a unique sequence of characters for indicating a boundary
- /// between parts in a multipart message.
+ /// Generates a unique sequence of characters for indicating a boundary between parts in a
+ /// multipart message.
/// </summary>
- /// <returns>A unique content boundary string</returns>
+ /// <returns>A unique content boundary string.</returns>
static string GenerateContentBoundary() {
return Guid.NewGuid().ToString("N");
}
/// <summary>
- /// Builds an RFC822/MIME-compliant mail body from the specified
- /// MailMessage instance and returns it as a formatted string.
+ /// Builds an RFC822/MIME-compliant mail body from the specified MailMessage instance and
+ /// returns it as a formatted string.
/// </summary>
- /// <param name="m">The MailMessage instance to build the mail body
- /// from.</param>
- /// <param name="header">The RFC822/MIME mail header to use for
- /// constructing the mail body.</param>
- /// <returns>An RFC822/MIME-compliant mail body as a string.
- /// </returns>
- /// <remarks>According to RFC2822 each line of a mail message should
- /// at max be 78 characters in length excluding carriage return and
- /// newline characters. This method accounts for that and ensures
- /// line breaks are inserted to meet this requirement.</remarks>
+ /// <param name="m">The MailMessage instance to build the mail body from.</param>
+ /// <param name="header">The RFC822/MIME mail header to use for constructing the mail
+ /// body.</param>
+ /// <returns>An RFC822/MIME-compliant mail body as a string.</returns>
+ /// <remarks>According to RFC2822 each line of a mail message should at max be 78 characters in
+ /// length excluding carriage return and newline characters. This method accounts for that and
+ /// ensures line breaks are inserted to meet this requirement.</remarks>
static string BuildBody(MailMessage m, NameValueCollection header) {
StringBuilder builder = new StringBuilder();
bool multipart = header["Content-Type"].Contains("boundary");
@@ -235,15 +226,14 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Adds a body part to the specified Stringbuilder object composed from
- /// the Body and BodyEncoding properties of the MailMessage class.
+ /// Adds a body part to the specified Stringbuilder object composed from the Body and
+ /// BodyEncoding properties of the MailMessage class.
/// </summary>
/// <param name="builder">The Stringbuilder to append the body part to.</param>
/// <param name="m">The MailMessage instance to build the body part from.</param>
- /// <param name="header">The RFC822/MIME mail header to use for
- /// constructing the mail body.</param>
- /// <param name="addHeaders">Set to true to append body headers before
- /// adding the actual body part content.</param>
+ /// <param name="header">The RFC822/MIME mail header to use for constructing the mail body.</param>
+ /// <param name="addHeaders">Set to true to append body headers before adding the actual body
+ /// part content.</param>
static void AddBody(StringBuilder builder, MailMessage m,
NameValueCollection header, bool addHeaders = false) {
bool base64 = header["Content-Transfer-Encoding"] == "base64";
@@ -271,16 +261,14 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Creates a MIME body part from an entry of the AlternateView or
- /// Attachments collection of a MailMessage instance and appends it
- /// to the specified Stringbuilder instance.
+ /// Creates a MIME body part from an entry of the AlternateView or Attachments collection of a
+ /// MailMessage instance and appends it to the specified Stringbuilder instance.
/// </summary>
- /// <param name="builder">The Stringbuilder instance to append the
- /// body part to.</param>
- /// <param name="view">An entry from either the AlternateView or the
- /// Attachments collection of a MailMessage instance.</param>
+ /// <param name="builder">The Stringbuilder instance to append the body part to.</param>
+ /// <param name="view">An entry from either the AlternateView or the Attachments collection of
+ /// a MailMessage instance.</param>
static void AddAttachment(StringBuilder builder, AttachmentBase view) {
- // Append the MIME headers for this body part
+ // Append the MIME headers for this body part.
string contentType = "Content-Type: " + view.ContentType.MediaType;
foreach (string key in view.ContentType.Parameters.Keys) {
contentType = contentType + "; " + key + "=" +
@@ -314,19 +302,17 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Creates a nested multipart/alternative part which contains all entries
- /// from the AlternateViews collection of the specified MailMessage instance
- /// as well as the body part for the Body and BodyEncoding properties of the
- /// specified MailMessage instance.
+ /// Creates a nested multipart/alternative part which contains all entries from the
+ /// AlternateViews collection of the specified MailMessage instance as well as the body part
+ /// for the Body and BodyEncoding properties of the specified MailMessage instance.
/// </summary>
/// <param name="builder">The StringBuilder instance to append to.</param>
- /// <param name="m">The MailMessage instance whose AlternateView collection
- /// will be added to the nested multipart/alternative part.</param>
- /// <param name="header">The RFC822/MIME mail header to use for
- /// constructing the mail body.</param>
- /// <remarks>This is used if the MailMessage instance contains both alternative
- /// views and attachments. In this case the created RFC822/MIME mail message will
- /// contain nested body parts.</remarks>
+ /// <param name="m">The MailMessage instance whose AlternateView collection will be added to the
+ /// nested multipart/alternative part.</param>
+ /// <param name="header">The RFC822/MIME mail header to use for constructing the mail body.</param>
+ /// <remarks>This is used if the MailMessage instance contains both alternative views and
+ /// attachments. In this case the created RFC822/MIME mail message will contain nested body
+ /// parts.</remarks>
static void AddNestedAlternative(StringBuilder builder, MailMessage m,
NameValueCollection header) {
string boundary = GenerateContentBoundary();
@@ -343,15 +329,15 @@ internal static class MailMessageExtension {
}
/// <summary>
- /// Creates a nested multipart/mixed part which contains all entries
- /// from the Attachments collection of the specified MailMessage instance.
+ /// Creates a nested multipart/mixed part which contains all entries from the Attachments
+ /// collection of the specified MailMessage instance.
/// </summary>
/// <param name="builder">The StringBuilder instance to append to.</param>
- /// <param name="m">The MailMessage instance whose Attachments collection
- /// will be added to the nested multipart/mixed part.</param>
- /// <remarks>This is used if the MailMessage instance contains both alternative
- /// views and attachments. In this case the created RFC822/MIME mail message will
- /// contain nested body parts.</remarks>
+ /// <param name="m">The MailMessage instance whose Attachments collection will be added to the
+ /// nested multipart/mixed part.</param>
+ /// <remarks>This is used if the MailMessage instance contains both alternative views and
+ /// attachments. In this case the created RFC822/MIME mail message will contain nested body
+ /// parts.</remarks>
static void AddNestedMixed(StringBuilder builder, MailMessage m) {
string boundary = GenerateContentBoundary();
builder.AppendLine("Content-Type: multipart/mixed; boundary=" + boundary);
View
45 MailboxFlags.cs
@@ -2,48 +2,49 @@
namespace S22.Imap {
/// <summary>
- /// An IMAP mailbox can have a number of flags (read: attributes) set on it,
- /// indicating its designated purpose (such as "Spam" or "Drafts").
- ///
- /// This is especially convenient if dealing with international mailbox
- /// names, because by examining the associated flags, the mailbox purpose
- /// can be easily determined, even if the mailbox name provides no useful
- /// indication.
+ /// Defines possible attributes for mailboxes.
/// </summary>
/// <remarks>
- /// Unfortunately as with many things IMAP, reporting the flags described
- /// above is an optional extension (XLIST) to the IMAP protocol and as
- /// such may or may not be supported by an IMAP server.
+ /// <para>
+ /// An IMAP mailbox can have a number of flags (read: attributes) set on it, indicating its
+ /// designated purpose (such as "Spam" or "Drafts").
+ /// </para>
+ /// <para>
+ /// This is especially convenient when dealing with international mailbox names, because, by
+ /// examining the associated flags, the mailbox purpose can be determined, even if the mailbox
+ /// name provides no useful indication.
+ /// </para>
+ /// <para>
+ /// Unfortunately, as with many things IMAP, reporting the flags described here is an optional
+ /// extension (XLIST) to the IMAP protocol and as such may or may not be supported by an IMAP
+ /// server.
+ /// </para>
/// </remarks>
public enum MailboxFlag {
/// <summary>
- /// The mailbox presents a view on all messages in the user's message
- /// store.
+ /// The mailbox presents a view on all messages in the user's message store.
/// </summary>
AllMail,
/// <summary>
- /// The mailbox is used to archive messages. The meaning of an
- /// "archival" mailbox is server-dependent.
+ /// The mailbox is used to archive messages. The meaning of an "archival" mailbox is server
+ /// dependent.
/// </summary>
Archive,
/// <summary>
- /// The mailbox is used to hold draft messages, typically these are
- /// messages that are being composed but have not yet been sent.
+ /// The mailbox is used to hold draft messages, typically these are messages that are being
+ /// composed but have not yet been sent.
/// </summary>
Drafts,
/// <summary>
- /// The mailbox is used to hold copies of messages that have been
- /// sent.
+ /// The mailbox is used to hold copies of messages that have been sent.
/// </summary>
Sent,
/// <summary>
- /// The mailbox is where messages deemed to be junk mail (spam) are
- /// held.
+ /// The mailbox is where messages deemed to be junk mail (spam) are held.
/// </summary>
Spam,
/// <summary>
- /// The mailbox is used to hold messages that have been deleted or
- /// marked for deletion.
+ /// The mailbox is used to hold messages that have been deleted or marked for deletion.
/// </summary>
Trash
}
View
31 MailboxInfo.cs
@@ -3,19 +3,18 @@
namespace S22.Imap {
/// <summary>
- /// Contains status information for an IMAP mailbox such as the total
- /// number of messages in the mailbox, various attributes as well as
- /// quota information.
+ /// Provides access to status information such as the total number of messages and quota
+ /// information for a mailbox.
/// </summary>
- /// <remarks>The terms "mailbox" and "folder" can be used interchangeably
- /// and refer to the IMAP concept of multiple server-side directories into
- /// which messages can be stored (such as "Inbox", "Sent Items", "Trash",
- /// etc.).</remarks>
+ /// <remarks>
+ /// The terms "mailbox" and "folder" can be used interchangeably and refer to the IMAP concept of
+ /// multiple server-side directories into which messages can be stored (such as "Inbox",
+ /// "Sent Items", "Trash", etc.).
+ /// </remarks>
[Serializable]
public class MailboxInfo {
/// <summary>
- /// Initializes a new instance of the MailboxInfo class with the specified
- /// values.
+ /// Initializes a new instance of the MailboxInfo class with the specified values.
/// </summary>
/// <param name="Name">The IMAP name of the mailbox.</param>
/// <param name="Flags">The IMAP flags set on this mailbox.</param>
@@ -44,7 +43,7 @@ public class MailboxInfo {
}
/// <summary>
- /// The name of the mailbox
+ /// The name of the mailbox.
/// </summary>
public string Name {
get;
@@ -52,7 +51,7 @@ public class MailboxInfo {
}
/// <summary>
- /// An enumerable collection of flags set on this mailbox.
+ /// An enumerable collection of flags set on the mailbox.
/// </summary>
public IEnumerable<MailboxFlag> Flags {
get;
@@ -86,9 +85,8 @@ public class MailboxInfo {
/// <summary>
/// The amount of used storage in the mailbox, measured in bytes.
/// </summary>
- /// <remarks>Not all IMAP servers support the retrieval of quota
- /// information. If it is not possible to retrieve the amount of
- /// used storage, this property will be set to 0.
+ /// <remarks>Not all IMAP servers support the retrieval of quota information. If it is not
+ /// possible to retrieve the amount of used storage, this property will be 0.
/// </remarks>
public UInt64 UsedStorage {
get;
@@ -98,9 +96,8 @@ public class MailboxInfo {
/// <summary>
/// The amount of free storage in the mailbox, measured in bytes.
/// </summary>
- /// <remarks>Not all IMAP servers support the retrieval of quota
- /// information. If it is not possible to retrieve the amount of
- /// free storage, this property will be set to 0.
+ /// <remarks>Not all IMAP servers support the retrieval of quota information. If it is not
+ /// possible to retrieve the amount of free storage, this property will be 0.
/// </remarks>
public UInt64 FreeStorage {
get;
View
19 MailboxQuota.cs
@@ -2,18 +2,15 @@
namespace S22.Imap {
/// <summary>
- /// Represents an IMAP QUOTA entry for a resource which typically consists of
- /// a resource name, the current usage of the resource, and the resource limit.
+ /// Represents an IMAP QUOTA entry for a resource which typically consists of a resource name,
+ /// the current usage of the resource, and the resource limit.
/// </summary>
internal class MailboxQuota {
/// <summary>
- /// Initializes a new instance of the MailboxQuota class with the specified
- /// values.
+ /// Initializes a new instance of the MailboxQuota class with the specified values.
/// </summary>
- /// <param name="Name">The name of the resource this MailboxQuota instance
- /// describes.</param>
- /// <param name="Usage">The current usage of the resource in units of 1024
- /// bytes.</param>
+ /// <param name="Name">The name of the resource this MailboxQuota instance describes.</param>
+ /// <param name="Usage">The current usage of the resource in units of 1024 bytes.</param>
/// <param name="Limit">The limit of the resource in units of 1024 bytes.</param>
internal MailboxQuota(string Name, uint Usage, uint Limit) {
this.ResourceName = Name.ToUpperInvariant();
@@ -30,8 +27,7 @@ internal class MailboxQuota {
}
/// <summary>
- /// The current usage of the resource this MailboxQuota instance describes,
- /// in bytes.
+ /// The current usage of the resource this MailboxQuota instance describes, in bytes.
/// </summary>
public UInt64 Usage {
get;
@@ -39,8 +35,7 @@ internal class MailboxQuota {
}
/// <summary>
- /// The limit of the resource this MailboxQuota instance describes,
- /// in bytes.
+ /// The limit of the resource this MailboxQuota instance describes, in bytes.
/// </summary>
public UInt64 Limit {
get;
View
8 MailboxStatus.cs
@@ -2,14 +2,14 @@
namespace S22.Imap {
/// <summary>
- /// Represents the status information of a mailbox which can be
- /// constructed from the server response to a STATUS command.
+ /// Represents the status information of a mailbox which can be constructed from the server
+ /// response to a STATUS command.
/// </summary>
[Serializable]
internal class MailboxStatus {
/// <summary>
- /// Initializes a new MailboxStatus instance with the specified number
- /// of total and unread messages.
+ /// Initializes a new MailboxStatus instance with the specified number of total and unread
+ /// messages.
/// </summary>
/// <param name="Messages">The total number of messages in the mailbox.</param>
/// <param name="Unread">The number of unread (unseen) messages in the mailbox.</param>
View
188 MessageBuilder.cs
@@ -8,18 +8,16 @@
namespace S22.Imap {
/// <summary>
- /// A helper class for reading mail message data and building a MailMessage
- /// instance out of it.
+ /// A helper class for reading mail message data and building a MailMessage instance out of it.
/// </summary>
internal static class MessageBuilder {
/// <summary>
- /// Creates a new empty instance of the MailMessage class from a string
- /// containing a raw mail message header.
+ /// Creates a new empty instance of the MailMessage class from a string containing a raw mail
+ /// message header.
/// </summary>
- /// <param name="text">A string containing the mail header to create
- /// the MailMessage instance from.</param>
- /// <returns>A MailMessage instance with initialized Header fields but
- /// no content</returns>
+ /// <param name="text">The mail header to create the MailMessage instance from.</param>
+ /// <returns>A MailMessage instance with initialized Header fields but without any
+ /// content.</returns>
internal static MailMessage FromHeader(string text) {
NameValueCollection header = ParseMailHeader(text);
MailMessage m = new MailMessage();
@@ -57,15 +55,13 @@ internal static class MessageBuilder {
}
/// <summary>
- /// Creates a new instance of the MailMessage class from a string
- /// containing raw RFC822/MIME mail message data.
+ /// Creates a new instance of the MailMessage class from a string containing raw RFC822/MIME
+ /// mail message data.
/// </summary>
- /// <param name="text">A string containing the mail message data to
- /// create the MailMessage instance from.</param>
+ /// <param name="text">The mail message data to create the MailMessage instance from.</param>
/// <returns>An initialized instance of the MailMessage class.</returns>
- /// <remarks>This is used when fetching entire messages instead
- /// of the partial-fetch mechanism because it saves redundant
- /// round-trips to the server.</remarks>
+ /// <remarks>This is used when fetching entire messages instead of the partial-fetch mechanism
+ /// because it saves redundant round-trips to the server.</remarks>
internal static MailMessage FromMIME822(string text) {
StringReader reader = new StringReader(text);
StringBuilder header = new StringBuilder();
@@ -80,12 +76,11 @@ internal static class MessageBuilder {
}
/// <summary>
- /// Parses the mail header of a mail message and returns it as a
- /// NameValueCollection.
+ /// Parses the mail header of a mail message and returns it as a NameValueCollection.
/// </summary>
/// <param name="header">The mail header to parse.</param>
- /// <returns>A NameValueCollection containing the header fields as keys
- /// with their respective values as values.</returns>
+ /// <returns>A NameValueCollection containing the header fields as keys with their respective
+ /// values as values.</returns>
internal static NameValueCollection ParseMailHeader(string header) {
StringReader reader = new StringReader(header);
NameValueCollection coll = new NameValueCollection();
@@ -114,13 +109,13 @@ internal static class MessageBuilder {
/// Parses a MIME header field which can contain multiple 'parameter = value'
/// pairs (such as Content-Type: text/html; charset=iso-8859-1).
/// </summary>
- /// <param name="field">The header field to parse</param>
- /// <returns>A NameValueCollection containing the parameter names as keys
- /// with the respective parameter values as values.</returns>
- /// <remarks>The value of the actual field disregarding the 'parameter = value'
- /// pairs is stored in the collection under the key "value" (in the above example
- /// of Content-Type, this would be "text/html").</remarks>
- private static NameValueCollection ParseMIMEField(string field) {
+ /// <param name="field">The header field to parse.</param>
+ /// <returns>A NameValueCollection containing the parameter names as keys with the respective
+ /// parameter values as values.</returns>
+ /// <remarks>The value of the actual field disregarding the 'parameter = value' pairs is stored
+ /// in the collection under the key "value" (in the above example of Content-Type, this would
+ /// be "text/html").</remarks>
+ static NameValueCollection ParseMIMEField(string field) {
NameValueCollection coll = new NameValueCollection();
try {
MatchCollection matches = Regex.Matches(field,
@@ -138,12 +133,11 @@ internal static class MessageBuilder {
}
/// <summary>
- /// Parses a mail header address-list field such as To, Cc and Bcc which
- /// can contain multiple email addresses.
+ /// Parses a mail header address-list field such as To, Cc and Bcc which can contain multiple
+ /// email addresses.
/// </summary>
/// <param name="list">The address-list field to parse</param>
- /// <returns>An array of MailAddress objects representing the parsed
- /// mail addresses.</returns>
+ /// <returns>An array of MailAddress objects representing the parsed mail addresses.</returns>
internal static MailAddress[] ParseAddressList(string list) {
const int minValidLength = 3;
List<MailAddress> mails = new List<MailAddress>();
@@ -156,19 +150,15 @@ internal static class MessageBuilder {
if (list.TrimStart('<').TrimEnd('>').Length < minValidLength)
return mails.ToArray();
MailAddressCollection mcol = new MailAddressCollection();
- // Use .NET internal MailAddressParser.ParseMultipleAddresses
- // to parse the address list.
- // Note: Add anything that fails to DecodeEncodedAddressLists test.
+ // Use .NET internal MailAddressParser.ParseMultipleAddresses to parse the address list.
mcol.Add(list);
foreach (MailAddress m in mcol) {
- // We might still need to decode the display name if it is
- // q-encoded.
+ // We might still need to decode the display name if it is Q-encoded.
string displayName = Util.DecodeWords(m.DisplayName);
mails.Add(new MailAddress(m.Address, displayName));
}
} catch {
- // We don't want this to throw any exceptions even if the
- // address list is malformed.
+ // We don't want this to throw any exceptions even if the address list is malformed.
}
return mails.ToArray();
}
@@ -177,12 +167,12 @@ internal static class MessageBuilder {
/// Parses a mail message identifier from a string.
/// </summary>
/// <param name="field">The field to parse the message id from</param>
- /// <exception cref="ArgumentException">Thrown when the field
- /// argument does not contain a valid message identifier.</exception>
- /// <returns>The parsed message id</returns>
- /// <remarks>A message identifier (msg-id) is a globally unique
- /// identifier for a message.</remarks>
- private static string ParseMessageId(string field) {
+ /// <exception cref="ArgumentException">The field argument does not contain a valid message
+ /// identifier.</exception>
+ /// <returns>The parsed message id.</returns>
+ /// <remarks>A message identifier (msg-id) is a globally unique identifier for a
+ /// message.</remarks>
+ static string ParseMessageId(string field) {
// A msg-id is enclosed in < > brackets.
Match m = Regex.Match(field, @"<(.+)>");
if (m.Success)
@@ -192,16 +182,15 @@ internal static class MessageBuilder {
}
/// <summary>
- /// Parses the priority of a mail message which can be specified
- /// as part of the header information.
+ /// Parses the priority of a mail message which can be specified as part of the header
+ /// information.
/// </summary>
- /// <param name="priority">The mail header priority value. The value
- /// can be null in which case a "normal priority" is returned.</param>
- /// <returns>A value from the MailPriority enumeration corresponding to
- /// the specified mail priority. If the passed priority value is null
- /// or invalid, a normal priority is assumed and MailPriority.Normal
- /// is returned.</returns>
- private static MailPriority ParsePriority(string priority) {
+ /// <param name="priority">The mail header priority value. The value can be null in which case
+ /// a "normal priority" is returned.</param>
+ /// <returns>A value from the MailPriority enumeration corresponding to the specified mail
+ /// priority. If the passed priority value is null or invalid, a normal priority is assumed and
+ /// MailPriority.Normal is returned.</returns>
+ static MailPriority ParsePriority(string priority) {
Dictionary<string, MailPriority> Map =
new Dictionary<string, MailPriority>(StringComparer.OrdinalIgnoreCase) {
{ "non-urgent", MailPriority.Low },
@@ -216,12 +205,12 @@ internal static class MessageBuilder {
}
/// <summary>
- /// Sets the address fields (From, To, CC, etc.) of a MailMessage
- /// object using the specified mail message header information.
+ /// Sets the address fields (From, To, CC, etc.) of a MailMessage object using the specified
+ /// mail message header information.
/// </summary>
- /// <param name="m">The MailMessage instance to operate on</param>
- /// <param name="header">A collection of mail and MIME headers</param>
- private static void SetAddressFields(MailMessage m, NameValueCollection header) {
+ /// <param name="m">The MailMessage instance to operate on.</param>
+ /// <param name="header">A collection of mail and MIME headers.</param>
+ static void SetAddressFields(MailMessage m, NameValueCollection header) {
MailAddress[] addr;
if (header["To"] != null) {
addr = ParseAddressList(header["To"]);
@@ -279,18 +268,17 @@ internal static class MessageBuilder {
break;
}
} catch {
- // If it's not a valid Base64 or quoted-printable encoded string
- // just leave the data as is
+ // If it's not a valid Base64 or quoted-printable encoded string just leave the data as is.
bytes = Encoding.ASCII.GetBytes(content);
}
- // If we have name it most likely is an attachment. And not a body.
- // Inline parts are better accessed as attachment instead of AlternateView.
- bool haveName = part.Parameters.ContainsKey("name");
+ // If the part has a name it most likely is an attachment and it should go into the
+ // Attachments collection.
+ bool hasName = part.Parameters.ContainsKey("name");
- // If the MailMessage's Body fields haven't been initialized yet, put it there.
- // Some weird (i.e. spam) mails like to omit content-types so we don't check for
- // that here and just assume it's text.
+ // If the MailMessage's Body fields haven't been initialized yet, put it there. Some weird
+ // (i.e. spam) mails like to omit content-types so we don't check for that here and just
+ // assume it's text.
if (String.IsNullOrEmpty(message.Body) &&
part.Disposition.Type != ContentDispositionType.Attachment) {
message.Body = encoding.GetString(bytes);
@@ -299,35 +287,32 @@ internal static class MessageBuilder {
return;
}
- // Check for a alternative view.
+ // Check for alternative view.
string ContentType = ParseMIMEField(message.Headers["Content-Type"])["value"];
bool preferAlternative = string.Compare(ContentType, "multipart/alternative", true) == 0;
- // can "multipart/mixed" be handled ?
- // Many attachments are missing Disposition Type, If not defined as alternative
- // And name is available assume it is Attachment and not AlternateView.
+ // Many attachments are missing the disposition-type. If it's not defined as alternative
+ // and it has a name attribute, assume it is Attachment rather than an AlternateView.
if (part.Disposition.Type == ContentDispositionType.Attachment ||
(part.Disposition.Type == ContentDispositionType.Unknown &&
- preferAlternative == false && haveName))
+ preferAlternative == false && hasName))
message.Attachments.Add(CreateAttachment(part, bytes));
else
message.AlternateViews.Add(CreateAlternateView(part, bytes));
}
/// <summary>
- /// Creates an instance of the Attachment class used by the MailMessage class
- /// to store mail message attachments.
+ /// Creates an instance of the Attachment class used by the MailMessage class to store mail
+ /// message attachments.
/// </summary>
/// <param name="part">The MIME body part to create the attachment from.</param>
- /// <param name="bytes">An array of bytes composing the content of the
- /// attachment</param>
- /// <returns>An initialized instance of the Attachment class</returns>
- private static Attachment CreateAttachment(Bodypart part, byte[] bytes) {
+ /// <param name="bytes">An array of bytes composing the content of the attachment.</param>
+ /// <returns>An initialized instance of the Attachment class.</returns>
+ static Attachment CreateAttachment(Bodypart part, byte[] bytes) {
MemoryStream stream = new MemoryStream(bytes);
string name = part.Disposition.Filename;
- // Many MUAs put the file name in the name parameter of the content-type
- // header instead of the filename parameter of the content-disposition
- // header.
+ // Many MUAs put the file name in the name parameter of the content-type header instead of
+ // the filename parameter of the content-disposition header.
if (String.IsNullOrEmpty(name) && part.Parameters.ContainsKey("name"))
name = part.Parameters["name"];
if (String.IsNullOrEmpty(name))
@@ -349,14 +334,13 @@ internal static class MessageBuilder {
}
/// <summary>
- /// Creates an instance of the AlternateView class used by the MailMessage class
- /// to store alternate views of the mail message's content.
+ /// Creates an instance of the AlternateView class used by the MailMessage class to store
+ /// alternate views of the mail message's content.
/// </summary>
/// <param name="part">The MIME body part to create the alternate view from.</param>
- /// <param name="bytes">An array of bytes composing the content of the
- /// alternate view</param>
- /// <returns>An initialized instance of the AlternateView class</returns>
- private static AlternateView CreateAlternateView(Bodypart part, byte[] bytes) {
+ /// <param name="bytes">An array of bytes composing the content of the alternate view.</param>
+ /// <returns>An initialized instance of the AlternateView class.</returns>
+ static AlternateView CreateAlternateView(Bodypart part, byte[] bytes) {
MemoryStream stream = new MemoryStream(bytes);
System.Net.Mime.ContentType contentType;
try {
@@ -376,11 +360,10 @@ internal static class MessageBuilder {
/// Parses the body part of a MIME/RFC822 mail message.
/// </summary>
/// <param name="body">The body of the mail message.</param>
- /// <param name="header">The header of the mail message whose body
- /// will be parsed.</param>
- /// <returns>An array of initialized MIMEPart instances representing
- /// the body parts of the mail message.</returns>
- private static MIMEPart[] ParseMailBody(string body,
+ /// <param name="header">The header of the mail message whose body will be parsed.</param>
+ /// <returns>An array of initialized MIMEPart instances representing the body parts of the mail
+ /// message.</returns>
+ static MIMEPart[] ParseMailBody(string body,
NameValueCollection header) {
NameValueCollection contentType = ParseMIMEField(header["Content-Type"]);
if (contentType["Boundary"] != null) {
@@ -402,13 +385,13 @@ internal static class MessageBuilder {
/// <summary>
/// Parses the body of a multipart MIME mail message.
/// </summary>
- /// <param name="reader">An instance of the StringReader class initialized
- /// with a string containing the body of the mail message.</param>
- /// <param name="boundary">The boundary value as is present as part of
- /// the Content-Type header field in multipart mail messages.</param>
- /// <returns>An array of initialized MIMEPart instances representing
- /// the various parts of the MIME mail message.</returns>
- private static MIMEPart[] ParseMIMEParts(StringReader reader, string boundary) {
+ /// <param name="reader">An instance of the StringReader class initialized with a string
+ /// containing the body of the mail message.</param>
+ /// <param name="boundary">The boundary value as is present as part of the Content-Type header
+ /// field in multipart mail messages.</param>
+ /// <returns>An array of initialized MIMEPart instances representing the various parts of the
+ /// MIME mail message.</returns>
+ static MIMEPart[] ParseMIMEParts(StringReader reader, string boundary) {
List<MIMEPart> list = new List<MIMEPart>();
string start = "--" + boundary, end = "--" + boundary + "--", line;
// Skip everything up to the first boundary.
@@ -436,11 +419,11 @@ internal static class MessageBuilder {
body.AppendLine(line);
}
p.body = body.ToString();
- // Add the MIME part to the list unless body is null or empty which means
- // the body contained nested multipart content.
+ // Add the MIME part to the list unless body is null or empty which means the body
+ // contained nested multipart content.
if (!String.IsNullOrWhiteSpace(p.body))
list.Add(p);
- // If this boundary is actually the end boundary, we're done.
+ // If this boundary is the end boundary, we're done.
if (line == null || line.StartsWith(end))
break;
}
@@ -450,10 +433,9 @@ internal static class MessageBuilder {
/// <summary>
/// Glue method to create a bodypart from a MIMEPart instance.
/// </summary>
- /// <param name="mimePart">The MIMEPart instance to create the
- /// bodypart instance from.</param>
+ /// <param name="mimePart">The MIMEPart instance to create the bodypart instance from.</param>
/// <returns>An initialized instance of the Bodypart class.</returns>
- private static Bodypart BodypartFromMIME(MIMEPart mimePart) {
+ static Bodypart BodypartFromMIME(MIMEPart mimePart) {
NameValueCollection contentType = ParseMIMEField(
mimePart.header["Content-Type"]);
Bodypart p = new Bodypart(null);
View
12 MessageFlags.cs
@@ -2,8 +2,7 @@
namespace S22.Imap {
/// <summary>
- /// Flag message attributes that can be associated with a mail message on an IMAP
- /// server.
+ /// Defines possible attributes for mail messages on an IMAP server.
/// </summary>
public enum MessageFlag {
/// <summary>
@@ -19,17 +18,16 @@ public enum MessageFlag {
/// </summary>
Flagged,
/// <summary>
- /// Indicates that the message has been marked as "deleted" and will be
- /// removed upon the next call to the Expunge method.
+ /// Indicates that the message has been marked as "deleted" and will be removed upon the next
+ /// call to the Expunge method.
/// </summary>
Deleted,
/// <summary>
- /// Indicates that the message has not completed composition and is
- /// marked as a draft.
+ /// Indicates that the message has not completed composition and is marked as a draft.
/// </summary>
Draft,
/// <summary>
- /// Indicates that the message has recently arrived in this mailbox.
+ /// Indicates that the message has recently arrived in the mailbox.
/// </summary>
Recent
}
View
4 Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("3.4.0.0")]
-[assembly: AssemblyFileVersion("3.4.0.0")]
+[assembly: AssemblyVersion("3.4.0.1")]
+[assembly: AssemblyFileVersion("3.4.0.1")]
View
10 SafeQueue.cs
@@ -6,7 +6,7 @@ namespace S22.Imap {
/// A thread-safe Queue.
/// </summary>
internal class SafeQueue<T> {
- private readonly Queue<T> _queue = new Queue<T>();
+ readonly Queue<T> _queue = new Queue<T>();
/// <summary>
/// Adds an object to the end of the queue.
@@ -21,12 +21,10 @@ internal class SafeQueue<T> {
}
/// <summary>
- /// Removes and returns the object at the beginning of the queue. If
- /// the queue is empty, the method blocks the calling thread until an
- /// object is put into the queue by another thread.
+ /// Removes and returns the object at the beginning of the queue. If the queue is empty, the
+ /// method blocks the calling thread until an object is put into the queue by another thread.
/// </summary>
- /// <returns>The object that is removed from the beginning
- /// of the queue.</returns>
+ /// <returns>The object that was removed from the beginning of the queue.</returns>
public T Dequeue() {
lock (_queue) {
while (_queue.Count == 0)
View
313 SearchCondition.cs
@@ -5,199 +5,196 @@
namespace S22.Imap {
/// <summary>
- /// Chainable search conditions to be used with the Search method.
+ /// Represents chainable search conditions that can be used with the Search method.
/// </summary>
public class SearchCondition {
/// <summary>
/// Finds all messages in the mailbox.
/// </summary>
- /// <returns>A SearchCondition object representing the "all" search criterion</returns>
+ /// <returns>A SearchCondition object representing the "all" search criterion.</returns>
public static SearchCondition All() {
return new SearchCondition { Field = Fields.All };
}
/// <summary>
- /// Finds messages that contain the specified string in the header or body of the
- /// message.
+ /// Finds messages that contain the specified string in the header or body of the message.
/// </summary>
- /// <param name="text">String to search messages for</param>
- /// <returns>A SearchCondition object representing the "text" search criterion</returns>
+ /// <param name="text">String to search messages for.</param>
+ /// <returns>A SearchCondition object representing the "text" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition Text(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Text, Value = text };
}
/// <summary>
- /// Finds messages that contain the specified string in the envelope structure's
- /// BCC field.
+ /// Finds messages that contain the specified string in the envelope structure's BCC field.
/// </summary>
- /// <param name="text">String to search the envelope structure's BCC field for</param>
- /// <returns>A SearchCondition object representing the "BCC" search criterion</returns>
+ /// <param name="text">String to search the envelope structure's BCC field for.</param>
+ /// <returns>A SearchCondition object representing the "BCC" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition BCC(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.BCC, Value = text };
}
/// <summary>
- /// Finds messages whose internal date (disregarding time and timezone) is
- /// earlier than the specified date.
+ /// Finds messages whose internal date (disregarding time and timezone) is earlier than the
+ /// specified date.
/// </summary>
- /// <param name="date">Date to compare the message's internal date with</param>
- /// <returns>A SearchCondition object representing the "Before" search criterion</returns>
+ /// <param name="date">The date to compare the message's internal date with.</param>
+ /// <returns>A SearchCondition object representing the "Before" search criterion.</returns>
public static SearchCondition Before(DateTime date) {
return new SearchCondition { Field = Fields.Before, Value = date };
}
/// <summary>
- /// Finds messages that contain the specified string in the body of the
- /// message.
+ /// Finds messages that contain the specified string in the body of the message.
/// </summary>
- /// <param name="text">String to search the message body for</param>
- /// <returns>A SearchCondition object representing the "Body" search criterion</returns>
+ /// <param name="text">String to search the message body for.</param>
+ /// <returns>A SearchCondition object representing the "Body" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition Body(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Body, Value = text };
}
/// <summary>
- /// Finds messages that contain the specified string in the envelope structure's
- /// CC field.
+ /// Finds messages that contain the specified string in the envelope structure's CC field.
/// </summary>
- /// <param name="text">String to search the envelope structure's CC field for</param>
- /// <returns>A SearchCondition object representing the "CC" search criterion</returns>
+ /// <param name="text">String to search the envelope structure's CC field for.</param>
+ /// <returns>A SearchCondition object representing the "CC" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition Cc(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Cc, Value = text };
}
/// <summary>
- /// Finds messages that contain the specified string in the envelope structure's
- /// FROM field.
+ /// Finds messages that contain the specified string in the envelope structure's FROM field.
/// </summary>
- /// <param name="text">String to search the envelope structure's FROM field for</param>
- /// <returns>A SearchCondition object representing the "FROM" search criterion</returns>
+ /// <param name="text">String to search the envelope structure's FROM field for.</param>
+ /// <returns>A SearchCondition object representing the "FROM" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition From(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.From, Value = text };
}
/// <summary>
- /// Finds messages that have a header with the specified field-name and that
- /// contains the specified string in the text of the header.
+ /// Finds messages that have a header with the specified field-name and that contains the
+ /// specified string in the text of the header.
/// </summary>
- /// <param name="name">field-name of the header to search for</param>
- /// <param name="text">String to search for in the text of the header</param>
- /// <returns>A SearchCondition object representing the "HEADER" search
- /// criterion</returns>
+ /// <param name="name">field-name of the header to search for.</param>
+ /// <param name="text">String to search for in the text of the header.</param>
+ /// <returns>A SearchCondition object representing the "HEADER" search criterion.</returns>
/// <remarks>
- /// If the string to search is zero-length, this matches all messages
- /// that have a header line with the specified field-name regardless of the
- /// contents.
+ /// If the string to search is zero-length, this matches all messages that have a header line
+ /// with the specified field-name regardless of the contents.
/// </remarks>
+ /// <exception cref="ArgumentNullException">The name parameter or the text parameter is
+ /// null.</exception>
public static SearchCondition Header(string name, string text) {
+ name.ThrowIfNull("name");
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Header, Quote = false,
Value = name + " " + text.QuoteString() };
}
/// <summary>
/// Finds messages with the specified keyword flag set.
/// </summary>
- /// <param name="text">Keyword flag to search for</param>
- /// <returns>A SearchCondition object representing the "KEYWORD" search
- /// criterion</returns>
+ /// <param name="text">The keyword flag to search for.</param>
+ /// <returns>A SearchCondition object representing the "KEYWORD" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition Keyword(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Keyword, Value = text };
}
/// <summary>
/// Finds messages with a size larger than the specified number of bytes.
/// </summary>
- /// <param name="size">Minimum size, in bytes a message must have to be
- /// included in the result set</param>
- /// <returns>A SearchCondition object representing the "LARGER" search
- /// criterion</returns>
+ /// <param name="size">Minimum size, in bytes a message must have to be included in the search
+ /// result.</param>
+ /// <returns>A SearchCondition object representing the "LARGER" search criterion.</returns>
public static SearchCondition Larger(long size) {
return new SearchCondition { Field = Fields.Larger, Value = size };
}
/// <summary>
/// Finds messages with a size smaller than the specified number of bytes.
/// </summary>
- /// <param name="size">Maximum size, in bytes a message must have to be
- /// included in the result set</param>
- /// <returns>A SearchCondition object representing the "SMALLER" search
- /// criterion</returns>
+ /// <param name="size">Maximum size, in bytes a message must have to be included in the search
+ /// result.</param>
+ /// <returns>A SearchCondition object representing the "SMALLER" search criterion.</returns>
public static SearchCondition Smaller(long size) {
return new SearchCondition { Field = Fields.Smaller, Value = size };
}
/// <summary>
- /// Finds messages whose Date: header (disregarding time and timezone) is
- /// earlier than the specified date.
+ /// Finds messages whose Date: header (disregarding time and timezone) is earlier than the
+ /// specified date.
/// </summary>
- /// <param name="date">Date to compare the Date: header field with.</param>
- /// <returns>A SearchCondition object representing the "SENTBEFORE" search
- /// criterion</returns>
+ /// <param name="date">The date to compare the Date: header field with.</param>
+ /// <returns>A SearchCondition object representing the "SENTBEFORE" search criterion.</returns>
public static SearchCondition SentBefore(DateTime date) {
return new SearchCondition { Field = Fields.SentBefore, Value = date };
}
/// <summary>
- /// Finds messages whose Date: header (disregarding time and timezone) is
- /// within the specified date.
+ /// Finds messages whose Date: header (disregarding time and timezone) is within the specified
+ /// date.
/// </summary>
- /// <param name="date">Date to compare the Date: header field with.</param>
- /// <returns>A SearchCondition object representing the "SENTON" search
- /// criterion</returns>
+ /// <param name="date">The date to compare the Date: header field with.</param>
+ /// <returns>A SearchCondition object representing the "SENTON" search criterion.</returns>
public static SearchCondition SentOn(DateTime date) {
return new SearchCondition { Field = Fields.SentOn, Value = date };
}
/// <summary>
- /// Finds messages whose Date: header (disregarding time and timezone) is
- /// within or later than the specified date.
+ /// Finds messages whose Date: header (disregarding time and timezone) is within or later than
+ /// the specified date.
/// </summary>
- /// <param name="date">Date to compare the Date: header field with.</param>
- /// <returns>A SearchCondition object representing the "SENTSINCE" search
- /// criterion</returns>
+ /// <param name="date">The date to compare the Date: header field with.</param>
+ /// <returns>A SearchCondition object representing the "SENTSINCE" search criterion.</returns>
public static SearchCondition SentSince(DateTime date) {
return new SearchCondition { Field = Fields.SentSince, Value = date };
}
/// <summary>
- /// Finds messages that contain the specified string in the envelope
- /// structure's SUBJECT field.
+ /// Finds messages that contain the specified string in the envelope structure's SUBJECT field.
/// </summary>
- /// <param name="text">String to search the envelope structure's SUBJECT
- /// field for</param>
- /// <returns>A SearchCondition object representing the "SUBJECT" search
- /// criterion</returns>
+ /// <param name="text">String to search the envelope structure's SUBJECT field for.</param>
+ /// <returns>A SearchCondition object representing the "SUBJECT" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition Subject(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Subject, Value = text };
}
/// <summary>
- /// Finds messages that contain the specified string in the envelope
- /// structure's TO field.
+ /// Finds messages that contain the specified string in the envelope structure's TO field.
/// </summary>
- /// <param name="text">String to search the envelope structure's TO
- /// field for</param>
- /// <returns>A SearchCondition object representing the "TO" search
- /// criterion</returns>
+ /// <param name="text">String to search the envelope structure's TO field for.</param>
+ /// <returns>A SearchCondition object representing the "TO" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition To(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.To, Value = text };
}
/// <summary>
- /// Finds messages with unique identifiers corresponding to the specified
- /// unique identifier set.
+ /// Finds messages with unique identifiers corresponding to the specified unique identifier set.
/// </summary>
- /// <param name="uids">An array of unique identifiers</param>
- /// <returns>A SearchCondition object representing the "UID" search
- /// criterion</returns>
+ /// <param name="uids">One or several unique identifiers (UID).</param>
+ /// <returns>A SearchCondition object representing the "UID" search criterion.</returns>
public static SearchCondition UID(params uint[] uids) {
return new SearchCondition { Field = Fields.UID,
Value = uids };
}
/// <summary>
- /// Finds messages with a unique identifier greater than the specified
- /// unique identifier. Because of the nature of the IMAP search mechanism,
- /// the result set will always contain the UID of the last message in the
- /// mailbox, even if said UID is smaller than the UID specified.
+ /// Finds messages with a unique identifier greater than the specified unique identifier.
/// </summary>
/// <param name="uid">A unique identifier (UID).</param>
- /// <returns>A SearchCondition object representing the "UID" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UID" search criterion.</returns>
+ /// <remarks>
+ /// Because of the nature of the IMAP search mechanism, the result set will always contain the
+ /// UID of the last message in the mailbox, even if said UID is smaller than the UID specified.
+ /// </remarks>
public static SearchCondition GreaterThan(uint uid) {
return new SearchCondition { Field = Fields.UID,
Value = (uid + 1).ToString() + ":*", Quote = false };
}
/// <summary>
- /// Finds messages with a unique identifier less than the specified
- /// unique identifier.
+ /// Finds messages with a unique identifier less than the specified unique identifier.
/// </summary>
/// <param name="uid">A unique identifier (UID).</param>
- /// <returns>A SearchCondition object representing the "UID" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UID" search criterion.</returns>
public static SearchCondition LessThan(uint uid) {
return new SearchCondition { Field = Fields.UID,
Value = "1:" + (uid - 1).ToString(), Quote = false };
@@ -205,184 +202,174 @@ public class SearchCondition {
/// <summary>
/// Finds messages that do not have the specified keyword flag set.
/// </summary>
- /// <param name="text">A valid IMAP keyword flag</param>
- /// <returns>A SearchCondition object representing the "UNKEYWORD"
- /// search criterion</returns>
+ /// <param name="text">The IMAP keyword flag to search for.</param>
+ /// <returns>A SearchCondition object representing the "UNKEYWORD" search criterion.</returns>
+ /// <exception cref="ArgumentNullException">The text parameter is null.</exception>
public static SearchCondition Unkeyword(string text) {
+ text.ThrowIfNull("text");
return new SearchCondition { Field = Fields.Unkeyword, Value = text };
}
/// <summary>
- /// Finds messages with the \Answered flag set.
+ /// Finds messages that have the \Answered flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "ANSWERED" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "ANSWERED" search criterion.</returns>
public static SearchCondition Answered() {
return new SearchCondition { Field = Fields.Answered };
}
/// <summary>
- /// Finds messages with the \Deleted flag set.
+ /// Finds messages that have the \Deleted flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "DELETED" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "DELETED" search criterion.</returns>
public static SearchCondition Deleted() {
return new SearchCondition { Field = Fields.Deleted };
}
/// <summary>
- /// Finds messages with the \Draft flag set.
+ /// Finds messages that have the \Draft flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "DRAFT" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "DRAFT" search criterion.</returns>
public static SearchCondition Draft() {
return new SearchCondition { Field = Fields.Draft };
}
/// <summary>
- /// Finds messages with the \Flagged flag set.
+ /// Finds messages that have the \Flagged flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "FLAGGED" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "FLAGGED" search criterion.</returns>
public static SearchCondition Flagged() {
return new SearchCondition { Field = Fields.Flagged };
}
/// <summary>
/// Finds messages that have the \Recent flag set but not the \Seen flag.
/// </summary>
- /// <returns>A SearchCondition object representing the "NEW" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "NEW" search criterion.</returns>
public static SearchCondition New() {
return new SearchCondition { Field = Fields.New };
}
/// <summary>
/// Finds messages that do not have the \Recent flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "OLD" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "OLD" search criterion.</returns>
public static SearchCondition Old() {
return new SearchCondition { Field = Fields.Old };
}
/// <summary>
/// Finds messages that have the \Recent flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "RECENT" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "RECENT" search criterion.</returns>
public static SearchCondition Recent() {
return new SearchCondition { Field = Fields.Recent };
}
/// <summary>
/// Finds messages that have the \Seen flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "SEEN" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "SEEN" search criterion.</returns>
public static SearchCondition Seen() {
return new SearchCondition { Field = Fields.Seen };
}
/// <summary>
/// Finds messages that do not have the \Answered flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "UNANSWERED" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UNANSWERED" search criterion.</returns>
public static SearchCondition Unanswered() {
return new SearchCondition { Field = Fields.Unanswered };
}
/// <summary>
/// Finds messages that do not have the \Deleted flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "UNDELETED" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UNDELETED" search criterion.</returns>
public static SearchCondition Undeleted() {
return new SearchCondition { Field = Fields.Undeleted };
}
/// <summary>
/// Finds messages that do not have the \Draft flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "UNDRAFT" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UNDRAFT" search criterion.</returns>
public static SearchCondition Undraft() {
return new SearchCondition { Field = Fields.Undraft };
}
/// <summary>
/// Finds messages that do not have the \Flagged flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "UNFLAGGED" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UNFLAGGED" search criterion.</returns>
public static SearchCondition Unflagged() {
return new SearchCondition { Field = Fields.Unflagged };
}
/// <summary>
/// Finds messages that do not have the \Seen flag set.
/// </summary>
- /// <returns>A SearchCondition object representing the "UNSEEN" search
- /// criterion</returns>
+ /// <returns>A SearchCondition object representing the "UNSEEN" search criterion.</returns>
public static SearchCondition Unseen() {
return new SearchCondition { Field = Fields.Unseen };
}
/// <summary>
- /// Logically ANDs multiple search conditions, meaning a message will only
- /// be included in the search result set if all conditions are met.
+ /// Logically ANDs multiple search conditions, meaning a message will only be included in the
+ /// search result if both of the ANDed conditions are met.
/// </summary>
- /// <param name="other">A search condition to logically AND this
- /// SearchCondition instance with</param>
- /// <returns>A new SearchCondition instance which can be further chained
- /// with other search conditions.</returns>
+ /// <param name="other">A search condition to logically AND this SearchCondition instance
+ /// with.</param>
+ /// <returns>A new SearchCondition instance which can be further chained with other search
+ /// conditions.</returns>
+ /// <exception cref="ArgumentNullException">The other parameter is null.</exception>
public SearchCondition And(SearchCondition other) {
+ other.ThrowIfNull("other");
return Join(string.Empty, this, other);
}
/// <summary>
- /// Logically negates search conditions, meaning a message will only
- /// be included in the search result set if the specified conditions
- /// are not met.
+ /// Logically negates search conditions, meaning a message will only be included in the search
+ /// result if the specified conditions are not met.
/// </summary>
- /// <param name="other">A search condition that must not be met by a
- /// message for it to be included in the search result set</param>
- /// <returns>A new SearchCondition instance which can be further chained
- /// with other search conditions.</returns>
+ /// <param name="other">A search condition that must not be met by a message for it to be
+ /// included in the search result set.</param>
+ /// <returns>A new SearchCondition instance which can be further chained with other search
+ /// conditions.</returns>
+ /// <exception cref="ArgumentNullException">The other parameter is null.</exception>
public SearchCondition Not(SearchCondition other) {
+ other.ThrowIfNull("other");
return Join("NOT", this, other);
}
/// <summary>
- /// Logically ORs multiple search conditions, meaning a message will be
- /// included in the search result set if it meets at least one of the
- /// conditions.
+ /// Logically ORs multiple search conditions, meaning a message will be included in the search
+ /// result if it meets at least either of the conditions.
/// </summary>
- /// <param name="other">A search condition to logically OR this
- /// SearchCondition instance with</param>
- /// <returns>A new SearchCondition instance which can be further chained
- /// with other search conditions.</returns>
+ /// <param name="other">A search condition to logically OR this SearchCondition instance
+ /// with.</param>
+ /// <returns>A new SearchCondition instance which can be further chained with other search
+ /// conditions.</returns>
+ /// <exception cref="ArgumentNullException">The other parameter is null.</exception>
public SearchCondition Or(SearchCondition other) {
+ other.ThrowIfNull("other");
return Join("OR", this, other);
}
/// <summary>
- /// The search keys which can be used with the IMAP SEARCH command, as
- /// are defined in section 6.4.4 of RFC 3501.
+ /// The search keys which can be used with the IMAP SEARCH command, as are defined in section
+ /// 6.4.4 of RFC 3501.
/// </summary>
- private enum Fields {
+ enum Fields {
BCC, Before, Body, Cc, From, Header, Keyword,
Larger, On, SentBefore, SentOn, SentSince, Since, Smaller, Subject,
Text, To, UID, Unkeyword, All, Answered, Deleted, Draft, Flagged,
New, Old, Recent, Seen, Unanswered, Undeleted, Undraft, Unflagged, Unseen
}
- private object Value { get; set; }
- private Fields? Field { get; set; }
- private List<SearchCondition> Conditions { get; set; }
- private string Operator { get; set; }
- private bool Quote = true;
+ object Value { get; set; }
+ Fields? Field { get; set; }
+ List<SearchCondition> Conditions { get; set; }
+ string Operator { get; set; }
+ bool Quote = true;
/// <summary>
- /// Joins two SearchCondition objects into a new one using the specified
- /// logical operator.
+ /// Joins two SearchCondition objects into a new one using the specified logical operator.
/// </summary>
- /// <param name="condition">The logical operator to use for joining the
- /// search conditions. Possible values are "OR", "NOT" and the empty
- /// string "" which denotes a logical AND.</param>
+ /// <param name="condition">The logical operator to use for joining the search conditions.
+ /// Possible values are "OR", "NOT" and the empty string "" which denotes a logical AND.</param>
/// <param name="left">The first SearchCondition object</param>
/// <param name="right">The second SearchCondition object</param>
- /// <returns>A new SearchCondition object representing the two
- /// search conditions joined by the specified logical operator.</returns>
- private static SearchCondition Join(string condition, SearchCondition left,
+ /// <returns>A new SearchCondition object representing the two search conditions joined by the
+ /// specified logical operator.</returns>
+ static SearchCondition Join(string condition, SearchCondition left,
SearchCondition right) {
return new SearchCondition {
Operator = condition.ToUpper(),
@@ -391,11 +378,11 @@ private enum Fields {
}
/// <summary>
- /// Constructs a string from this SearchCondition object using the proper syntax
- /// as is required for the IMAP SEARCH command.
+ /// Constructs a string from the SearchCondition object using the proper syntax as is required
+ /// for the IMAP SEARCH command.
/// </summary>
- /// <returns>A string representing this SearchCondition instance that can be
- /// used with the IMAP SEARCH command.</returns>
+ /// <returns>A string representing this SearchCondition instance that can be used with the IMAP
+ /// SEARCH command.</returns>
public override string ToString() {
if (Conditions != null && Conditions.Count > 0 && Operator != null) {
return (Operator.ToUpper() + " (" +
@@ -410,8 +397,8 @@ private enum Fields {
builder.Append(" ");
if (Val is string) {
string s = (string)Val;
- // If the string contains non-ASCII characters we must use the somewhat
- // cumbersome literal form as is outlined in RFC 3501 Section 4.3.
+ // If the string contains non-ASCII characters we must use the somewhat cumbersome literal
+ // form as is outlined in RFC 3501 Section 4.3.
if (!s.IsASCII()) {
builder.AppendLine("{" + Encoding.UTF8.GetBytes(s).Length + "}");
} else {
View
206 Util.cs
@@ -7,19 +7,17 @@
namespace S22.Imap {
/// <summary>
- /// A static utility class containing methods for decoding encoded
- /// non-ASCII data as is often used in mail messages as well as
+ /// A static utility class containing methods for decoding encoded non-ASCII data as well as
/// extension methods for some classes of the base class library.
/// </summary>
internal static class Util {
/// <summary>
- /// Returns a copy of the string enclosed in double-quotes and with escaped
- /// CRLF, back-slash and double-quote characters (as is expected by some
- /// commands of the IMAP protocol).
+ /// Returns a copy of the string enclosed in double-quotes and with escaped CRLF, back-slash
+ /// and double-quote characters (as is expected by some commands of the IMAP protocol).
/// </summary>
/// <param name="value">Extends the System.String class</param>
- /// <returns>A copy of the string enclosed in double-quotes and properly
- /// escaped as is required by the IMAP protocol.</returns>
+ /// <returns>A copy of the string enclosed in double-quotes and properly escaped as is required
+ /// by the IMAP protocol.</returns>
internal static string QuoteString(this string value) {
return "\"" + value
.Replace("\\", "\\\\")
@@ -32,20 +30,17 @@ internal static class Util {
/// Returns true if the string contains only ASCII characters.
/// </summary>
/// <param name="s">Extension method for the String class.</param>
- /// <returns>Returns true if the string contains only ASCII characters,
- /// otherwise false is returned.</returns>
+ /// <returns>true if the string contains only ASCII characters; Otherwise false.</returns>
internal static bool IsASCII(this string s) {
return s.All(c => c < 127);
}
/// <summary>
- /// Splits a string into chunks of the specified number of
- /// characters.
+ /// Splits a string into chunks of the specified number of characters.
/// </summary>
/// <param name="str">Extension method for the String class.</param>
- /// <param name="characters">The length of a chunk, measured in
- /// characters.</param>
- /// <returns>An array of string chunks</returns>
+ /// <param name="characters">The length of a chunk, measured in characters.</param>
+ /// <returns>An array of string chunks.</returns>
[Obsolete]
internal static string[] ToChunks(this string str, int characters) {
List<string> list = new List<string>();
@@ -60,18 +55,15 @@ internal static class Util {
}
/// <summary>
- /// Returns a value indicating whether the specified string occurs within
- /// this string. A parameter specifies the type of search to use for the
- /// specified string.
+ /// Determines whether the specified string occurs within this string.
/// </summary>
/// <param name="str">Extension method for the String class.</param>
/// <param name="value">The string to seek.</param>
- /// <param name="comparer">One of the enumeration values that specifies
- /// the rules for the search.</param>
- /// <returns>true if the value parameter occurs within this string, or
- /// if value is the empty string (""); otherwise, false.</returns>
- /// <exception cref="ArgumentNullException">Thrown if the value
- /// parameter is null.</exception>
+ /// <param name="comparer">One of the enumeration values that specifies the rules for the
+ /// search.</param>
+ /// <returns>true if the value parameter occurs within this string, or if value is the empty
+ /// string (""); otherwise, false.</returns>
+ /// <exception cref="ArgumentNullException">The value parameter is null.</exception>
internal static bool Contains(this string str, string value,
StringComparison comparer) {
return str.IndexOf(value, comparer) >= 0;
@@ -80,26 +72,24 @@ internal static class Util {
/// <summary>
/// Raises the event. Ensures the event is only raised, if it is not null.
/// </summary>
- /// <typeparam name="T">Extends System.EventHandler class</typeparam>
- /// <param name="event">Extends System.EventHandler class</param>
- /// <param name="sender">The sender of the event</param>
- /// <param name="args">The event arguments associated with this event</param>
+ /// <typeparam name="T">Extends System.EventHandler class.</typeparam>
+ /// <param name="event">Extends System.EventHandler class.</param>
+ /// <param name="sender">The sender of the event.</param>
+ /// <param name="args">The event arguments associated with this event.</param>
internal static void Raise<T>(this EventHandler<T> @event, object sender, T args)
where T : EventArgs {
- if (@event == null)
- return;
- @event(sender, args);
+ EventHandler<T> handler = @event;
+ if (handler != null)
+ handler(sender, args);
}
/// <summary>
/// Throws an ArgumentNullException if the given data item is null.
/// </summary>
/// <param name="data">The item to check for nullity.</param>
- /// <param name="name">The name to use when throwing an
- /// exception, if necessary</param>
+ /// <param name="name">The name to use when throwing an exception, if necessary.</param>
/// <remarks>Courtesy of Jon Skeet.</remarks>
- internal static void ThrowIfNull<T>(this T data, string name)
- where T : class {
+ internal static void ThrowIfNull<T>(this T data, string name) where T : class {
if (data == null)
throw new ArgumentNullException(name);
}
@@ -109,15 +99,14 @@ internal static void ThrowIfNull<T>(this T data, string name)
/// </summary>
/// <param name="data">The item to check for nullity.</param>
/// <remarks>Courtesy of Jon Skeet.</remarks>
- internal static void ThrowIfNull<T>(this T data)
- where T : class {
+ internal static void ThrowIfNull<T>(this T data) where T : class {
if (data == null)
throw new ArgumentNullException();
}
/// <summary>
- /// Throws an ArgumentNullException if the given string is null and
- /// throws an ArgumentException if the given string is empty.
+ /// Throws an ArgumentNullException if the given string is null or throws an ArgumentException
+ /// if the given string is empty.
/// </summary>
/// <param name="s">The string to check for nullity and emptiness.</param>
internal static void ThrowIfNullOrEmpty(this string s) {
@@ -128,12 +117,11 @@ internal static void ThrowIfNull<T>(this T data)
}
/// <summary>
- /// Throws an ArgumentNullException if the given string is null and
- /// throws an ArgumentException if the given string is empty.
+ /// Throws an ArgumentNullException if the given string is null or throws an ArgumentException
+ /// if the given string is empty.
/// </summary>
/// <param name="s">The string to check for nullity and emptiness.</param>
- /// <param name="name">The name to use when throwing an
- /// exception, if necessary.</param>
+ /// <param name="name">The name to use when throwing an exception, if necessary.</param>
internal static void ThrowIfNullOrEmpty(this string s, string name) {
if (s == null)
throw new ArgumentNullException(name);
@@ -142,14 +130,12 @@ internal static void ThrowIfNull<T>(this T data)
}
/// <summary>
- /// Reads an unsigned short value from the underlying stream, optionally
- /// using big endian byte ordering.
+ /// Reads an unsigned short value from the underlying stream, optionally using big-endian byte
+ /// ordering.
/// </summary>
/// <param name="reader">Extension method for BinaryReader.</param>
- /// <param name="bigEndian">Set to true to interpret the short value
- /// as big endian value.</param>
- /// <returns>The 16-byte unsigned short value read from the underlying
- /// stream.</returns>
+ /// <param name="bigEndian">Set to true to interpret the short value as big endian value.</param>
+ /// <returns>The 16-byte unsigned short value read from the underlying stream.</returns>
internal static ushort ReadUInt16(this BinaryReader reader,
bool bigEndian) {
if (!bigEndian)
@@ -163,12 +149,10 @@ internal static void ThrowIfNull<T>(this T data)
/// <summary>
/// Decodes a string composed of one or several MIME 'encoded-words'.
/// </summary>
- /// <param name="words">A string to composed of one or several MIME
- /// 'encoded-words'</param>
- /// <exception cref="FormatException">Thrown when an unknown encoding
- /// (other than Q-Encoding or Base64) is encountered.</exception>
- /// <returns>A concatenation of all enconded-words in the passed
- /// string</returns>
+ /// <param name="words">A string to composed of one or several MIME 'encoded-words'.</param>
+ /// <exception cref="FormatException">An unknown encoding (other than Q-Encoding or Base64) is
+ /// encountered.</exception>
+ /// <returns>A concatenation of all enconded-words in the passed string</returns>
public static string DecodeWords(string words) {
if (String.IsNullOrEmpty(words))
return String.Empty;
@@ -176,12 +160,10 @@ internal static void ThrowIfNull<T>(this T data)
if (matches.Count == 0)
return words;
// http://tools.ietf.org/html/rfc2047#page-10:
- // When displaying a particular header field that contains multiple
- // 'encoded-word's, any 'linear-white-space' that separates a pair of
- // adjacent 'encoded-word's is ignored. (This is to allow the use of
- // multiple 'encoded-word's to represent long strings of unencoded text,
- // without having to separate 'encoded-word's where spaces occur in the
- // unencoded text.) */
+ // When displaying a particular header field that contains multiple 'encoded-word's, any
+ // 'linear-white-space' that separates a pair of adjacent 'encoded-word's is ignored. (This is
+ // to allow the use of multiple 'encoded-word's to represent long strings of unencoded text,
+ // without having to separate 'encoded-word's where spaces occur in the unencoded text.)
// line-white-space ref: http://tools.ietf.org/html/rfc2616#page-16
StringBuilder decoded = new StringBuilder();
// Keep track of and use separation data between 'encoded-word's.
@@ -198,33 +180,30 @@ internal static void ThrowIfNull<T>(this T data)
}
/// <summary>
- /// Internal function reuse to add separation between multiple 'encoded-word's
- /// correctly.
+ /// Internal function reuse to add separation between multiple 'encoded-word's correctly.
/// </summary>
- private static void HandleFillData(StringBuilder decoded, string data) {
+ static void HandleFillData(StringBuilder decoded, string data) {
if (String.IsNullOrEmpty(data))
return;
// Cr or Lf is never in the result.
string FillData = data.Replace("\r", "").Replace("\n", "");
- // Any 'linear-white-space' that separates a pair of adjacent 'encoded-word's
- // is ignored.
+ // Any 'linear-white-space' that separates a pair of adjacent 'encoded-word's is ignored.
if (FillData.Trim().Length != 0)
decoded.Append(FillData);
}
- private static readonly Regex rxDecodeWord =
+ static readonly Regex rxDecodeWord =
new Regex(@"=\?([A-Za-z0-9\-_]+)\?([BbQq])\?([^\?]+)\?=", RegexOptions.Compiled);
/// <summary>
/// Decodes a MIME 'encoded-word' string.
/// </summary>
/// <param name="word">The encoded word to decode</param>
- /// <exception cref="FormatException">Thrown when an unknown encoding
- /// (other than Q-Encoding or Base64) is encountered.</exception>
+ /// <exception cref="FormatException">An unknown encoding (other than Q-Encoding or Base64) is
+ /// encountered.</exception>
/// <returns>A decoded string</returns>
- /// <remarks>MIME encoded-word syntax is a way to encode strings that
- /// contain non-ASCII data. Commonly used encodings for the encoded-word
- /// sytax are Q-Encoding and Base64. For an in-depth description, refer
- /// to RFC 2047</remarks>
+ /// <remarks>MIME encoded-word syntax is a way to encode strings that contain non-ASCII data.
+ /// Commonly used encodings for the encoded-word sytax are Q-Encoding and Base64. For an
+ /// in-depth description, refer to RFC 2047.</remarks>
internal static string DecodeWord(string word) {
if (String.IsNullOrEmpty(word))
return String.Empty;
@@ -246,15 +225,12 @@ internal static void ThrowIfNull<T>(this T data)
}
/// <summary>
- /// Takes a Q-encoded string and decodes it using the specified
- /// encoding.
+ /// Takes a Q-encoded string and decodes it using the specified encoding.
/// </summary>
- /// <param name="value">The Q-encoded string to decode</param>
- /// <param name="encoding">The encoding to use for encoding the
- /// returned string</param>
- /// <exception cref="FormatException">Thrown if the string is
- /// not a valid Q-encoded string.</exception>
- /// <returns>A Q-decoded string</returns>
+ /// <param name="value">The Q-encoded string to decode.</param>
+ /// <param name="encoding">The encoding to use for encoding the returned string.</param>
+ /// <exception cref="FormatException">The string is not a valid Q-encoded string.</exception>
+ /// <returns>The Q-decoded string.</returns>
internal static string QDecode(string value, Encoding encoding) {
try {
using (MemoryStream m = new MemoryStream()) {
@@ -272,22 +248,18 @@ internal static void ThrowIfNull<T>(this T data)
return encoding.GetString(m.ToArray());
}
} catch {
-