예제 #1
0
        /// <summary>
        /// Ensures that the specified items are cached for the specified messages.
        /// </summary>
        /// <param name="pMessages"></param>
        /// <param name="pItems"></param>
        /// <param name="pConfiguration">Operation specific timeout, cancellation token and progress callbacks.</param>
        /// <returns>A list of messages where something went wrong and the cache was not populated.</returns>
        /// <remarks>
        /// <note type="note"><see cref="cMessageCacheItems"/> has implicit conversions from other types including <see cref="fMessageProperties"/>. This means that you can use values of those types as arguments to this method.</note>
        /// </remarks>
        public List <cMessage> Fetch(IEnumerable <cMessage> pMessages, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration)
        {
            var lContext = mRootContext.NewMethodV(true, nameof(cIMAPClient), nameof(Fetch), 3);

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

            var lMessageHandles = cMessageHandleList.FromMessages(pMessages);

            if (lMessageHandles.All(h => h.Contains(pItems)))
            {
                return(new List <cMessage>());
            }

            var lTask = ZFetchCacheItemsAsync(lMessageHandles, pItems, pConfiguration, lContext);

            mSynchroniser.Wait(lTask, lContext);

            return(new List <cMessage>(from m in pMessages where !m.MessageHandle.Contains(pItems) select m));
        }
예제 #2
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);
            }
        }
예제 #3
0
        internal cMessage Message(iMailboxHandle pMailboxHandle, cUID pUID, cMessageCacheItems pItems)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(Message));
            var lTask    = ZUIDFetchCacheItemsAsync(pMailboxHandle, cUIDList.FromUID(pUID), pItems, null, lContext);

            mSynchroniser.Wait(lTask, lContext);
            var lResult = lTask.Result;

            if (lResult.Count == 0)
            {
                return(null);
            }
            if (lResult.Count == 1)
            {
                return(lResult[0]);
            }
            throw new cInternalErrorException(lContext);
        }
예제 #4
0
        /// <summary>
        /// Compares two messages using the comparision implied by the value of this instance.
        /// </summary>
        /// <param name="pX"></param>
        /// <param name="pY"></param>
        /// <returns></returns>
        /// <remarks>
        /// If the attributes required for the comparision are not in the message cache they will be fetched from the server.
        /// </remarks>
        public int Compare(cMessage pX, cMessage pY)
        {
            if (pX == null)
            {
                if (pY == null)
                {
                    return(0);
                }
                return(-1);
            }

            if (pY == null)
            {
                return(1);
            }

            cMessageCacheItems lItems = Attributes(out _);

            pX.Fetch(lItems);
            pY.Fetch(lItems);
            return(Compare(pX.MessageHandle, pY.MessageHandle));
        }
예제 #5
0
        internal async Task <bool> FetchAsync(iMessageHandle pMessageHandle, cMessageCacheItems pItems)
        {
            var lContext = mRootContext.NewMethodV(true, nameof(cIMAPClient), nameof(FetchAsync), 1);

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

            if (pMessageHandle.Contains(pItems))
            {
                return(true);
            }

            await ZFetchCacheItemsAsync(cMessageHandleList.FromMessageHandle(pMessageHandle), pItems, null, lContext).ConfigureAwait(false);

            return(pMessageHandle.Contains(pItems));
        }
예제 #6
0
        internal bool Fetch(iMessageHandle pMessageHandle, cMessageCacheItems pItems)
        {
            var lContext = mRootContext.NewMethodV(true, nameof(cIMAPClient), nameof(Fetch), 1);

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

            if (pMessageHandle.Contains(pItems))
            {
                return(true);
            }

            var lTask = ZFetchCacheItemsAsync(cMessageHandleList.FromMessageHandle(pMessageHandle), pItems, null, lContext);

            mSynchroniser.Wait(lTask, lContext);

            return(pMessageHandle.Contains(pItems));
        }
예제 #7
0
            private async Task ZUIDFetchCacheItemsAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, uint pUIDValidity, cUIntList pUIDs, cMessageCacheItems pItems, cTrace.cContext pParentContext)
            {
                // note that this will fail if the UIDValidity has changed (this is different to the behaviour of standard fetch)
                // note that the caller should have checked that pAttributes contains some attributes to fetch

                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZUIDFetchCacheItemsAsync), pMC, pMailboxHandle, pUIDValidity, pUIDs, pItems);

                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 (pUIDs == null)
                {
                    throw new ArgumentNullException(nameof(pUIDs));
                }
                if (pItems == null)
                {
                    throw new ArgumentNullException(nameof(pItems));
                }

                if (pUIDs.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pUIDs));
                }
                if (pItems.IsEmpty)
                {
                    throw new ArgumentOutOfRangeException(nameof(pItems));
                }

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

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUIDValidity);

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

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

                    lBuilder.Add(kFetchCommandPartUIDFetchSpace, new cTextCommandPart(cSequenceSet.FromUInts(pUIDs)), cCommandPart.Space);
                    lBuilder.Add(pItems, lSelectedMailbox.MessageCache.NoModSeq);

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

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

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
예제 #8
0
 public cFetchCacheItemsGroup(cMessageCacheItems pItems)
 {
     Items = pItems ?? throw new ArgumentNullException(nameof(pItems));
 }
