private ImapCommandResult PostProcessTransaction(IImapTransaction t)
        {
            lastTransactionResult = t.Result;

              switch (t.Result.Code) {
            /*
             * disconnect without processing responses
             */
            case ImapCommandResultCode.InternalError:
              CloseConnection();
              throw new ImapException(t.Result.Description, t.Result.Exception);

            case ImapCommandResultCode.SocketTimeout:
              CloseConnection();
              throw new TimeoutException(string.Format("socket timeout in {0}", t.GetType().FullName), t.Result.Exception);

            case ImapCommandResultCode.ConnectionError:
            case ImapCommandResultCode.UpgradeError:
              CloseConnection();
              throw t.Result.Exception;
               }

              ProcessUpdatedSizeAndStatusResponse(t.Result);

              if (t.Result.Code == ImapCommandResultCode.Bye) {
            TransitStateTo(ImapSessionState.NotAuthenticated);
            CloseConnection();
              }

              return t.Result;
        }
Beispiel #2
0
 public static void Log(IImapTransaction transaction, string format, params object[] args)
 {
     Verbose("CID:{0} {1}: {2}",
       transaction.Connection.Id,
       transaction.GetType().Name.Replace("Transaction", string.Empty),
       args == null ? format : string.Format(format, args));
 }
        private IAsyncResult BeginProcessTransaction(IImapTransaction t, bool exceptionIfIncapable)
        {
            PreProcessTransaction(t, exceptionIfIncapable);

              var processTransaction = new ProcessTransactionDelegate(ProcessTransactionInternal);

              return new TransactionAsyncResult(t, processTransaction.BeginInvoke(t, null, null));
        }
Beispiel #4
0
        public static void LogRequest(IImapTransaction transaction)
        {
            var args = new StringBuilder();

              foreach (var p in transaction.RequestArguments) {
            var val = (p.Value == null) ? string.Empty : p.Value.ToString();

            if (0x100 < val.Length)
              val = val.Substring(0, 0x100) + " ...";

            args.AppendFormat("'{0}'=>'{1}'; ", p.Key, val);
              }

              Log(transaction,
              args.ToString(),
              null);
        }
        private ImapCommandResult AuthenticateInternal(IImapTransaction t,
                                                   string username,
                                                   ImapAuthenticationMechanism authenticationMechanism,
                                                   bool reissueCapability)
        {
            var result = ProcessTransaction(t);
              var refferalResponseCode = result.GetResponseCode(ImapResponseCode.Referral);

              if (refferalResponseCode != null) {
            // RFC 2221 IMAP4 Login Referrals
            // http://tools.ietf.org/html/rfc2221
            // 4.1. LOGIN and AUTHENTICATE Referrals
            //    An IMAP4 server MAY respond to a LOGIN or AUTHENTICATE command with a
            //    home server referral if it wishes to direct the user to another IMAP4
            //    server.
            var referToUri = ImapResponseTextConverter.FromReferral(refferalResponseCode.ResponseText)[0];

            if (handlesReferralAsException) {
              throw new ImapLoginReferralException(string.Format("try another server: '{0}'", refferalResponseCode.ResponseText.Text),
                                               referToUri);
            }
            else {
              Trace.Info("login referral: '{0}'", refferalResponseCode.ResponseText.Text);

              if (result.Succeeded)
            Trace.Info("  another server available at {0}", referToUri);
              else
            Trace.Info("  try to connect to {0}", referToUri);
            }
              }

              if (result.Succeeded) {
            UpdateAuthority(username, authenticationMechanism);
            TransitStateTo(ImapSessionState.Authenticated);

            // 6.2.2. AUTHENTICATE Command
            //       A server MAY include a CAPABILITY response code in the tagged OK
            //       response of a successful AUTHENTICATE command in order to send
            //       capabilities automatically.

            // 6.2.3. LOGIN Command
            //       A server MAY include a CAPABILITY response code in the tagged OK
            //       response to a successful LOGIN command in order to send
            //       capabilities automatically.  It is unnecessary for a client to
            //       send a separate CAPABILITY command if it recognizes these
            //       automatic capabilities.
            var capabilityResponseCode = result.GetResponseCode(ImapResponseCode.Capability);

            if (capabilityResponseCode == null) {
              var capability = result.GetResponse(ImapDataResponseType.Capability);

              if (capability != null) {
            SetServerCapabilities(ImapDataResponseConverter.FromCapability(capability));
            reissueCapability = false;
              }
            }
            else {
              SetServerCapabilities(ImapResponseTextConverter.FromCapability(capabilityResponseCode.ResponseText));
              reissueCapability = false;
            }
              }
              else {
            return result;
              }

              if (reissueCapability)
            Capability();

              return result;
        }
