internal Task FetchAsync(iMessageHandle pMessageHandle, 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(FetchAsync)); return(ZFetchBodyAsync(pMessageHandle, pSection, pDecoding, pStream, pConfiguration, lContext)); }
public cFilterMSNRelativity(cFilterMSNOffset pOffset, eFilterHandleRelativity pRelativity) { End = pOffset.End; MessageHandle = pOffset.MessageHandle; Offset = pOffset.Offset; Relativity = pRelativity; }
public cFilterMSNRelativity(iMessageHandle pMessageHandle, eFilterHandleRelativity pRelativity) : base(true, pMessageHandle.MessageCache.UIDValidity) { MessageHandle = pMessageHandle ?? throw new ArgumentNullException(nameof(pMessageHandle)); End = null; Offset = 0; Relativity = pRelativity; }
internal void Fetch(iMessageHandle pMessageHandle, 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(Fetch)); var lTask = ZFetchBodyAsync(pMessageHandle, pSection, pDecoding, pStream, pConfiguration, lContext); mSynchroniser.Wait(lTask, lContext); }
internal int FetchSizeInBytes(iMessageHandle pMessageHandle, cSinglePartBody pPart) { var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(FetchSizeInBytes)); var lTask = ZFetchSizeInBytesAsync(pMessageHandle, pPart, lContext); mSynchroniser.Wait(lTask, lContext); return(lTask.Result); }
internal cCopyFeedback Copy(iMessageHandle pSourceMessageHandle, iMailboxHandle pDestinationMailboxHandle) { var lContext = mRootContext.NewMethodV(nameof(cIMAPClient), nameof(Copy), 1); var lTask = ZCopyAsync(cMessageHandleList.FromMessageHandle(pSourceMessageHandle), pDestinationMailboxHandle, lContext); mSynchroniser.Wait(lTask, lContext); return(lTask.Result); }
internal async Task <cStoreFeedback> StoreAsync(iMessageHandle pMessageHandle, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq) { var lContext = mRootContext.NewMethodV(nameof(cIMAPClient), nameof(StoreAsync), 1); var lFeedback = new cStoreFeedback(pMessageHandle, pOperation, pFlags); await ZStoreAsync(lFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext).ConfigureAwait(false); return(lFeedback); }
internal cStoreFeedback Store(iMessageHandle pMessageHandle, eStoreOperation pOperation, cStorableFlags pFlags, ulong?pIfUnchangedSinceModSeq) { var lContext = mRootContext.NewMethodV(nameof(cIMAPClient), nameof(Store), 1); var lFeedback = new cStoreFeedback(pMessageHandle, pOperation, pFlags); var lTask = ZStoreAsync(lFeedback, pOperation, pFlags, pIfUnchangedSinceModSeq, lContext); mSynchroniser.Wait(lTask, lContext); return(lFeedback); }
private async Task ZFetchBodyAsync(iMessageHandle pMessageHandle, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cBodyFetchConfiguration pConfiguration, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZFetchBodyAsync), pMessageHandle, 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 (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } 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.FetchBodyAsync(lMC, pMessageHandle, 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.FetchBodyAsync(lMC, pMessageHandle, pSection, pDecoding, pStream, lProgress, lWriteSizer, lContext).ConfigureAwait(false); } }
public void InvokeMessagePropertyChanged(iMessageHandle pMessageHandle, string pPropertyName, cTrace.cContext pParentContext) { if (MessagePropertyChanged == null) { return; // pre-check for efficiency only } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeMessagePropertyChanged), pMessageHandle, pPropertyName); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } ZInvokeAndForget(new cMessagePropertyChangedEventArgs(pMessageHandle, pPropertyName), lContext); }
public cSelectedMailbox CheckInSelectedMailbox(iMessageHandle pMessageHandle) { if (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } if (mSelectedMailbox == null || !ReferenceEquals(pMessageHandle.MessageCache, mSelectedMailbox.MessageCache)) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.MailboxNotSelected); } if (pMessageHandle.Expunged) { throw new cMessageExpungedException(pMessageHandle); } return(mSelectedMailbox); }
internal cStoreFeedback(iMessageHandle pMessageHandle, eStoreOperation pOperation, cStorableFlags pFlags) { if (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } if (pFlags == null) { throw new ArgumentNullException(nameof(pFlags)); } mItems = new List <cStoreFeedbackItem>(); mItems.Add(new cStoreFeedbackItem(pMessageHandle)); mOperation = pOperation; mFlags = pFlags; }
public uint GetMSN(iMessageHandle pMessageHandle) { // this should only be called when no msnunsafe commands are running // zero return means that the message isn't cached if (!(pMessageHandle is cItem lItem)) { return(0); } if (!ReferenceEquals(lItem.MessageCache, this)) { return(0); } int lIndex = mItems.BinarySearch(lItem); if (lIndex < 0) { return(0); } return((uint)lIndex + 1); }
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)); }
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)); }
public Task FetchBodyAsync(cMethodControl pMC, iMessageHandle pMessageHandle, cSection pSection, eDecodingRequired pDecoding, Stream pStream, cProgress pProgress, cBatchSizer pWriteSizer, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(FetchBodyAsync), pMC, pMessageHandle, pSection, pDecoding); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } mMailboxCache.CheckInSelectedMailbox(pMessageHandle); // to be repeated inside the select lock if (pMessageHandle.UID == null) { return(ZFetchBodyAsync(pMC, null, null, pMessageHandle, pSection, pDecoding, pStream, pProgress, pWriteSizer, lContext)); } else { return(ZFetchBodyAsync(pMC, pMessageHandle.MessageCache.MailboxHandle, pMessageHandle.UID, null, pSection, pDecoding, pStream, pProgress, pWriteSizer, lContext)); } }
internal cFilterMSNOffset(eFilterEnd pEnd, int pOffset) { MessageHandle = null; End = pEnd; Offset = pOffset; }
internal cFilterMSNOffset(iMessageHandle pMessageHandle, int pOffset) { MessageHandle = pMessageHandle ?? throw new ArgumentNullException(nameof(pMessageHandle)); End = null; Offset = pOffset; }
private async Task <int> ZFetchSizeInBytesAsync(iMessageHandle pMessageHandle, cSinglePartBody pPart, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZFetchSizeInBytesAsync), pMessageHandle, pPart); if (mDisposed) { throw new ObjectDisposedException(nameof(cIMAPClient)); } var lSession = mSession; if (lSession == null || lSession.ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } if (pPart == null) { throw new ArgumentNullException(nameof(pPart)); } if (lSession.Capabilities.Binary && pPart.Section.TextPart == eSectionTextPart.all && pPart.DecodingRequired != eDecodingRequired.none) { uint lSizeInBytes; if (pMessageHandle.BinarySizes.TryGetValue(pPart.Section.Part, out lSizeInBytes)) { return((int)lSizeInBytes); } using (var lToken = mCancellationManager.GetToken(lContext)) { var lMC = new cMethodControl(mTimeout, lToken.CancellationToken); if (pMessageHandle.UID == null) { await lSession.FetchBinarySizeAsync(lMC, pMessageHandle, pPart.Section.Part, lContext).ConfigureAwait(false); } else { if (pMessageHandle.Expunged) { throw new cMessageExpungedException(pMessageHandle); } await lSession.UIDFetchBinarySizeAsync(lMC, pMessageHandle.MessageCache.MailboxHandle, pMessageHandle.UID, pPart.Section.Part, lContext).ConfigureAwait(false); } } if (pMessageHandle.BinarySizes.TryGetValue(pPart.Section.Part, out lSizeInBytes)) { return((int)lSizeInBytes); } if (pMessageHandle.Expunged) { throw new cMessageExpungedException(pMessageHandle); } else { throw new cRequestedDataNotReturnedException(); } } return((int)pPart.SizeInBytes); }
internal Task <int> FetchSizeInBytesAsync(iMessageHandle pMessageHandle, cSinglePartBody pPart) { var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(FetchSizeInBytesAsync)); return(ZFetchSizeInBytesAsync(pMessageHandle, pPart, lContext)); }
internal cMessageExpungedException(iMessageHandle pMessageHandle) { MessageHandle = pMessageHandle; }
internal cMessagePropertyChangedEventArgs(iMessageHandle pMessageHandle, string pPropertyName) : base(pPropertyName) { MessageHandle = pMessageHandle; }
public async Task FetchBinarySizeAsync(cMethodControl pMC, iMessageHandle pMessageHandle, string pPart, cTrace.cContext pParentContext) { var lContext = pParentContext.NewMethod(nameof(cSession), nameof(FetchBinarySizeAsync), pMC, pMessageHandle, pPart); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } 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 cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pMessageHandle); 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 the MSN uint lMSN = lSelectedMailbox.GetMSN(pMessageHandle); if (lMSN == 0) { if (pMessageHandle.Expunged) { throw new cMessageExpungedException(pMessageHandle); } else { throw new ArgumentOutOfRangeException(nameof(pMessageHandle)); } } // build command lBuilder.Add(kFetchCommandPartFetchSpace, new cTextCommandPart(lMSN), kFetchCommandPartSpaceBinarySizeLBracket, lPart, cCommandPart.RBracket); // go var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false); if (lResult.ResultType == eCommandResultType.ok) { lContext.TraceInformation("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); } }
public void InvokeMessagePropertiesChanged(iMessageHandle pMessageHandle, fMessageProperties pProperties, cTrace.cContext pParentContext) { if (MessagePropertyChanged == null || pProperties == 0) { return; // pre-checks for efficiency } var lContext = pParentContext.NewMethod(nameof(cCallbackSynchroniser), nameof(InvokeMessagePropertiesChanged), pMessageHandle, pProperties); if (mDisposed) { throw new ObjectDisposedException(nameof(cCallbackSynchroniser)); } if ((pProperties & fMessageProperties.flags) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Flags))); } if ((pProperties & fMessageProperties.answered) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Answered))); } if ((pProperties & fMessageProperties.flagged) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Flagged))); } if ((pProperties & fMessageProperties.deleted) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Deleted))); } if ((pProperties & fMessageProperties.seen) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Seen))); } if ((pProperties & fMessageProperties.draft) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Draft))); } if ((pProperties & fMessageProperties.recent) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Recent))); } // see comments elsewhere as to why this is commented out //if ((pProperties & fMessageProperties.mdnsent) != 0) ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pHandle, nameof(cMessage.MDNSent))); if ((pProperties & fMessageProperties.forwarded) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Forwarded))); } if ((pProperties & fMessageProperties.submitpending) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.SubmitPending))); } if ((pProperties & fMessageProperties.submitted) != 0) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.Submitted))); } if (((pProperties & fMessageProperties.modseq) != 0)) { ZInvokeAndForgetEnqueue(new cMessagePropertyChangedEventArgs(pMessageHandle, nameof(cMessage.ModSeq))); } ZInvokeAndForget(lContext); }
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); }
/// <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 the result may be misleading. /// </remarks> /// <seealso cref="Attributes"/> /// <seealso cref="iMessageHandle.Attributes"/> /// <seealso cref="cMailbox.Messages(IEnumerable{iMessageHandle}, cMessageCacheItems, cCacheItemFetchConfiguration)"/> public int Compare(iMessageHandle pX, iMessageHandle pY) { if (pX == null) { if (pY == null) { return(0); } return(-1); } if (pY == null) { return(1); } if (Items != null) { foreach (var lItem in Items) { int lCompareTo; switch (lItem.Item) { case eSortItem.received: lCompareTo = ZCompareTo(pX.Received, pY.Received); break; case eSortItem.cc: lCompareTo = ZCompareTo(pX.Envelope?.CC?.SortString, pY.Envelope?.CC?.SortString); break; case eSortItem.sent: // rfc 5256 says to use the internal date if the sent date is null lCompareTo = ZCompareTo(pX.Envelope?.Sent ?? pX.Received, pY.Envelope?.Sent ?? pY.Received); break; case eSortItem.from: lCompareTo = ZCompareTo(pX.Envelope?.From?.SortString, pY.Envelope?.From?.SortString); break; case eSortItem.size: lCompareTo = ZCompareTo(pX.Size, pY.Size); break; case eSortItem.subject: lCompareTo = ZCompareTo(pX.Envelope?.BaseSubject, pY.Envelope?.BaseSubject); break; case eSortItem.to: lCompareTo = ZCompareTo(pX.Envelope?.To?.SortString, pY.Envelope?.To?.SortString); break; case eSortItem.displayfrom: lCompareTo = ZCompareTo(pX.Envelope?.From?.DisplaySortString, pY.Envelope?.From?.DisplaySortString); break; case eSortItem.displayto: lCompareTo = ZCompareTo(pX.Envelope?.To?.DisplaySortString, pY.Envelope?.To?.DisplaySortString); break; default: lCompareTo = 0; break; } if (lCompareTo != 0) { if (lItem.Desc) { return(-lCompareTo); } else { return(lCompareTo); } } } } return(pX.CacheSequence.CompareTo(pY.CacheSequence)); }
public uint GetMSN(iMessageHandle pMessageHandle) => mCache.GetMSN(pMessageHandle); // this should only be called when no msnunsafe commands are running
internal Task <cCopyFeedback> CopyAsync(iMessageHandle pSourceMessageHandle, iMailboxHandle pDestinationMailboxHandle) { var lContext = mRootContext.NewMethodV(nameof(cIMAPClient), nameof(CopyAsync), 1); return(ZCopyAsync(cMessageHandleList.FromMessageHandle(pSourceMessageHandle), pDestinationMailboxHandle, lContext)); }
// re-instate if threading is ever done //public readonly int Indent; // Indicates the indent of the message. This only means something when compared to the indents of surrounding items in a threaded list of messages. It is a bit of a hack having it in this class. internal cMessage(cIMAPClient pClient, iMessageHandle pMessageHandle) // , int pIndent = -1 // re-instate if threading is ever done { Client = pClient ?? throw new ArgumentNullException(nameof(pClient)); MessageHandle = pMessageHandle ?? throw new ArgumentNullException(nameof(pMessageHandle)); //Indent = pIndent; // re-instate if threading is ever done }
private async Task <cBody> ZFetchBodyAsync(cMethodControl pMC, iMessageHandle pMessageHandle, 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(ZFetchBodyAsync), pMC, pMessageHandle, pBinary, pSection, pOrigin, pLength); if (mDisposed) { throw new ObjectDisposedException(nameof(cSession)); } if (_ConnectionState != eConnectionState.selected) { throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotSelected); } if (pMessageHandle == null) { throw new ArgumentNullException(nameof(pMessageHandle)); } if (pSection == null) { throw new ArgumentNullException(nameof(pSection)); } using (var lBuilder = new cCommandDetailsBuilder()) { lBuilder.Add(await mSelectExclusiveAccess.GetBlockAsync(pMC, lContext).ConfigureAwait(false)); // block select cSelectedMailbox lSelectedMailbox = mMailboxCache.CheckInSelectedMailbox(pMessageHandle); 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 set before the handle is resolved lBuilder.AddUIDValidity(lSelectedMailbox.MessageCache.UIDValidity); // resolve the MSN uint lMSN = lSelectedMailbox.GetMSN(pMessageHandle); if (lMSN == 0) { if (pMessageHandle.Expunged) { throw new cMessageExpungedException(pMessageHandle); } throw new ArgumentOutOfRangeException(nameof(pMessageHandle)); } // build command lBuilder.Add(kFetchCommandPartFetchSpace, new cTextCommandPart(lMSN)); if (pBinary) { lBuilder.Add(kFetchCommandPartSpaceBinaryPeekLBracket); } else { lBuilder.Add(kFetchCommandPartSpaceBodyPeekLBracket); } lBuilder.Add(pSection, pOrigin, pLength); // hook var lHook = new cCommandHookFetchBodyMSN(pBinary, pSection, pOrigin, lMSN); lBuilder.Add(lHook); // go var lResult = await mPipeline.ExecuteAsync(pMC, lBuilder.EmitCommandDetails(), lContext).ConfigureAwait(false); if (lResult.ResultType == eCommandResultType.ok) { lContext.TraceInformation("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 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); } }