Esempio n. 1
0
            public async Task CheckAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CheckAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    if (_ConnectionState != eConnectionState.selected)
                    {
                        return;
                    }

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.Add(kCheckCommandPart);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("check success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 2
0
        private async Task ZMessagesFetchAsync(cMethodControl pMC, cSession pSession, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMessagesFetchAsync), pMC, pMessageHandles, pItems);

            if (pMessageHandles.Count == 0)
            {
                return;
            }
            if (pItems.IsEmpty)
            {
                return;
            }

            if (pMessageHandles.TrueForAll(h => h.Contains(pItems)))
            {
                return;
            }

            cProgress lProgress;

            if (pConfiguration == null)
            {
                lProgress = new cProgress();
            }
            else
            {
                mSynchroniser.InvokeActionInt(pConfiguration.SetCount, pMessageHandles.Count, lContext);
                lProgress = new cProgress(mSynchroniser, pConfiguration.Increment);
            }

            await pSession.FetchCacheItemsAsync(pMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false);
        }
Esempio n. 3
0
            public async Task NoOpAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(NoOpAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState < eConnectionState.notauthenticated || _ConnectionState > eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kNoOpCommandPart);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceVerbose("noop success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 4
0
            public async Task <iMailboxHandle> RenameAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cMailboxName pMailboxName, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(RenameAsync), pMC, pMailboxHandle, pMailboxName);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pMailboxName == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxName));
                }

                var lItem = mMailboxCache.CheckHandle(pMailboxHandle);

                if (!mCommandPartFactory.TryAsMailbox(pMailboxName.Path, pMailboxName.Delimiter, out var lMailboxCommandPart, out _))
                {
                    throw new ArgumentOutOfRangeException(nameof(pMailboxName));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kRenameCommandPart, lItem.MailboxNameCommandPart, cCommandPart.Space, lMailboxCommandPart);

                    if (pMailboxHandle.MailboxName.IsInbox)
                    {
                        lItem = null;                                     // renaming the inbox has special behaviour
                    }
                    var lHook = new cRenameCommandHook(mMailboxCache, lItem, pMailboxName);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("rename success");
                        return(lHook.MailboxHandle);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 5
0
        private async Task ZSelectAsync(iMailboxHandle pMailboxHandle, bool pForUpdate, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZSelectAsync), pMailboxHandle, pForUpdate);

            if (mDisposed)
            {
                throw new ObjectDisposedException(nameof(cIMAPClient));
            }

            var lSession = mSession;

            if (lSession == null || !lSession.IsConnected)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
            }

            if (pMailboxHandle == null)
            {
                throw new ArgumentNullException(nameof(pMailboxHandle));
            }

            using (var lToken = mCancellationManager.GetToken(lContext))
            {
                var lMC = new cMethodControl(mTimeout, lToken.CancellationToken);
                if (pForUpdate)
                {
                    await lSession.SelectAsync(lMC, pMailboxHandle, lContext).ConfigureAwait(false);
                }
                else
                {
                    await lSession.ExamineAsync(lMC, pMailboxHandle, lContext).ConfigureAwait(false);
                }
            }
        }
Esempio n. 6
0
            public async Task FetchCacheItemsAsync(cMethodControl pMC, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cProgress pProgress, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(FetchCacheItemsAsync), pMC, pMessageHandles, pItems);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }

                if (pMessageHandles == null)
                {
                    throw new ArgumentNullException(nameof(pMessageHandles));
                }
                if (pItems == null)
                {
                    throw new ArgumentNullException(nameof(pItems));
                }
                if (pProgress == null)
                {
                    throw new ArgumentNullException(nameof(pProgress));
                }

                mMailboxCache.CheckInSelectedMailbox(pMessageHandles); // to be repeated inside the select lock

                // split the handles into groups based on what attributes need to be retrieved, for each group do the retrieval
                foreach (var lGroup in ZFetchCacheItemsGroups(pMessageHandles, pItems))
                {
                    await ZFetchCacheItemsAsync(pMC, lGroup, pProgress, lContext).ConfigureAwait(false);
                }
            }