Beispiel #6
0
 public static void LogResponse(IImapTransaction transaction)
 {
     Log(transaction,
       "{0} {1}",
       transaction.Result.Code,
       transaction.Result.ResultText);
 }
 public TransactionAsyncResult(IImapTransaction transaction, IAsyncResult processTransactionAsyncResult)
 {
     this.transaction = transaction;
     this.processTransactionAsyncResult = processTransactionAsyncResult;
 }
        private IImapTransaction ProcessTransactionInternal(IImapTransaction t)
        {
            lock (transactionLockObject) {
            Trace.LogRequest(t);

            if (t is IdleTransaction)
              TraceInfo("idling");

            t.Process();

            if (t is IdleTransaction)
              TraceInfo("done");

            Trace.LogResponse(t);

            return t;
              }
        }
        private ImapCommandResult ProcessTransaction(IImapTransaction t)
        {
            if (transactionTimeout == Timeout.Infinite) {
            // no timeout
            PreProcessTransaction(t, handlesIncapableAsException);

            ProcessTransactionInternal(t);

            return PostProcessTransaction(t);
              }
              else {
            var async = BeginProcessTransaction(t, handlesIncapableAsException);

            if (async.AsyncWaitHandle.WaitOne(transactionTimeout, false)) {
              return EndProcessTransaction(async);
            }
            else {
              CloseConnection();
              throw new TimeoutException(string.Format("transaction timeout ({0})", t.GetType().FullName));
            }
              }
        }
        private void PreProcessTransaction(IImapTransaction t, bool exceptionIfIncapable)
        {
            // TODO: '5.5. Multiple Commands in Progress'
              //   The following are examples of valid non-waiting command sequences:
              //      FETCH + STORE + SEARCH + CHECK
              //      STORE + COPY + EXPUNGE
              if (IsTransactionProceeding)
            throw new InvalidOperationException("another transaction proceesing");

              RejectIdling();

              // check and set literal options
              var isNonSyncLiteralCapable = serverCapabilities.Has(ImapCapability.LiteralNonSync);
              var isLiteral8Capable = serverCapabilities.Has(ImapCapability.Binary);
              var containsNonSyncLiteral = false;
              var containsLiteral8 = false;

              TraverseTransactionRequestArgumentLiterals(t.RequestArguments, delegate(IImapLiteralString literal) {
            var syncMode = literal.Options & ImapLiteralOptions.SynchronizationMode;
            var literalMode = literal.Options & ImapLiteralOptions.LiteralMode;

            switch (syncMode) {
              case ImapLiteralOptions.NonSynchronizingIfCapable:
            syncMode = isNonSyncLiteralCapable ? ImapLiteralOptions.NonSynchronizing : ImapLiteralOptions.Synchronizing;
            break;
              case ImapLiteralOptions.NonSynchronizing:
            containsNonSyncLiteral = true;
            break;
            }

            switch (literalMode) {
              case ImapLiteralOptions.Literal8IfCapable:
            literalMode = isLiteral8Capable ? ImapLiteralOptions.Literal8 : ImapLiteralOptions.Literal;
            break;
              case ImapLiteralOptions.Literal8:
            containsLiteral8 = true;
            break;
            }

            literal.Options = (syncMode | literalMode)
                          | (literal.Options & ~(ImapLiteralOptions.SynchronizationMode | ImapLiteralOptions.LiteralMode));
              });

              // check capability
              if (!exceptionIfIncapable)
            return;

              if (!serverCapabilities.Has(Imap4.ImapCapability.Imap4Rev1) && !(t is CapabilityTransaction))
            throw new ImapIncapableException(ImapCapability.Imap4Rev1);

              if (containsNonSyncLiteral && !isNonSyncLiteralCapable)
            throw new ImapIncapableException(ImapCapability.LiteralNonSync);
              if (containsLiteral8 && !isLiteral8Capable)
            throw new ImapIncapableException(ImapCapability.Binary);

              CheckServerCapability(t as IImapExtension);
              CheckServerCapability(t as IImapMultipleExtension);

              foreach (var arg in t.RequestArguments.Values) {
            CheckServerCapability(arg as IImapExtension);
            CheckServerCapability(arg as IImapMultipleExtension);
              }
        }