Example #1
0
        internal Task UIDFetchAsync(iMailboxHandle pMailboxHandle, cUID pUID, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cBodyFetchConfiguration pConfiguration)
        {
            // note: if it fails bytes could have been written to the stream
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(UIDFetchAsync));

            return(ZUIDFetchBodyAsync(pMailboxHandle, pUID, pSection, pDecoding, pStream, pConfiguration, lContext));
        }
Example #2
0
        internal cCopyFeedback UIDCopy(iMailboxHandle pSourceMailboxHandle, cUID pSourceUID, iMailboxHandle pDestinationMailboxHandle)
        {
            var lContext = mRootContext.NewMethodV(nameof(cIMAPClient), nameof(UIDCopy), 1);
            var lTask    = ZUIDCopyAsync(pSourceMailboxHandle, cUIDList.FromUID(pSourceUID), pDestinationMailboxHandle, lContext);

            mSynchroniser.Wait(lTask, lContext);
            return(lTask.Result);
        }
Example #3
0
 public iMessageHandle GetHandle(cUID pUID)
 {
     if (mUIDIndex.TryGetValue(pUID, out var lMessageHandle))
     {
         return(lMessageHandle);
     }
     return(null);
 }
Example #4
0
        internal cUIDStoreFeedback UIDStore(iMailboxHandle pMailboxHandle, cUID pUID, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq)
        {
            var lContext  = mRootContext.NewMethod(nameof(cIMAPClient), nameof(UIDStore));
            var lFeedback = new cUIDStoreFeedback(pUID, pOperation, pFlags);
            var lTask     = ZUIDStoreAsync(pMailboxHandle, lFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext);

            mSynchroniser.Wait(lTask, lContext);
            return(lFeedback);
        }
Example #5
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);
            }
        }
Example #6
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);
        }
Example #7
0
        internal cUIDStoreFeedback(cUID pUID, eStoreOperation pOperation, cStorableFlags pFlags)
        {
            if (pUID == null)
            {
                throw new ArgumentNullException(nameof(pUID));
            }
            if (pFlags == null)
            {
                throw new ArgumentNullException(nameof(pFlags));
            }

            mItems = new List <cUIDStoreFeedbackItem>();
            mItems.Add(new cUIDStoreFeedbackItem(pUID));

            mOperation = pOperation;
            mFlags     = pFlags;
        }
Example #8
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);
        }
Example #9
0
            private async Task <cBody> ZUIDFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, bool pBinary, cSection pSection, uint pOrigin, uint pLength, cTrace.cContext pParentContext)
            {
                // the caller must have checked that the binary option is compatible with the section (e.g. if binary is true the section can't specify a textpart)
                //  the length must be greater than zero

                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZUIDFetchBodyAsync), pMC, pMailboxHandle, pUID, pBinary, pSection, pOrigin, pLength);

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

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

                    mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity);

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

                    // set uidvalidity
                    lBuilder.AddUIDValidity(pUID.UIDValidity);

                    // build command

                    lBuilder.Add(kFetchCommandPartUIDFetchSpace, new cTextCommandPart(pUID.UID));

                    if (pBinary)
                    {
                        lBuilder.Add(kFetchCommandPartSpaceBinaryPeekLBracket);
                    }
                    else
                    {
                        lBuilder.Add(kFetchCommandPartSpaceBodyPeekLBracket);
                    }

                    lBuilder.Add(pSection, pOrigin, pLength);

                    // hook
                    var lHook = new cCommandHookFetchBodyUID(pBinary, pSection, pOrigin, pUID.UID);
                    lBuilder.Add(lHook);

                    // go

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

                    if (lResult.ResultType == eCommandResultType.ok)
                    {
                        lContext.TraceInformation("uid fetch body success");
                        if (lHook.Body == null)
                        {
                            throw new cRequestedDataNotReturnedException(lContext);
                        }
                        return(lHook.Body);
                    }

                    if (lHook.Body != null)
                    {
                        lContext.TraceError("received body on a failed uid fetch body");
                    }

                    fCapabilities lTryIgnoring;
                    if (pBinary)
                    {
                        lTryIgnoring = fCapabilities.binary;
                    }
                    else
                    {
                        lTryIgnoring = 0;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }
Example #10
0
        internal async Task <cUIDStoreFeedback> UIDStoreAsync(iMailboxHandle pMailboxHandle, cUID pUID, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq)
        {
            var lContext  = mRootContext.NewMethod(nameof(cIMAPClient), nameof(UIDStore));
            var lFeedback = new cUIDStoreFeedback(pUID, pOperation, pFlags);

            await ZUIDStoreAsync(pMailboxHandle, lFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext).ConfigureAwait(false);

            return(lFeedback);
        }