Esempio n. 7
0
        private async Task <cMailbox> ZCreateAsync(cMailboxName pMailboxName, bool pAsFutureParent, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZCreateAsync), pMailboxName, pAsFutureParent);

            if (mDisposed)
            {
                throw new ObjectDisposedException(nameof(cIMAPClient));
            }

            var lSession = mSession;

            if (lSession == null || !lSession.IsConnected)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
            }

            if (pMailboxName == null)
            {
                throw new ArgumentNullException(nameof(pMailboxName));
            }

            using (var lToken = mCancellationManager.GetToken(lContext))
            {
                var lMC            = new cMethodControl(mTimeout, lToken.CancellationToken);
                var lMailboxHandle = await lSession.CreateAsync(lMC, pMailboxName, pAsFutureParent, lContext).ConfigureAwait(false);

                return(new cMailbox(this, lMailboxHandle));
            }
        }
Esempio n. 8
0
            private async Task ZUIDStoreAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, uint pUIDValidity, cStoreFeedbackCollector pFeedbackCollector, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cUIDStoreFeedback pFeedback, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZStoreAsync), pMC, pMailboxHandle, pUIDValidity, pFeedbackCollector, pOperation, pFlags, pIfUnchangedSinceModSeq, pFeedback);

                // no validation ... all the parameters have been validated already by the cSession by the time we get here

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUIDValidity);
                    if (!lSelectedMailbox.SelectedForUpdate)
                    {
                        throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);
                    }

                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // this command is msnunsafe

                    lBuilder.AddUIDValidity(pUIDValidity);                                                  // the command is sensitive to UIDValidity changes

                    // build the command
                    lBuilder.Add(kUIDStoreCommandPartUIDStoreSpace, new cTextCommandPart(cSequenceSet.FromUInts(pFeedbackCollector.UInts)), cCommandPart.Space);
                    if (pIfUnchangedSinceModSeq != null)
                    {
                        lBuilder.Add(kStoreCommandPartLParenUnchangedSinceSpace, new cTextCommandPart(pIfUnchangedSinceModSeq.Value), kStoreCommandPartRParenSpace);
                    }
                    lBuilder.Add(pOperation, pFlags);

                    // add the hook
                    var lHook = new cCommandHookStore(pFeedbackCollector, pFeedback, lSelectedMailbox);
                    lBuilder.Add(lHook);

                    // submit the command
                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    // note: the base spec states that non-existent UIDs are ignored without comment => a NO from a UID STORE is unexpected

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid store success");
                        return;
                    }

                    fCapabilities lTryIgnoring;
                    if (pIfUnchangedSinceModSeq == null)
                    {
                        lTryIgnoring = 0;
                    }
                    else
                    {
                        lTryIgnoring = fCapabilities.condstore;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Esempio n. 9
0
        private async Task ZDisconnectAsync(cTrace.cContext pParentContext)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(ZDisconnectAsync));

            if (mDisposed)
            {
                throw new ObjectDisposedException(nameof(cIMAPClient));
            }

            var lSession = mSession;

            if (lSession == null || !lSession.IsConnected)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
            }

            using (var lToken = mCancellationManager.GetToken(lContext))
            {
                var lMC = new cMethodControl(mTimeout, lToken.CancellationToken);

                try { await lSession.LogoutAsync(lMC, lContext).ConfigureAwait(false); }
                catch when(lSession.ConnectionState != eConnectionState.disconnected)
                {
                    lSession.Disconnect(lContext);
                    throw;
                }
            }
        }
Esempio n. 10
0
                public async sealed override Task WriteAsync(cMethodControl pMC, cBytes pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext)
                {
                    while (pOffset < pBytes.Count)
                    {
                        byte lByte = pBytes[pOffset++];

                        if (mBufferedCR)
                        {
                            mBufferedCR = false;

                            if (lByte == cASCII.LF)
                            {
                                await YWriteLineAsync(pMC, mLine, pWriteSizer, pContext).ConfigureAwait(false);

                                mLine.Clear();
                                continue;
                            }

                            mLine.Add(cASCII.CR);
                        }

                        if (lByte == cASCII.CR)
                        {
                            mBufferedCR = true;
                        }
                        else
                        {
                            mLine.Add(lByte);
                        }
                    }
                }