예제 #9
0
            private IEnumerable <cFetchCacheItemsGroup> ZFetchCacheItemsGroups(cMessageHandleList pMessageHandles, cMessageCacheItems pItems)
            {
                Dictionary <cMessageCacheItems, cFetchCacheItemsGroup> lGroups = new Dictionary <cMessageCacheItems, cFetchCacheItemsGroup>();

                foreach (var lMessageHandle in pMessageHandles)
                {
                    cMessageCacheItems lItems;

                    if (lMessageHandle.Expunged)
                    {
                        lItems = cMessageCacheItems.Empty;                          // none to get
                    }
                    else
                    {
                        lItems = lMessageHandle.Missing(pItems);  // might also be none to get
                    }
                    cFetchCacheItemsGroup lGroup;

                    if (!lGroups.TryGetValue(lItems, out lGroup))
                    {
                        lGroup = new cFetchCacheItemsGroup(lItems);
                        lGroups.Add(lItems, lGroup);
                    }

                    if (lMessageHandle.UID == null)
                    {
                        lGroup.MSNHandleCount++;
                    }

                    lGroup.MessageHandles.Add(lMessageHandle);
                }

                return(lGroups.Values);
            }
예제 #10
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);
                }
            }
예제 #11
0
        internal Task <List <cMessage> > MessagesAsync(iMailboxHandle pMailboxHandle, IEnumerable <cUID> pUIDs, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(MessagesAsync));

            return(ZUIDFetchCacheItemsAsync(pMailboxHandle, cUIDList.FromUIDs(pUIDs), pItems, pConfiguration, lContext));
        }
예제 #12
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);
        }
예제 #13
0
        internal async Task <cMessage> MessageAsync(iMailboxHandle pMailboxHandle, cUID pUID, cMessageCacheItems pItems)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(MessageAsync));
            var lResult  = await ZUIDFetchCacheItemsAsync(pMailboxHandle, cUIDList.FromUID(pUID), pItems, null, lContext).ConfigureAwait(false);

            if (lResult.Count == 0)
            {
                return(null);
            }
            if (lResult.Count == 1)
            {
                return(lResult[0]);
            }
            throw new cInternalErrorException(lContext);
        }
예제 #14
0
            public async Task <cMessageHandleList> UIDFetchCacheItemsAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUIDList pUIDs, cMessageCacheItems pItems, cProgress pProgress, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchCacheItemsAsync), pMC, pMailboxHandle, pUIDs, pItems);

                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 (pUIDs == null)
                {
                    throw new ArgumentNullException(nameof(pUIDs));
                }
                if (pItems == null)
                {
                    throw new ArgumentNullException(nameof(pItems));
                }
                if (pProgress == null)
                {
                    throw new ArgumentNullException(nameof(pProgress));
                }

                if (pUIDs.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pUIDs));
                }
                if (pItems.IsEmpty)
                {
                    throw new ArgumentOutOfRangeException(nameof(pItems));
                }

                uint lUIDValidity = pUIDs[0].UIDValidity;

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

                // split the list into those messages I have handles for and those I dont
                /////////////////////////////////////////////////////////////////////////

                cMessageHandleList lMessageHandles = new cMessageHandleList();
                cUIDList           lUIDs           = new cUIDList();

                // check the selected mailbox and resolve uids -> handles whilst blocking select exclusive access
                //
                using (var lBlock = await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false))
                {
                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity);

                    foreach (var lUID in pUIDs)
                    {
                        var lMessageHandle = lSelectedMailbox.GetHandle(lUID);
                        if (lMessageHandle == null)
                        {
                            lUIDs.Add(lUID);                         // don't have a handle
                        }
                        else if (lMessageHandle.ContainsNone(pItems))
                        {
                            lUIDs.Add(lUID);                                           // have to get all the attributes, may as well fetch them with the ones where I might need all the attributes
                        }
                        else
                        {
                            lMessageHandles.Add(lMessageHandle);
                        }
                    }
                }

                // for the messages I have handles for, fetch the missing attributes
                ////////////////////////////////////////////////////////////////////

                if (lMessageHandles.Count > 0)
                {
                    // split the handles into groups based on what attributes need to be retrieved, for each group do the retrieval
                    foreach (var lGroup in ZFetchCacheItemsGroups(lMessageHandles, pItems))
                    {
                        await ZFetchCacheItemsAsync(pMC, lGroup, pProgress, lContext).ConfigureAwait(false);
                    }
                }

                // for the messages only identified by UID or where I have to get all the items
                ////////////////////////////////////////////////////////////////////////////////////

                if (lUIDs.Count > 0)
                {
                    await ZUIDFetchCacheItemsAsync(pMC, pMailboxHandle, lUIDs, pItems, pProgress, lContext).ConfigureAwait(false);

                    // resolve uids -> handles whilst blocking select exclusive access
                    //
                    using (var lBlock = await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false))
                    {
                        cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, lUIDValidity);

                        foreach (var lUID in lUIDs)
                        {
                            var lMessageHandle = lSelectedMailbox.GetHandle(lUID);
                            if (lMessageHandle != null)
                            {
                                lMessageHandles.Add(lMessageHandle);
                            }
                        }
                    }
                }

                return(lMessageHandles);
            }