Example #11
0
        internal Task <cCopyFeedback> UIDCopyAsync(iMailboxHandle pSourceMailboxHandle, cUID pSourceUID, iMailboxHandle pDestinationMailboxHandle)
        {
            var lContext = mRootContext.NewMethodV(nameof(cIMAPClient), nameof(UIDCopyAsync), 1);

            return(ZUIDCopyAsync(pSourceMailboxHandle, cUIDList.FromUID(pSourceUID), pDestinationMailboxHandle, lContext));
        }
Example #12
0
            private async Task ZFetchBodyAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, iMessageHandle pMessageHandle, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ZFetchBodyAsync), pMC, pMailboxHandle, pUID, pMessageHandle, pSection, pDecoding);

                if (pSection == null)
                {
                    throw new ArgumentNullException(nameof(pSection));
                }
                if (pStream == null)
                {
                    throw new ArgumentNullException(nameof(pStream));
                }
                if (pProgress == null)
                {
                    throw new ArgumentNullException(nameof(pProgress));
                }
                if (pWriteSizer == null)
                {
                    throw new ArgumentNullException(nameof(pWriteSizer));
                }

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

                // work out if binary can/should be used or not
                bool lBinary = _Capabilities.Binary && pSection.TextPart == eSectionTextPart.all && pDecoding != eDecodingRequired.none;

                cDecoder lDecoder;

                if (lBinary || pDecoding == eDecodingRequired.none)
                {
                    lDecoder = new cIdentityDecoder(pStream);
                }
                else if (pDecoding == eDecodingRequired.base64)
                {
                    lDecoder = new cBase64Decoder(pStream);
                }
                else if (pDecoding == eDecodingRequired.quotedprintable)
                {
                    lDecoder = new cQuotedPrintableDecoder(pStream);
                }
                else
                {
                    throw new cContentTransferDecodingException("required decoding not supported", lContext);
                }

                uint lOrigin = 0;

                Stopwatch lStopwatch = new Stopwatch();

                while (true)
                {
                    int lLength = mFetchBodyReadSizer.Current;

                    lStopwatch.Restart();

                    cBody lBody;
                    if (pUID == null)
                    {
                        lBody = await ZFetchBodyAsync(pMC, pMessageHandle, lBinary, pSection, lOrigin, (uint)lLength, lContext).ConfigureAwait(false);
                    }
                    else
                    {
                        lBody = await ZUIDFetchBodyAsync(pMC, pMailboxHandle, pUID, lBinary, pSection, lOrigin, (uint)lLength, lContext).ConfigureAwait(false);
                    }

                    lStopwatch.Stop();

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

                    uint lBodyOrigin = lBody.Origin ?? 0;

                    // the body that we get may start before the place that we asked for
                    int lOffset = (int)(lOrigin - lBodyOrigin);

                    // write the bytes
                    await lDecoder.WriteAsync(pMC, lBody.Bytes, lOffset, pWriteSizer, lContext).ConfigureAwait(false);

                    // update progress
                    pProgress.Increment(lBody.Bytes.Count - lOffset, lContext);

                    // if the body we got was the whole body, we are done
                    if (lBody.Origin == null)
                    {
                        break;
                    }

                    // if we got less bytes than asked for then we will assume that we are at the end
                    if (lBody.Bytes.Count - lOffset < lLength)
                    {
                        break;
                    }

                    // set the start point for the next fetch
                    lOrigin = lBodyOrigin + (uint)lBody.Bytes.Count;
                }

                await lDecoder.FlushAsync(pMC, pWriteSizer, lContext).ConfigureAwait(false);
            }
Example #13
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));
            }
Example #14
0
 internal cCopyFeedbackItem(cUID pSourceMessageUID, cUID pCreatedMessageUID)
 {
     SourceMessageUID  = pSourceMessageUID;
     CreatedMessageUID = pCreatedMessageUID;
 }
Example #15
0
 public iMessageHandle GetHandle(uint pMSN) => mCache.GetHandle(pMSN);                                                                                                        // this should only be called from a commandcompletion
 public iMessageHandle GetHandle(cUID pUID) => mCache.GetHandle(pUID);
