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)); }
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); }
public iMessageHandle GetHandle(cUID pUID) { if (mUIDIndex.TryGetValue(pUID, out var lMessageHandle)) { return(lMessageHandle); } return(null); }
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); }
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); } }
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); }
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; }
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); }
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); } }
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); }
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)); }
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); }
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)); }
internal cCopyFeedbackItem(cUID pSourceMessageUID, cUID pCreatedMessageUID) { SourceMessageUID = pSourceMessageUID; CreatedMessageUID = pCreatedMessageUID; }
public iMessageHandle GetHandle(uint pMSN) => mCache.GetHandle(pMSN); // this should only be called from a commandcompletion public iMessageHandle GetHandle(cUID pUID) => mCache.GetHandle(pUID);
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); } }
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); } }
internal cUIDStoreFeedbackItem(cUID pUID) { UID = pUID ?? throw new ArgumentNullException(nameof(pUID)); }