Esempio n. 11
0
                public static void _Tests(cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cQuotedPrintableDecoder), nameof(_Tests));

                    if (LTest("testNow's the time =    \r\n", "for all folk to come=\t \t \r\n", " to the aid of their country.   \t\r\n") != "Now's the time for all folk to come to the aid of their country.\r\n")
                    {
                        throw new cTestsException($"{nameof(cQuotedPrintableDecoder)}.1");
                    }



                    string LTest(params string[] pLines)
                    {
                        var lMC         = new cMethodControl(-1, System.Threading.CancellationToken.None);
                        var lWriteSizer = new cBatchSizer(new cBatchSizerConfiguration(1, 10, 1000, 1));

                        using (var lStream = new MemoryStream())
                        {
                            cDecoder lDecoder = new cQuotedPrintableDecoder(lStream);

                            int lOffset = 4;

                            foreach (var lLine in pLines)
                            {
                                lDecoder.WriteAsync(lMC, new cBytes(lLine), lOffset, lWriteSizer, lContext).Wait();
                                lOffset = 0;
                            }

                            lDecoder.FlushAsync(lMC, lWriteSizer, lContext).Wait();

                            return(new string(System.Text.Encoding.UTF8.GetChars(lStream.GetBuffer(), 0, (int)lStream.Length)));
                        }
                    }
                }
Esempio n. 12
0
                protected async Task YWriteAsync(cMethodControl pMC, IList <byte> pBytes, int pOffset, cBatchSizer pWriteSizer, cTrace.cContext pContext)
                {
                    if (mStream.CanTimeout)
                    {
                        mStream.WriteTimeout = pMC.Timeout;
                    }

                    while (pOffset < pBytes.Count)
                    {
                        if (mCount == 0)
                        {
                            mBuffer = new byte[pWriteSizer.Current];
                        }

                        while (mCount < mBuffer.Length && pOffset < pBytes.Count)
                        {
                            mBuffer[mCount++] = pBytes[pOffset++];
                        }
                        if (mCount < mBuffer.Length)
                        {
                            return;
                        }

                        await YFlushAsync(pMC, pWriteSizer, pContext).ConfigureAwait(false);
                    }
                }
Esempio n. 13
0
                protected async override Task YWriteLineAsync(cMethodControl pMC, List <byte> pLine, cBatchSizer pWriteSizer, cTrace.cContext pContext)
                {
                    // build the buffer to decode
                    mBytes.Clear();
                    foreach (var lByte in pLine)
                    {
                        if (cBase64.IsInAlphabet(lByte))
                        {
                            mBytes.Add(lByte);
                        }
                    }

                    // special case
                    if (mBytes.Count == 0)
                    {
                        return;
                    }

                    // decode
                    if (!cBase64.TryDecode(mBytes, out var lBytes, out var lError))
                    {
                        throw new cContentTransferDecodingException(lError, pContext);
                    }

                    await YWriteAsync(pMC, lBytes, 0, pWriteSizer, pContext).ConfigureAwait(false);
                }
