/// <summary> /// Gets a substream of the specified message. /// </summary> /// <remarks> /// <para>Gets a substream of the specified message. If the starting offset is beyond /// the end of the specified section of the message, an empty stream is returned. If /// the number of bytes desired extends beyond the end of the section, a truncated /// stream will be returned.</para> /// <para>For more information about how to construct the <paramref name="section"/>, /// see Section 6.4.5 of RFC3501.</para> /// </remarks> /// <returns>The stream.</returns> /// <param name="index">The index of the message.</param> /// <param name="section">The desired section of the message.</param> /// <param name="offset">The starting offset of the first desired byte.</param> /// <param name="count">The number of bytes desired.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress reporting mechanism.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="section"/> is <c>null</c>. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <para><paramref name="index"/> is out of range.</para> /// <para>-or-</para> /// <para><paramref name="offset"/> is negative.</para> /// <para>-or-</para> /// <para><paramref name="count"/> is negative.</para> /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="ImapClient"/> has been disposed. /// </exception> /// <exception cref="ServiceNotConnectedException"> /// The <see cref="ImapClient"/> is not connected. /// </exception> /// <exception cref="ServiceNotAuthenticatedException"> /// The <see cref="ImapClient"/> is not authenticated. /// </exception> /// <exception cref="FolderNotOpenException"> /// The <see cref="ImapFolder"/> is not currently open. /// </exception> /// <exception cref="MessageNotFoundException"> /// The IMAP server did not return the requested message stream. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="ImapProtocolException"> /// The server's response contained unexpected tokens. /// </exception> /// <exception cref="ImapCommandException"> /// The server replied with a NO or BAD response. /// </exception> public override Stream GetStream (int index, string section, int offset, int count, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null) { if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); if (section == null) throw new ArgumentNullException ("section"); if (offset < 0) throw new ArgumentOutOfRangeException ("offset"); if (count < 0) throw new ArgumentOutOfRangeException ("count"); CheckState (true, false); if (count == 0) return new MemoryStream (); var command = string.Format ("FETCH {0} (BODY.PEEK[{1}]<{2}.{3}>)\r\n", index + 1, section, offset, count); var ic = new ImapCommand (Engine, cancellationToken, this, command); var ctx = new FetchStreamContext (progress); Stream stream; ic.RegisterUntaggedHandler ("FETCH", FetchStream); ic.UserData = ctx; Engine.QueueCommand (ic); try { Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Response != ImapCommandResponse.Ok) throw ImapCommandException.Create ("FETCH", ic); if (!ctx.Sections.TryGetValue (section, out stream)) throw new MessageNotFoundException ("The IMAP server did not return the requested stream."); ctx.Sections.Remove (section); } finally { ctx.Dispose (); } return stream; }
/// <summary> /// Gets a substream of the specified body part. /// </summary> /// <remarks> /// <para>Gets a substream of the specified message.</para> /// <para>For more information about how to construct the <paramref name="section"/>, /// see Section 6.4.5 of RFC3501.</para> /// </remarks> /// <returns>The stream.</returns> /// <param name="uid">The UID of the message.</param> /// <param name="section">The desired section of the message.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress reporting mechanism.</param> /// <exception cref="System.ArgumentException"> /// <paramref name="uid"/> is invalid. /// </exception> /// <exception cref="System.ArgumentNullException"> /// <paramref name="section"/> is <c>null</c>. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="ImapClient"/> has been disposed. /// </exception> /// <exception cref="ServiceNotConnectedException"> /// The <see cref="ImapClient"/> is not connected. /// </exception> /// <exception cref="ServiceNotAuthenticatedException"> /// The <see cref="ImapClient"/> is not authenticated. /// </exception> /// <exception cref="FolderNotOpenException"> /// The <see cref="ImapFolder"/> is not currently open. /// </exception> /// <exception cref="MessageNotFoundException"> /// The IMAP server did not return the requested message stream. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="ImapProtocolException"> /// The server's response contained unexpected tokens. /// </exception> /// <exception cref="ImapCommandException"> /// The server replied with a NO or BAD response. /// </exception> public override Stream GetStream (UniqueId uid, string section, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null) { if (uid.Id == 0) throw new ArgumentException ("The uid is invalid.", "uid"); if (section == null) throw new ArgumentNullException ("section"); CheckState (true, false); var command = string.Format ("UID FETCH {0} (BODY.PEEK[{1}])\r\n", uid.Id, section); var ic = new ImapCommand (Engine, cancellationToken, this, command); var ctx = new FetchStreamContext (progress); Stream stream; ic.RegisterUntaggedHandler ("FETCH", FetchStream); ic.UserData = ctx; Engine.QueueCommand (ic); try { Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Response != ImapCommandResponse.Ok) throw ImapCommandException.Create ("FETCH", ic); if (!ctx.Sections.TryGetValue (section, out stream)) throw new MessageNotFoundException ("The IMAP server did not return the requested stream."); ctx.Sections.Remove (section); } finally { ctx.Dispose (); } return stream; }
/// <summary> /// Gets a substream of the specified message. /// </summary> /// <remarks> /// Fetches a substream of the message. If the starting offset is beyond /// the end of the message, an empty stream is returned. If the number of /// bytes desired extends beyond the end of the message, a truncated stream /// will be returned. /// </remarks> /// <returns>The stream.</returns> /// <param name="uid">The UID of the message.</param> /// <param name="offset">The starting offset of the first desired byte.</param> /// <param name="count">The number of bytes desired.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress reporting mechanism.</param> /// <exception cref="System.ArgumentException"> /// <paramref name="uid"/> is invalid. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <para><paramref name="offset"/> is negative.</para> /// <para>-or-</para> /// <para><paramref name="count"/> is negative.</para> /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="ImapClient"/> has been disposed. /// </exception> /// <exception cref="ServiceNotConnectedException"> /// The <see cref="ImapClient"/> is not connected. /// </exception> /// <exception cref="ServiceNotAuthenticatedException"> /// The <see cref="ImapClient"/> is not authenticated. /// </exception> /// <exception cref="FolderNotOpenException"> /// The <see cref="ImapFolder"/> is not currently open. /// </exception> /// <exception cref="MessageNotFoundException"> /// The IMAP server did not return the requested message stream. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="ImapProtocolException"> /// The server's response contained unexpected tokens. /// </exception> /// <exception cref="ImapCommandException"> /// The server replied with a NO or BAD response. /// </exception> public override Stream GetStream (UniqueId uid, int offset, int count, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null) { if (uid.Id == 0) throw new ArgumentException ("The uid is invalid.", "uid"); if (offset < 0) throw new ArgumentOutOfRangeException ("offset"); if (count < 0) throw new ArgumentOutOfRangeException ("count"); CheckState (true, false); if (count == 0) return new MemoryStream (); var ic = new ImapCommand (Engine, cancellationToken, this, "UID FETCH %u (BODY.PEEK[]<%d.%d>)\r\n", uid.Id, offset, count); var ctx = new FetchStreamContext (progress); Stream stream; ic.RegisterUntaggedHandler ("FETCH", FetchStream); ic.UserData = ctx; Engine.QueueCommand (ic); try { Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Response != ImapCommandResponse.Ok) throw ImapCommandException.Create ("FETCH", ic); if (!ctx.Sections.TryGetValue (string.Empty, out stream)) throw new MessageNotFoundException ("The IMAP server did not return the requested stream."); ctx.Sections.Remove (string.Empty); } finally { ctx.Dispose (); } return stream; }
/// <summary> /// Gets the specified body part. /// </summary> /// <remarks> /// Gets the specified body part. /// </remarks> /// <returns>The body part.</returns> /// <param name="index">The index of the message.</param> /// <param name="partSpecifier">The body part specifier.</param> /// <param name="headersOnly"><c>true</c> if only the headers should be downloaded; otherwise, <c>false</c>></param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress reporting mechanism.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="partSpecifier"/> is <c>null</c>. /// </exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="index"/> is out of range. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="ImapClient"/> has been disposed. /// </exception> /// <exception cref="ServiceNotConnectedException"> /// The <see cref="ImapClient"/> is not connected. /// </exception> /// <exception cref="ServiceNotAuthenticatedException"> /// The <see cref="ImapClient"/> is not authenticated. /// </exception> /// <exception cref="FolderNotOpenException"> /// The <see cref="ImapFolder"/> is not currently open. /// </exception> /// <exception cref="MessageNotFoundException"> /// The IMAP server did not return the requested message. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="ImapProtocolException"> /// The server's response contained unexpected tokens. /// </exception> /// <exception cref="ImapCommandException"> /// The server replied with a NO or BAD response. /// </exception> public MimeEntity GetBodyPart (int index, string partSpecifier, bool headersOnly, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null) { if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); if (partSpecifier == null) throw new ArgumentNullException ("partSpecifier"); CheckState (true, false); string[] tags; var command = string.Format ("FETCH {0} ({1})\r\n", index + 1, GetBodyPartQuery (partSpecifier, headersOnly, out tags)); var ic = new ImapCommand (Engine, cancellationToken, this, command); var ctx = new FetchStreamContext (progress); ChainedStream chained; bool dispose = false; Stream stream; ic.RegisterUntaggedHandler ("FETCH", FetchStream); ic.UserData = ctx; Engine.QueueCommand (ic); try { Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Response != ImapCommandResponse.Ok) throw ImapCommandException.Create ("FETCH", ic); chained = new ChainedStream (); foreach (var tag in tags) { if (!ctx.Sections.TryGetValue (tag, out stream)) throw new MessageNotFoundException ("The IMAP server did not return the requested body part."); if (!(stream is MemoryStream || stream is MemoryBlockStream)) dispose = true; chained.Add (stream); } foreach (var tag in tags) ctx.Sections.Remove (tag); } finally { ctx.Dispose (); } var entity = ParseEntity (chained, dispose, cancellationToken); if (partSpecifier.Length == 0) { for (int i = entity.Headers.Count; i > 0; i--) { var header = entity.Headers[i - 1]; if (!header.Field.StartsWith ("Content-", StringComparison.OrdinalIgnoreCase)) entity.Headers.RemoveAt (i - 1); } } return entity; }
/// <summary> /// Gets the specified message. /// </summary> /// <remarks> /// Gets the specified message. /// </remarks> /// <returns>The message.</returns> /// <param name="index">The index of the message.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress reporting mechanism.</param> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="index"/> is out of range. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="ImapClient"/> has been disposed. /// </exception> /// <exception cref="ServiceNotConnectedException"> /// The <see cref="ImapClient"/> is not connected. /// </exception> /// <exception cref="ServiceNotAuthenticatedException"> /// The <see cref="ImapClient"/> is not authenticated. /// </exception> /// <exception cref="FolderNotOpenException"> /// The <see cref="ImapFolder"/> is not currently open. /// </exception> /// <exception cref="MessageNotFoundException"> /// The IMAP server did not return the requested message. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="ImapProtocolException"> /// The server's response contained unexpected tokens. /// </exception> /// <exception cref="ImapCommandException"> /// The server replied with a NO or BAD response. /// </exception> public override MimeMessage GetMessage (int index, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null) { if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); CheckState (true, false); var ic = new ImapCommand (Engine, cancellationToken, this, "FETCH %d (BODY.PEEK[])\r\n", index + 1); var ctx = new FetchStreamContext (progress); Stream stream; ic.RegisterUntaggedHandler ("FETCH", FetchStream); ic.UserData = ctx; Engine.QueueCommand (ic); try { Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Response != ImapCommandResponse.Ok) throw ImapCommandException.Create ("FETCH", ic); if (!ctx.Sections.TryGetValue (string.Empty, out stream)) throw new MessageNotFoundException ("The IMAP server did not return the requested message."); ctx.Sections.Remove (string.Empty); } finally { ctx.Dispose (); } return ParseMessage (stream, cancellationToken); }
/// <summary> /// Gets the specified message. /// </summary> /// <remarks> /// Gets the specified message. /// </remarks> /// <returns>The message.</returns> /// <param name="uid">The UID of the message.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress reporting mechanism.</param> /// <exception cref="System.ArgumentException"> /// <paramref name="uid"/> is invalid. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The <see cref="ImapClient"/> has been disposed. /// </exception> /// <exception cref="ServiceNotConnectedException"> /// The <see cref="ImapClient"/> is not connected. /// </exception> /// <exception cref="ServiceNotAuthenticatedException"> /// The <see cref="ImapClient"/> is not authenticated. /// </exception> /// <exception cref="FolderNotOpenException"> /// The <see cref="ImapFolder"/> is not currently open. /// </exception> /// <exception cref="System.OperationCanceledException"> /// The operation was canceled via the cancellation token. /// </exception> /// <exception cref="System.IO.IOException"> /// An I/O error occurred. /// </exception> /// <exception cref="ImapProtocolException"> /// The server's response contained unexpected tokens. /// </exception> /// <exception cref="ImapCommandException"> /// The server replied with a NO or BAD response. /// </exception> public override MimeMessage GetMessage (UniqueId uid, CancellationToken cancellationToken = default (CancellationToken), ITransferProgress progress = null) { if (uid.Id == 0) throw new ArgumentException ("The uid is invalid.", "uid"); CheckState (true, false); var ic = new ImapCommand (Engine, cancellationToken, this, "UID FETCH %u (BODY.PEEK[])\r\n", uid.Id); var ctx = new FetchStreamContext (progress); Stream stream; ic.RegisterUntaggedHandler ("FETCH", FetchStream); ic.UserData = ctx; Engine.QueueCommand (ic); try { Engine.Wait (ic); ProcessResponseCodes (ic, null); if (ic.Result != ImapCommandResult.Ok) throw ImapCommandException.Create ("FETCH", ic); if (!ctx.Sections.TryGetValue (string.Empty, out stream)) throw new ImapCommandException ("The IMAP server did not return the requested message."); ctx.Sections.Remove (string.Empty); } finally { ctx.Dispose (); } return ParseMessage (stream, cancellationToken); }