/// <summary>
/// Takes posession of the <see cref="ImapStream"/> and reads the greeting.
/// </summary>
/// <param name="imap">The IMAP stream.</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <exception cref="System.OperationCanceledException">
/// The operation was canceled via the cancellation token.
/// </exception>
/// <exception cref="System.IO.IOException">
/// An I/O error occurred.
/// </exception>
/// <exception cref="ImapProtocolException">
/// An IMAP protocol error occurred.
/// </exception>
public void Connect(ImapStream imap, CancellationToken cancellationToken)
{
if (stream != null)
stream.Dispose ();
TagPrefix = (char) ('A' + (TagPrefixIndex++ % 26));
ProtocolVersion = ImapProtocolVersion.Unknown;
Capabilities = ImapCapabilities.None;
AuthenticationMechanisms.Clear ();
CompressionAlgorithms.Clear ();
ThreadingAlgorithms.Clear ();
SupportedCharsets.Clear ();
SupportedContexts.Clear ();
// TODO: should we clear the folder cache?
State = ImapEngineState.Connected;
SupportedCharsets.Add ("UTF-8");
CapabilitiesVersion = 0;
QResyncEnabled = false;
stream = imap;
Tag = 0;
try {
var token = stream.ReadToken (cancellationToken);
if (token.Type != ImapTokenType.Asterisk)
throw UnexpectedToken (token, true);
token = stream.ReadToken (cancellationToken);
if (token.Type != ImapTokenType.Atom)
throw UnexpectedToken (token, true);
var atom = (string) token.Value;
switch (atom) {
case "PREAUTH": State = ImapEngineState.Authenticated; break;
case "OK": State = ImapEngineState.PreAuth; break;
case "BYE":
// FIXME: should we throw a special exception here?
throw UnexpectedToken (token, true);
default:
throw UnexpectedToken (token, true);
}
token = stream.ReadToken (cancellationToken);
if (token.Type == ImapTokenType.OpenBracket) {
var code = ParseResponseCode (cancellationToken);
if (code.Type == ImapResponseCodeType.Alert)
OnAlert (code.Message);
} else if (token.Type != ImapTokenType.Eoln) {
// throw away any remaining text up until the end of the line
ReadLine (cancellationToken);
}
} catch {
Disconnect ();
throw;
}
}