Esempio n. 14
0
            public async Task <Exception> LoginAsync(cMethodControl pMC, cAccountId pAccountId, cLogin pLogin, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LoginAsync), pMC, pAccountId);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notauthenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnauthenticated);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this is only called during connect

                    lBuilder.Add(kLoginCommandPartLogin, cCommandPartFactory.AsASCIILiteral(pLogin.UserId), cCommandPart.Space, cCommandPartFactory.AsASCIILiteral(pLogin.Password));

                    var lHook = new cCommandHookInitial();
                    lBuilder.Add(lHook);

                    var lCapabilities = mPipeline.Capabilities;

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("login success");
                        ZAuthenticated(lCapabilities, lHook, lResult.ResponseText, pAccountId, lContext);
                        return(null);
                    }

                    if (lHook.Capabilities != null)
                    {
                        lContext.TraceError("received capability on a failed login");
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        lContext.TraceInformation("login failed: {0}", lResult.ResponseText);

                        if (ZSetHomeServerReferral(lResult.ResponseText, lContext))
                        {
                            return(new cHomeServerReferralException(lResult.ResponseText, lContext));
                        }

                        if (lResult.ResponseText.Code == eResponseTextCode.authenticationfailed || lResult.ResponseText.Code == eResponseTextCode.authorizationfailed || lResult.ResponseText.Code == eResponseTextCode.expired)
                        {
                            return(new cCredentialsException(lResult.ResponseText, lContext));
                        }

                        return(null);
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 15
0
            public async Task IdAsync(cMethodControl pMC, cId pClientId, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(IdAsync), pMC, pClientId);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState < eConnectionState.notauthenticated || _ConnectionState > eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                // install the permanent response data processor
                if (mIdResponseDataProcessor == null)
                {
                    mIdResponseDataProcessor = new cIdDataProcessor(mSynchroniser);
                    mPipeline.Install(mIdResponseDataProcessor);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kIdCommandPart);

                    if (pClientId == null || pClientId.Count == 0)
                    {
                        lBuilder.Add(cCommandPart.Nil);
                    }
                    else
                    {
                        lBuilder.BeginList(eListBracketing.bracketed);

                        foreach (var lPair in pClientId)
                        {
                            lBuilder.Add(mCommandPartFactory.AsString(lPair.Key));
                            lBuilder.Add(mCommandPartFactory.AsNString(lPair.Value));
                        }

                        lBuilder.EndList();
                    }

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("id success");
                        return;
                    }

                    throw new cProtocolErrorException(lResult, fCapabilities.id, lContext);
                }
            }
Esempio n. 16
0
 public async sealed override Task FlushAsync(cMethodControl pMC, cBatchSizer pWriteSizer, cTrace.cContext pContext)
 {
     if (mBufferedCR)
     {
         mLine.Add(cASCII.CR);
     }
     await YWriteLineAsync(pMC, mLine, pWriteSizer, pContext).ConfigureAwait(false);
     await YFlushAsync(pMC, pWriteSizer, pContext).ConfigureAwait(false);
 }
Esempio n. 17
0
        private async Task ZUIDFetchBodyAsync(iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cBodyFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDFetchBodyAsync), pMailboxHandle, pUID, pSection, pDecoding);

            if (mDisposed)
            {
                throw new ObjectDisposedException(nameof(cIMAPClient));
            }

            var lSession = mSession;

            if (lSession == null || lSession.ConnectionState != eConnectionState.selected)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
            }

            if (pMailboxHandle == null)
            {
                throw new ArgumentNullException(nameof(pMailboxHandle));
            }
            if (pUID == null)
            {
                throw new ArgumentNullException(nameof(pUID));
            }
            if (pSection == null)
            {
                throw new ArgumentNullException(nameof(pSection));
            }
            if (pStream == null)
            {
                throw new ArgumentNullException(nameof(pStream));
            }

            if (!pStream.CanWrite)
            {
                throw new ArgumentOutOfRangeException(nameof(pStream));
            }

            if (pConfiguration == null)
            {
                using (var lToken = mCancellationManager.GetToken(lContext))
                {
                    var lMC         = new cMethodControl(mTimeout, lToken.CancellationToken);
                    var lProgress   = new cProgress();
                    var lWriteSizer = new cBatchSizer(mFetchBodyWriteConfiguration);
                    await lSession.UIDFetchBodyAsync(lMC, pMailboxHandle, pUID, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false);
                }
            }
            else
            {
                var lMC         = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken);
                var lProgress   = new cProgress(mSynchroniser, pConfiguration.Increment);
                var lWriteSizer = new cBatchSizer(pConfiguration.Write ?? mFetchBodyWriteConfiguration);
                await lSession.UIDFetchBodyAsync(lMC, pMailboxHandle, pUID, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false);
            }
        }