예제 #15
0
            private async Task ZUIDFetchCacheItemsAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUIDList pUIDs, cMessageCacheItems pItems, cProgress pProgress, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZUIDFetchCacheItemsAsync), pMC, pMailboxHandle, pUIDs, pItems);

                // get the UIDValidity
                uint lUIDValidity = pUIDs[0].UIDValidity;

                // sort the uids so we might get good sequence sets
                pUIDs.Sort();

                int       lIndex     = 0;
                Stopwatch lStopwatch = new Stopwatch();

                while (lIndex < pUIDs.Count)
                {
                    // the number of messages to fetch this time
                    int lFetchCount = mFetchCacheItemsSizer.Current;

                    // get the UIDs to fetch this time
                    cUIntList lUIDs = new cUIntList();
                    while (lIndex < pUIDs.Count && lUIDs.Count < lFetchCount)
                    {
                        lUIDs.Add(pUIDs[lIndex++].UID);
                    }

                    // fetch
                    lStopwatch.Restart();
                    await ZUIDFetchCacheItemsAsync(pMC, pMailboxHandle, lUIDValidity, lUIDs, pItems, lContext).ConfigureAwait(false);

                    lStopwatch.Stop();

                    // store the time taken so the next fetch is a better size
                    mFetchCacheItemsSizer.AddSample(lUIDs.Count, lStopwatch.ElapsedMilliseconds);

                    // update progress
                    pProgress.Increment(lUIDs.Count, lContext);
                }
            }
예제 #16
0
        private async Task <List <cMessage> > ZZMessagesAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cFilter pFilter, cSort pSort, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZZMessagesAsync), pMC, pMailboxHandle, pFilter, pSort, pItems);

            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 (pFilter == null)
            {
                throw new ArgumentNullException(nameof(pFilter));
            }
            if (pSort == null)
            {
                throw new ArgumentNullException(nameof(pSort));
            }
            if (pItems == null)
            {
                throw new ArgumentNullException(nameof(pItems));
            }

            cMessageCacheItems lItems;

            if (ReferenceEquals(pSort, cSort.None))
            {
                lItems = pItems;
            }

            /* de-implemented pending a requirement to complete it
             * else if (ReferenceEquals(pSort, cSort.ThreadOrderedSubject))
             * {
             *  if (lSession.Capabilities.ThreadOrderedSubject) return await ZMessagesThreadAsync(pMC, lSession, pHandle, eMessageThreadAlgorithm.orderedsubject, pFilter, pItems, pConfiguration, lContext).ConfigureAwait(false);
             *  lItems = new cCacheItems(pItems.Attributes | fCacheAttributes.envelope | fCacheAttributes.received, pItems.Names);
             * }
             * else if (ReferenceEquals(pSort, cSort.ThreadReferences))
             * {
             *  if (lSession.Capabilities.ThreadReferences) return await ZMessagesThreadAsync(pMC, lSession, pHandle, eMessageThreadAlgorithm.references, pFilter, pItems, pConfiguration, lContext).ConfigureAwait(false);
             *  lItems = new cCacheItems(pItems.Attributes | fCacheAttributes.envelope | fCacheAttributes.received, pItems.Names.Union(cHeaderFieldNames.References));
             * } */
            else
            {
                var lSortAttributes = pSort.Attributes(out var lSortDisplay);
                if (!lSortDisplay && lSession.Capabilities.Sort || lSortDisplay && lSession.Capabilities.SortDisplay)
                {
                    return(await ZMessagesSortAsync(pMC, lSession, pMailboxHandle, pSort, pFilter, pItems, pConfiguration, lContext).ConfigureAwait(false));
                }
                lItems = new cMessageCacheItems(pItems.Attributes | lSortAttributes, pItems.Names);
            }

            cMessageHandleList lMessageHandles;

            if (lSession.Capabilities.ESearch)
            {
                lMessageHandles = await lSession.SearchExtendedAsync(pMC, pMailboxHandle, pFilter, lContext).ConfigureAwait(false);
            }
            else
            {
                lMessageHandles = await lSession.SearchAsync(pMC, pMailboxHandle, pFilter, lContext).ConfigureAwait(false);
            }

            // get the properties
            await ZMessagesFetchAsync(pMC, lSession, lMessageHandles, lItems, pConfiguration, lContext).ConfigureAwait(false);

            if (ReferenceEquals(pSort, cSort.None))
            {
                return(ZMessagesFlatMessageList(lMessageHandles, lContext));
            }

            // client side sorting

            // de-implemented pending a requirement to complete it
            // if (ReferenceEquals(pSort, cSort.ThreadOrderedSubject)) return ZMessagesThreadOrderedSubject(lHandles, lContext);
            // if (ReferenceEquals(pSort, cSort.ThreadReferences)) return ZMessagesThreadReferences(lHandles, lContext);

            lMessageHandles.Sort(pSort);
            return(ZMessagesFlatMessageList(lMessageHandles, lContext));
        }