Example #16
0
                public void Update(cResponseDataFetch lFetch, out fMessageCacheAttributes rAttributesSet, out fMessageProperties rPropertiesChanged)
                {
                    rAttributesSet     = ~mAttributes & lFetch.Attributes;
                    rPropertiesChanged = 0;

                    if ((rAttributesSet & fMessageCacheAttributes.flags) != 0)
                    {
                        Flags = lFetch.Flags;
                    }
                    else if (lFetch.Flags != null)
                    {
                        foreach (var lFlag in Flags.SymmetricDifference(lFetch.Flags))
                        {
                            rAttributesSet     |= fMessageCacheAttributes.flags;
                            rPropertiesChanged |= fMessageProperties.flags | LMessageProperty(lFlag);
                        }

                        Flags = lFetch.Flags;
                    }

                    if ((rAttributesSet & fMessageCacheAttributes.envelope) != 0)
                    {
                        Envelope = lFetch.Envelope;
                    }
                    if ((rAttributesSet & fMessageCacheAttributes.received) != 0)
                    {
                        Received = lFetch.Received;
                    }
                    if ((rAttributesSet & fMessageCacheAttributes.size) != 0)
                    {
                        Size = lFetch.Size;
                    }
                    if ((rAttributesSet & fMessageCacheAttributes.body) != 0)
                    {
                        mBody = lFetch.Body;
                    }
                    if ((rAttributesSet & fMessageCacheAttributes.bodystructure) != 0)
                    {
                        BodyStructure = lFetch.BodyStructure;
                    }
                    if ((rAttributesSet & fMessageCacheAttributes.uid) != 0 && mMessageCache.UIDValidity != 0)
                    {
                        UID = new cUID(mMessageCache.UIDValidity, lFetch.UID.Value);
                    }

                    if (!mMessageCache.NoModSeq)
                    {
                        if ((rAttributesSet & fMessageCacheAttributes.modseq) != 0)
                        {
                            mModSeq = lFetch.ModSeq;
                        }
                        else if (lFetch.ModSeq != null && lFetch.ModSeq != mModSeq)
                        {
                            rAttributesSet     |= fMessageCacheAttributes.modseq;
                            rPropertiesChanged |= fMessageProperties.modseq;
                            mModSeq             = lFetch.ModSeq;
                        }
                    }

                    HeaderFields += lFetch.HeaderFields;
                    BinarySizes  += lFetch.BinarySizes;

                    mAttributes |= lFetch.Attributes;

                    fMessageProperties LMessageProperty(string pFlag)
                    {
                        if (pFlag.Equals(kMessageFlag.Answered, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.answered);
                        }
                        if (pFlag.Equals(kMessageFlag.Flagged, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.flagged);
                        }
                        if (pFlag.Equals(kMessageFlag.Deleted, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.deleted);
                        }
                        if (pFlag.Equals(kMessageFlag.Seen, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.seen);
                        }
                        if (pFlag.Equals(kMessageFlag.Draft, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.draft);
                        }
                        if (pFlag.Equals(kMessageFlag.Recent, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.recent);
                        }
                        // see comments elsewhere as to why this is commented out
                        //if (pFlag.Equals(kMessageFlagName.MDNSent, StringComparison.InvariantCultureIgnoreCase)) return fMessageProperties.mdnsent;
                        if (pFlag.Equals(kMessageFlag.Forwarded, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.forwarded);
                        }
                        if (pFlag.Equals(kMessageFlag.SubmitPending, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.submitpending);
                        }
                        if (pFlag.Equals(kMessageFlag.Submitted, StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(fMessageProperties.submitted);
                        }
                        return(0);
                    }
                }
Example #17
0
            public async Task UIDFetchBinarySizeAsync(cMethodControl pMC, iMailboxHandle pMailboxHandle, cUID pUID, string pPart, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(UIDFetchBinarySizeAsync), pMC, pMailboxHandle, pUID, pPart);

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

                if (!cCommandPartFactory.TryAsAtom(pPart, out var lPart))
                {
                    throw new ArgumentOutOfRangeException(nameof(pPart));
                }

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

                    mMailboxCache.CheckIsSelectedMailbox(pMailboxHandle, pUID.UIDValidity);

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

                    // set uidvalidity
                    lBuilder.AddUIDValidity(pUID.UIDValidity);

                    // build command
                    lBuilder.Add(kFetchCommandPartUIDFetchSpace, new cTextCommandPart(pUID.UID), kFetchCommandPartSpaceBinarySizeLBracket, lPart, cCommandPart.RBracket);

                    // go

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

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

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, fCapabilities.binary, lContext);
                    }
                    throw new cProtocolErrorException(lResult, fCapabilities.binary, lContext);
                }
            }
Example #18
0
 internal cUIDStoreFeedbackItem(cUID pUID)
 {
     UID = pUID ?? throw new ArgumentNullException(nameof(pUID));
 }