Esempio n. 18
0
            public async Task <cMessageHandleList> SetUnseenCountAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(SetUnseenCountAsync), pMC, pMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select

                    var lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, null);

                    lBuilder.Add(await mSearchExclusiveAccess.GetTokenAsync(pMC, lContext).ConfigureAwait(false)); // search commands must be single threaded (so we can tell which result is which)

                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);                            // if a UIDValidity change happens while the command is running, disbelieve the results

                    lBuilder.Add(kSetUnseenCountCommandPart);

                    var lHook = new cSetUnseenCountCommandHook(lSelectedMailbox);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("setunseencount success");
                        if (lHook.MessageHandles == null)
                        {
                            throw new cUnexpectedServerActionException(0, "results not received on a successful setunseencount", lContext);
                        }
                        return(lHook.MessageHandles);
                    }

                    if (lHook.MessageHandles != null)
                    {
                        lContext.TraceError("results received on a failed setunseencount");
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 19
0
            public async Task <List <iMailboxHandle> > LSubAsync(cMethodControl pMC, string pListMailbox, char?pDelimiter, cMailboxPathPattern pPattern, bool pHasSubscribedChildren, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LSubAsync), pMC, pListMailbox, pDelimiter, pPattern, pHasSubscribedChildren);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pListMailbox == null)
                {
                    throw new ArgumentNullException(nameof(pListMailbox));
                }
                if (pPattern == null)
                {
                    throw new ArgumentNullException(nameof(pPattern));
                }

                if (!mCommandPartFactory.TryAsListMailbox(pListMailbox, pDelimiter, out var lListMailboxCommandPart))
                {
                    throw new ArgumentOutOfRangeException(nameof(pListMailbox));
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kLSubCommandPart, lListMailboxCommandPart);

                    var lHook = new cCommandHookLSub(mMailboxCache, pPattern, pHasSubscribedChildren);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("lsub success");
                        return(lHook.MailboxHandles);
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 20
0
            public async Task UIDStoreAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUIDStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDStoreAsync), pMC, pMailboxHandle, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }

                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }
                if (pFeedback == null)
                {
                    throw new ArgumentNullException(nameof(pFeedback));
                }
                if (pFlags == null)
                {
                    throw new ArgumentNullException(nameof(pFlags));
                }

                if (pFeedback.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pFeedback));
                }

                if (pIfUnchangedSinceModSeq == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pIfUnchangedSinceModSeq));
                }
                if (pIfUnchangedSinceModSeq != null && !_Capabilities.CondStore)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.CondStoreNotInUse);
                }

                uint lUIDValidity = pFeedback[0].UID.UIDValidity;

                cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity); // to be repeated inside the select lock

                if (!lSelectedMailbox.SelectedForUpdate)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);                                      // to be repeated inside the select lock
                }
                cStoreFeedbackCollector lFeedbackCollector = new cStoreFeedbackCollector(pFeedback);

                await ZUIDStoreAsync(pMC, pMailboxHandle, lUIDValidity, lFeedbackCollector, pOperation, pFlags, pIfUnchangedSinceModSeq, pFeedback, lContext).ConfigureAwait(false);
            }
Esempio n. 21
0
                public async Task <cExclusiveAccess.cToken> GetIdleBlockTokenAsync(cMethodControl pMC, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cCommandPipeline), nameof(GetIdleBlockTokenAsync));

                    if (mDisposed)
                    {
                        throw new ObjectDisposedException(nameof(cCommandPipeline));
                    }
                    var lTask = mIdleBlock.GetTokenAsync(pMC, lContext);

                    mBackgroundReleaser.Release(lContext);
                    return(await lTask.ConfigureAwait(false));
                }
Esempio n. 22
0
        private Task ZRequestStatus(cMethodControl pMC, cSession pSession, List <iMailboxHandle> pMailboxHandles, cTrace.cContext pParentContext)
        {
            var         lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZRequestStatus), pMC);
            List <Task> lTasks   = new List <Task>();

            foreach (var lMailboxHandle in pMailboxHandles)
            {
                if (lMailboxHandle.ListFlags?.CanSelect == true)
                {
                    lTasks.Add(pSession.StatusAsync(pMC, lMailboxHandle, lContext));
                }
            }
            return(Task.WhenAll(lTasks));
        }