예제 #17
0
        private async Task <List <cMessage> > ZMessagesAsync(iMailboxHandle pMailboxHandle, cFilter pFilter, cSort pSort, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMessagesAsync), pMailboxHandle, pFilter, pSort, pItems);

            if (pConfiguration == null)
            {
                using (var lToken = mCancellationManager.GetToken(lContext))
                {
                    var lMC = new cMethodControl(mTimeout, lToken.CancellationToken);
                    return(await ZZMessagesAsync(lMC, pMailboxHandle, pFilter, pSort, pItems, null, lContext).ConfigureAwait(false));
                }
            }
            else
            {
                var lMC = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken);
                return(await ZZMessagesAsync(lMC, pMailboxHandle, pFilter, pSort, pItems, pConfiguration, lContext).ConfigureAwait(false));
            }
        }
예제 #18
0
        internal Task <List <cMessage> > MessagesAsync(iMailboxHandle pMailboxHandle, cFilter pFilter, cSort pSort, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(MessagesAsync));

            return(ZMessagesAsync(pMailboxHandle, pFilter, pSort, pItems, pConfiguration, lContext));
        }
예제 #19
0
        internal List <cMessage> Messages(iMailboxHandle pMailboxHandle, cFilter pFilter, cSort pSort, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(Messages));
            var lTask    = ZMessagesAsync(pMailboxHandle, pFilter, pSort, pItems, pConfiguration, lContext);

            mSynchroniser.Wait(lTask, lContext);
            return(lTask.Result);
        }
예제 #20
0
        private async Task <List <cMessage> > ZMessagesSortAsync(cMethodControl pMC, cSession pSession, iMailboxHandle pMailboxHandle, cSort pSort, cFilter pFilter, cMessageCacheItems pItems, cMessageFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMessagesSortAsync), pMC, pMailboxHandle, pSort, pFilter, pItems);

            cMessageHandleList lMessageHandles;

            if (pSession.Capabilities.ESort)
            {
                lMessageHandles = await pSession.SortExtendedAsync(pMC, pMailboxHandle, pFilter, pSort, lContext).ConfigureAwait(false);
            }
            else
            {
                lMessageHandles = await pSession.SortAsync(pMC, pMailboxHandle, pFilter, pSort, lContext).ConfigureAwait(false);
            }

            await ZMessagesFetchAsync(pMC, pSession, lMessageHandles, pItems, pConfiguration, lContext).ConfigureAwait(false);

            return(ZMessagesFlatMessageList(lMessageHandles, lContext));
        }
예제 #21
0
        internal async Task <cMessageHandleList> FetchAsync(IEnumerable <iMessageHandle> pMessageHandles, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration)
        {
            var lContext = mRootContext.NewMethodV(true, nameof(cIMAPClient), nameof(FetchAsync), 2);

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

            var lMessageHandles = cMessageHandleList.FromMessageHandles(pMessageHandles);

            if (lMessageHandles.All(h => h.Contains(pItems)))
            {
                return(new cMessageHandleList());
            }

            await ZFetchCacheItemsAsync(lMessageHandles, pItems, pConfiguration, lContext).ConfigureAwait(false);

            return(new cMessageHandleList(from h in lMessageHandles where !h.Contains(pItems) select h));
        }
예제 #22
0
 public cMessageCacheItems Missing(cMessageCacheItems pItems) => new cMessageCacheItems(~mAttributes & pItems.Attributes, HeaderFields.Missing(pItems.Names));
예제 #23
0
        private async Task <List <cMessage> > ZUIDFetchCacheItemsAsync(iMailboxHandle pMailboxHandle, cUIDList pUIDs, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZUIDFetchCacheItemsAsync), pMailboxHandle, pUIDs, pItems);

            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 (pUIDs == null)
            {
                throw new ArgumentNullException(nameof(pUIDs));
            }
            if (pItems == null)
            {
                throw new ArgumentNullException(nameof(pItems));
            }

            if (pUIDs.Count == 0)
            {
                return(new List <cMessage>());
            }
            if (pItems.IsEmpty)
            {
                throw new ArgumentOutOfRangeException(nameof(pItems));
            }

            cMessageHandleList lMessageHandles;

            if (pConfiguration == null)
            {
                using (var lToken = mCancellationManager.GetToken(lContext))
                {
                    var lMC       = new cMethodControl(mTimeout, lToken.CancellationToken);
                    var lProgress = new cProgress();
                    lMessageHandles = await lSession.UIDFetchCacheItemsAsync(lMC, pMailboxHandle, pUIDs, pItems, lProgress, lContext).ConfigureAwait(false);
                }
            }
            else
            {
                var lMC       = new cMethodControl(pConfiguration.Timeout, pConfiguration.CancellationToken);
                var lProgress = new cProgress(mSynchroniser, pConfiguration.Increment);
                lMessageHandles = await lSession.UIDFetchCacheItemsAsync(lMC, pMailboxHandle, pUIDs, pItems, lProgress, lContext).ConfigureAwait(false);
            }

            List <cMessage> lMessages = new List <cMessage>(lMessageHandles.Count);

            foreach (var lMessageHandle in lMessageHandles)
            {
                lMessages.Add(new cMessage(this, lMessageHandle));
            }
            return(lMessages);
        }
예제 #24
0
        internal List <cMessage> Messages(iMailboxHandle pMailboxHandle, IEnumerable <cUID> pUIDs, cMessageCacheItems pItems, cCacheItemFetchConfiguration pConfiguration)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(Messages));
            var lTask    = ZUIDFetchCacheItemsAsync(pMailboxHandle, cUIDList.FromUIDs(pUIDs), pItems, pConfiguration, lContext);

            mSynchroniser.Wait(lTask, lContext);
            return(lTask.Result);
        }
예제 #25
0
            private async Task ZFetchCacheItemsAsync(cMethodControl pMC, cMessageHandleList pMessageHandles, cMessageCacheItems pItems, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchCacheItemsAsync), 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 (pMessageHandles.Count == 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(pMessageHandles));
                }
                if (pItems.IsEmpty)
                {
                    throw new ArgumentOutOfRangeException(nameof(pItems));
                }

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

                    cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pMessageHandles);

                    lBuilder.Add(await mPipeline.GetIdleBlockTokenAsync(pMC, lContext).ConfigureAwait(false)); // stop the pipeline from iding (idle is msnunsafe)
                    lBuilder.Add(await mMSNUnsafeBlock.GetTokenAsync(pMC, lContext).ConfigureAwait(false));    // wait until all commands that are msnunsafe complete, block all commands that are msnunsafe

                    // uidvalidity must be captured before the handles are resolved
                    lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity);

                    // resolve MSNs

                    cUIntList lMSNs = new cUIntList();

                    foreach (var lMessageHandle in pMessageHandles)
                    {
                        var lMSN = lSelectedMailbox.GetMSN(lMessageHandle);
                        if (lMSN != 0)
                        {
                            lMSNs.Add(lMSN);
                        }
                    }

                    if (lMSNs.Count == 0)
                    {
                        return;
                    }

                    // build command

                    lBuilder.Add(kFetchCommandPartFetchSpace, new cTextCommandPart(cSequenceSet.FromUInts(lMSNs)), cCommandPart.Space);
                    lBuilder.Add(pItems, lSelectedMailbox.MessageCache.NoModSeq);

                    // go

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

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

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
예제 #26
0
 public bool ContainsNone(cMessageCacheItems pItems) => (~mAttributes & pItems.Attributes) == pItems.Attributes && HeaderFields.ContainsNone(pItems.Names);