Esempio n. 23
0
            public async Task ConnectAsync(cMethodControl pMC, cServer pServer, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ConnectAsync), pMC, pServer);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }

                if (_ConnectionState != eConnectionState.notconnected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnconnected);
                }
                ZSetState(eConnectionState.connecting, lContext);

                sGreeting lGreeting;

                try { lGreeting = await mPipeline.ConnectAsync(pMC, pServer, lContext).ConfigureAwait(false); }
                catch (Exception)
                {
                    ZSetState(eConnectionState.disconnected, lContext);
                    throw;
                }

                if (lGreeting.Type == eGreetingType.bye)
                {
                    ZSetState(eConnectionState.disconnected, lContext);
                    if (ZSetHomeServerReferral(lGreeting.ResponseText, lContext))
                    {
                        throw new cHomeServerReferralException(lGreeting.ResponseText, lContext);
                    }
                    throw new cConnectByeException(lGreeting.ResponseText, lContext);
                }

                if (mPipeline.Capabilities != null)
                {
                    ZSetCapabilities(mPipeline.Capabilities, mPipeline.AuthenticationMechanisms, lContext);
                }

                if (lGreeting.Type == eGreetingType.ok)
                {
                    ZSetState(eConnectionState.notauthenticated, lContext);
                    return;
                }

                // preauth

                ZSetHomeServerReferral(lGreeting.ResponseText, lContext);
                ZSetConnectedAccountId(new cAccountId(pServer.Host, eAccountType.unknown), lContext);
            }
Esempio n. 24
0
        private async Task ZUIDStoreAsync(iMailboxHandle pMailboxHandle, cUIDStoreFeedback pFeedback, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDStoreAsync), pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq);

            if (mDisposed)
            {
                throw new ObjectDisposedException(nameof(cIMAPClient));
            }

            var lSession = mSession;

            if (lSession == null || lSession.SelectedMailboxDetails?.SelectedForUpdate != true)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelectedForUpdate);
            }

            if (pMailboxHandle == null)
            {
                throw new ArgumentNullException(nameof(pMailboxHandle));
            }
            if (pFeedback == null)
            {
                throw new ArgumentNullException(nameof(pFeedback));
            }
            if (pFlags == null)
            {
                throw new ArgumentNullException(nameof(pFlags));
            }

            if (pIfUnchangedSinceModSeq == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(pIfUnchangedSinceModSeq));
            }
            if (pIfUnchangedSinceModSeq != null && !lSession.Capabilities.CondStore)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.CondStoreNotInUse);
            }

            if (pFeedback.Count == 0)
            {
                return;
            }
            // it is valid to add or remove zero flags according to the ABNF (!)

            using (var lToken = mCancellationManager.GetToken(lContext))
            {
                var lMC = new cMethodControl(mTimeout, lToken.CancellationToken);
                await lSession.UIDStoreAsync(lMC, pMailboxHandle, pFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext).ConfigureAwait(false);
            }
        }
Esempio n. 25
0
        private async Task ZFetchCacheItemsAsync(cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZFetchCacheItemsAsync), pMessageHandles, pItems);

            if (mDisposed)
            {
                throw new ObjectDisposedException(nameof(cIMAPClient));
            }

            var lSession = mSession;

            if (lSession == null || lSession.ConnectionState != eConnectionState.selected)
            {
                throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
            }

            if (pMessageHandles == null)
            {
                throw new ArgumentNullException(nameof(pMessageHandles));
            }
            if (pItems == null)
            {
                throw new ArgumentNullException(nameof(pItems));
            }

            if (pMessageHandles.Count == 0)
            {
                return;
            }
            if (pItems.IsEmpty)
            {
                return;
            }

            if (pConfiguration == null)
            {
                using (var lToken = mCancellationManager.GetToken(lContext))
                {
                    var lMC       = new cMethodControl(mTimeout, lToken.CancellationToken);
                    var lProgress = new cProgress();
                    await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false);
                }
            }
            else
            {
                var lMC       = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken);
                var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment);
                await lSession.FetchCacheItemsAsync(lMC, pMessageHandles, pItems, lProgress, lContext).ConfigureAwait(false);
            }
        }
Esempio n. 26
0
            public async Task EnableAsync(cMethodControl pMC, fEnableableExtensions pExtensions, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(EnableAsync), pMC, pExtensions);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.authenticated)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotAuthenticated);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    //  note the lack of locking - this can only called during connect

                    lBuilder.BeginList(eListBracketing.none);
                    lBuilder.Add(kEnableCommandPartEnable);
                    if ((pExtensions & fEnableableExtensions.utf8) != 0)
                    {
                        lBuilder.Add(kEnableCommandPartUTF8);
                    }
                    // more here as required
                    lBuilder.EndList();

                    var lHook = new cEnableCommandHook();
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        var lEnabledExtensions = lHook.EnabledExtensions;
                        lContext.TraceInformation("enabled extensions {0}", lEnabledExtensions);
                        EnabledExtensions = EnabledExtensions | lEnabledExtensions;
                        lContext.TraceVerbose("current enabled extensions {0}", EnabledExtensions);
                        mSynchroniser.InvokePropertyChanged(nameof(cIMAPClient.EnabledExtensions), lContext);
                        return;
                    }

                    if (lHook.EnabledExtensions != fEnableableExtensions.none)
                    {
                        lContext.TraceError("received enabled on a failed enable");
                    }

                    throw new cProtocolErrorException(lResult, fCapabilities.enable, lContext);
                }
            }
Esempio n. 27
0
            public async Task LogoutAsync(cMethodControl pMC, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LogoutAsync), pMC);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState < eConnectionState.notauthenticated || _ConnectionState > eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kLogoutCommandPart);

                    var lHook = new cLogoutCommandHook(mPipeline);
                    lBuilder.Add(lHook);

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("logout success");
                        if (!lHook.GotBye)
                        {
                            throw new cUnexpectedServerActionException(0, "bye not received", lContext);
                        }
                        Disconnect(lContext);
                        return;
                    }

                    if (lHook.GotBye)
                    {
                        lContext.TraceError("received bye on a failed logout");
                    }

                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 28
0
            public async Task DeleteAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(DeleteAsync), pMC, pMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.notselected && _ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotConnected);
                }
                if (pMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pMailboxHandle));
                }

                var lItem = mMailboxCache.CheckHandle(pMailboxHandle);

                using (var lBuilder = new cCommandDetailsBuilder())
                {
                    if (!_Capabilities.QResync)
                    {
                        lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select if mailbox-data delivered during the command would be ambiguous
                    }
                    lBuilder.Add(await mMSNUnsafeBlock.GetBlockAsync(pMC, lContext).ConfigureAwait(false));            // this command is msnunsafe

                    lBuilder.Add(kDeleteCommandPart, lItem.MailboxNameCommandPart);

                    lBuilder.Add(new cDeleteCommandHook(lItem));

                    var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false);

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("delete success");
                        return;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Esempio n. 29
0
            public Task UIDFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchBodyAsync), pMC, pMailboxHandle, pUID, pSection, pDecoding);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }

                mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity); // to be repeated inside the select lock

                return(ZFetchBodyAsync(pMC, pMailboxHandle, pUID, null, pSection, pDecoding, pStream, pProgress, pWriteSizer, lContext));
            }
Esempio n. 30
0
            public Task <cCopyFeedback> CopyAsync(cMethodControl pMC, cMessageHandleList pSourceMessageHandles, iMailboxHandle pDestinationMailboxHandle, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(CopyAsync), pMC, pSourceMessageHandles, pDestinationMailboxHandle);

                if (mDisposed)
                {
                    throw new ObjectDisposedException(nameof(cSession));
                }
                if (_ConnectionState != eConnectionState.selected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected);
                }

                if (pSourceMessageHandles == null)
                {
                    throw new ArgumentNullException(nameof(pSourceMessageHandles));
                }
                if (pDestinationMailboxHandle == null)
                {
                    throw new ArgumentNullException(nameof(pDestinationMailboxHandle));
                }

                if (pSourceMessageHandles.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pSourceMessageHandles));
                }

                cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pSourceMessageHandles); // to be repeated inside the select lock

                var lDestinationItem = mMailboxCache.CheckHandle(pDestinationMailboxHandle);

                if (pSourceMessageHandles.TrueForAll(h => h.UID != null))
                {
                    var lMessageHandle = pSourceMessageHandles.Find(h => h.Expunged);
                    if (lMessageHandle != null)
                    {
                        throw new cMessageExpungedException(lMessageHandle);
                    }
                    return(ZUIDCopyAsync(pMC, lSelectedMailbox.MailboxHandle, pSourceMessageHandles[0].UID.UIDValidity, new cUIntList(from h in pSourceMessageHandles select h.UID.UID), lDestinationItem, lContext));
                }
                else
                {
                    return(ZCopyAsync(pMC, pSourceMessageHandles, lDestinationItem, lContext));
                }
            }