Example #1
0
        private async Task <List <cMailbox> > ZSubscribedAsync(iMailboxHandle pMailboxHandle, bool pDescend, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZSubscribedAsync), pMailboxHandle, pDescend, pDataSets);

            if (pMailboxHandle == null)
            {
                throw new ArgumentNullException(nameof(pMailboxHandle));
            }
            if (pMailboxHandle.MailboxName.Delimiter == null)
            {
                return(new List <cMailbox>());
            }

            string lWildcard;

            if (pDescend)
            {
                lWildcard = "*";
            }
            else
            {
                lWildcard = "%";
            }

            string lListMailbox          = pMailboxHandle.MailboxName.Path.Replace('*', '%') + pMailboxHandle.MailboxName.Delimiter + lWildcard;
            cMailboxPathPattern lPattern = new cMailboxPathPattern(pMailboxHandle.MailboxName.Path + pMailboxHandle.MailboxName.Delimiter, lWildcard, pMailboxHandle.MailboxName.Delimiter);

            return(await ZZSubscribedAsync(lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, !pDescend, pDataSets, lContext).ConfigureAwait(false));
        }
Example #2
0
 public cListExtendedCommandHook(cMailboxCache pCache, eListExtendedSelect pSelect, cMailboxPathPattern pPattern, bool pStatus)
 {
     mCache   = pCache;
     mSelect  = pSelect;
     mPattern = pPattern;
     mStatus  = pStatus;
 }
Example #3
0
        private Task <List <cMailbox> > ZSubscribedAsync(cNamespaceName pNamespaceName, bool pDescend, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZSubscribedAsync), pNamespaceName, pDescend, pDataSets);

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

            string lWildcard;

            if (pDescend)
            {
                lWildcard = "*";
            }
            else
            {
                lWildcard = "%";
            }

            string lListMailbox          = pNamespaceName.Prefix.Replace('*', '%') + lWildcard;
            cMailboxPathPattern lPattern = new cMailboxPathPattern(pNamespaceName.Prefix, lWildcard, pNamespaceName.Delimiter);

            return(ZZSubscribedAsync(lListMailbox, pNamespaceName.Delimiter, lPattern, !pDescend, pDataSets, lContext));
        }
Example #4
0
        private Task <List <cMailbox> > ZMailboxesAsync(string pListMailbox, char?pDelimiter, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMailboxesAsync), pListMailbox, pDelimiter, pDataSets);

            if (string.IsNullOrEmpty(pListMailbox))
            {
                throw new ArgumentOutOfRangeException(nameof(pListMailbox));
            }
            cMailboxPathPattern lPattern = new cMailboxPathPattern(string.Empty, pListMailbox, pDelimiter);

            return(ZZMailboxesAsync(pListMailbox, pDelimiter, lPattern, pDataSets, lContext));
        }
Example #5
0
        private Task <List <cMailbox> > ZMailboxesAsync(cNamespaceName pNamespaceName, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMailboxesAsync), pNamespaceName, pDataSets);

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

            string lListMailbox          = pNamespaceName.Prefix.Replace('*', '%') + "%";
            cMailboxPathPattern lPattern = new cMailboxPathPattern(pNamespaceName.Prefix, "%", pNamespaceName.Delimiter);

            return(ZZMailboxesAsync(lListMailbox, pNamespaceName.Delimiter, lPattern, pDataSets, lContext));
        }
Example #6
0
                public void ResetExists(cMailboxPathPattern pPattern, int pSequence, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(ResetExists), pPattern, pSequence);

                    foreach (var lItem in mDictionary.Values)
                    {
                        if (lItem.Exists != false && lItem.MailboxName != null && pPattern.Matches(lItem.MailboxName.Path))
                        {
                            if (lItem.ListFlags == null || lItem.ListFlags.Sequence < pSequence)
                            {
                                lItem.ResetExists(lContext);
                            }
                        }
                    }
                }
Example #7
0
        private async Task <List <cMailbox> > ZMailboxesAsync(iMailboxHandle pMailboxHandle, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZMailboxesAsync), pMailboxHandle, pDataSets);

            if (pMailboxHandle == null)
            {
                throw new ArgumentNullException(nameof(pMailboxHandle));
            }
            if (pMailboxHandle.MailboxName.Delimiter == null)
            {
                return(new List <cMailbox>());
            }

            string lListMailbox          = pMailboxHandle.MailboxName.Path.Replace('*', '%') + pMailboxHandle.MailboxName.Delimiter + "%";
            cMailboxPathPattern lPattern = new cMailboxPathPattern(pMailboxHandle.MailboxName.Path + pMailboxHandle.MailboxName.Delimiter, "%", pMailboxHandle.MailboxName.Delimiter);

            return(await ZZMailboxesAsync(lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, pDataSets, lContext).ConfigureAwait(false));
        }
Example #8
0
                public void ResetLSubFlags(cMailboxPathPattern pPattern, int pSequence, cTrace.cContext pParentContext)
                {
                    // called after an LSub with subscribed = true
                    //  called after a list-extended/subscribed with subscribed = true

                    var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(ResetLSubFlags), pPattern, pSequence);

                    cLSubFlags lNotSubscribed = new cLSubFlags(mSequence++, false);

                    foreach (var lItem in mDictionary.Values)
                    {
                        if (lItem.MailboxName != null && pPattern.Matches(lItem.MailboxName.Path))
                        {
                            if (lItem.LSubFlags == null || lItem.LSubFlags.Sequence < pSequence)
                            {
                                lItem.SetLSubFlags(lNotSubscribed, lContext);
                            }
                        }
                    }
                }
Example #9
0
                public void ResetStatus(cMailboxPathPattern pPattern, int pSequence, cTrace.cContext pParentContext)
                {
                    var lContext = pParentContext.NewMethod(nameof(cMailboxCache), nameof(ResetStatus), pPattern, pSequence);

                    iMailboxHandle lSelectedMailboxHandle = mSelectedMailbox?.MailboxHandle;

                    foreach (var lItem in mDictionary.Values)
                    {
                        if (lItem.Exists != false && lItem.MailboxName != null && pPattern.Matches(lItem.MailboxName.Path))
                        {
                            if (lItem.Status != null && lItem.Status.Sequence < pSequence)
                            {
                                lItem.ClearStatus(lContext);
                                if (!ReferenceEquals(lSelectedMailboxHandle, lItem))
                                {
                                    lItem.UpdateMailboxStatus(lContext);
                                }
                            }
                        }
                    }
                }
Example #10
0
                public bool HasChildren(iMailboxHandle pMailboxHandle)
                {
                    CheckHandle(pMailboxHandle);

                    if (pMailboxHandle.MailboxName.Delimiter == null)
                    {
                        return(false);
                    }

                    cMailboxPathPattern lPattern = new cMailboxPathPattern(pMailboxHandle.MailboxName.Path + pMailboxHandle.MailboxName.Delimiter, "*", pMailboxHandle.MailboxName.Delimiter);

                    foreach (var lItem in mDictionary.Values)
                    {
                        if (lItem.Exists == true && lItem.MailboxName != null && lPattern.Matches(lItem.MailboxName.Path))
                        {
                            return(true);
                        }
                    }

                    return(false);
                }
Example #11
0
            public static void _Tests(cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cMailboxPathPattern), nameof(_Tests));

                cMailboxPathPattern lPattern;

                lPattern = new cMailboxPathPattern("", "*", null);

                if (!lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (!lPattern.Matches("fred/angus"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (!lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (!lPattern.Matches("fred/angus/tom"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (!lPattern.Matches("fred/nigel"))
                {
                    throw new cTestsException($"{lPattern},5");
                }
                if (!lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},6");
                }
                if (!lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},7");
                }
                if (!lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},8");
                }

                lPattern = new cMailboxPathPattern("", "*", '/');

                if (!lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (!lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (!lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (!lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (!lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},5");
                }

                lPattern = new cMailboxPathPattern("", "fred", '/');

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},5");
                }

                lPattern = new cMailboxPathPattern("", "fred*", '/');

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (!lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (!lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},5");
                }

                lPattern = new cMailboxPathPattern("", "*fred", '/');

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (!lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},5");
                }


                lPattern = new cMailboxPathPattern("", "*fred*", '/');

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (!lPattern.Matches("fred/angus"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (!lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (!lPattern.Matches("fred/angus/tom"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (!lPattern.Matches("fred/nigel"))
                {
                    throw new cTestsException($"{lPattern},5");
                }
                if (!lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},6");
                }
                if (!lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},7");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},8");
                }

                lPattern = new cMailboxPathPattern("fred/", "%", null);

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (!lPattern.Matches("fred/angus"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (!lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (!lPattern.Matches("fred/angus/tom"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (!lPattern.Matches("fred/nigel"))
                {
                    throw new cTestsException($"{lPattern},5");
                }
                if (!lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},6");
                }
                if (lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},7");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},8");
                }


                lPattern = new cMailboxPathPattern("fred/", "%", '/');

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (!lPattern.Matches("fred/angus"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (lPattern.Matches("fred/angus/tom"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (!lPattern.Matches("fred/nigel"))
                {
                    throw new cTestsException($"{lPattern},5");
                }
                if (lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},6");
                }
                if (lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},7");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},8");
                }



                lPattern = new cMailboxPathPattern("", "*/%g%/*", '/');

                if (lPattern.Matches(""))
                {
                    throw new cTestsException($"{lPattern},1");
                }
                if (lPattern.Matches("fred/angus"))
                {
                    throw new cTestsException($"{lPattern},2");
                }
                if (!lPattern.Matches("fred/angus/nigel"))
                {
                    throw new cTestsException($"{lPattern},3");
                }
                if (!lPattern.Matches("fred/angus/tom"))
                {
                    throw new cTestsException($"{lPattern},4");
                }
                if (lPattern.Matches("fred/nigel"))
                {
                    throw new cTestsException($"{lPattern},5");
                }
                if (!lPattern.Matches("fred/nigel/angus"))
                {
                    throw new cTestsException($"{lPattern},6");
                }
                if (lPattern.Matches("~other/fred"))
                {
                    throw new cTestsException($"{lPattern},7");
                }
                if (lPattern.Matches("~other/angus"))
                {
                    throw new cTestsException($"{lPattern},8");
                }
            }
Example #12
0
        // common processing

        private async Task <List <cMailbox> > ZZMailboxesAsync(string pListMailbox, char?pDelimiter, cMailboxPathPattern pPattern, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZZMailboxesAsync), pListMailbox, pDelimiter, pPattern, pDataSets);

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

            var lSession = mSession;

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

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

            List <iMailboxHandle> lMailboxHandles;

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

                var  lCapabilities = lSession.Capabilities;
                bool lLSub         = (pDataSets & fMailboxCacheDataSets.lsub) != 0;
                bool lStatus       = (pDataSets & fMailboxCacheDataSets.status) != 0;

                Task <List <iMailboxHandle> > lListTask;
                Task lLSubTask;

                if (lCapabilities.ListExtended)
                {
                    bool lListStatus = lStatus && lCapabilities.ListStatus;

                    lListTask = lSession.ListExtendedAsync(lMC, eListExtendedSelect.exists, mMailboxReferrals, pListMailbox, pDelimiter, pPattern, lListStatus, lContext);

                    if (lLSub && (mMailboxCacheDataItems & fMailboxCacheDataItems.subscribed) == 0)
                    {
                        if (mMailboxReferrals)
                        {
                            lLSubTask = lSession.ListExtendedAsync(lMC, eListExtendedSelect.subscribed, true, pListMailbox, pDelimiter, pPattern, false, lContext);
                        }
                        else
                        {
                            lLSubTask = lSession.LSubAsync(lMC, pListMailbox, pDelimiter, pPattern, false, lContext);
                        }
                    }
                    else
                    {
                        lLSubTask = null;
                    }

                    lMailboxHandles = await lListTask.ConfigureAwait(false);

                    if (lStatus && !lListStatus)
                    {
                        await ZRequestStatus(lMC, lSession, lMailboxHandles, lContext).ConfigureAwait(false);
                    }
                }
                else
                {
                    if (mMailboxReferrals && lCapabilities.MailboxReferrals)
                    {
                        lListTask = lSession.RListAsync(lMC, pListMailbox, pDelimiter, pPattern, lContext);
                    }
                    else
                    {
                        lListTask = lSession.ListMailboxesAsync(lMC, pListMailbox, pDelimiter, pPattern, lContext);
                    }

                    if (lLSub)
                    {
                        if (mMailboxReferrals && lCapabilities.MailboxReferrals)
                        {
                            lLSubTask = lSession.RLSubAsync(lMC, pListMailbox, pDelimiter, pPattern, false, lContext);
                        }
                        else
                        {
                            lLSubTask = lSession.LSubAsync(lMC, pListMailbox, pDelimiter, pPattern, false, lContext);
                        }
                    }
                    else
                    {
                        lLSubTask = null;
                    }

                    lMailboxHandles = await lListTask.ConfigureAwait(false);

                    if (lStatus)
                    {
                        await ZRequestStatus(lMC, lSession, lMailboxHandles, lContext).ConfigureAwait(false);
                    }
                }

                if (lLSubTask != null)
                {
                    await lLSubTask.ConfigureAwait(false);
                }
            }

            List <cMailbox> lMailboxes = new List <cMailbox>();

            foreach (var lMailboxHandle in lMailboxHandles)
            {
                lMailboxes.Add(new cMailbox(this, lMailboxHandle));
            }
            return(lMailboxes);
        }
Example #13
0
 public cCommandHookListMailboxes(cMailboxCache pCache, cMailboxPathPattern pPattern)
 {
     mCache   = pCache;
     mPattern = pPattern;
 }
Example #14
0
        private async Task ZConnectAsync(cTrace.cContext pParentContext)
        {
            var lContext = mRootContext.NewMethod(nameof(cIMAPClient), nameof(ZConnectAsync));

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

            cServer      lServer      = Server;
            cCredentials lCredentials = Credentials;

            if (lServer == null)
            {
                throw new InvalidOperationException("connect requires server to be set");
            }
            if (lCredentials == null)
            {
                throw new InvalidOperationException("connect requires credentials to be set");
            }

            bool lSessionReplaced;

            if (mSession == null)
            {
                lSessionReplaced = false;
            }
            else
            {
                if (!mSession.IsUnconnected)
                {
                    throw new InvalidOperationException(kInvalidOperationExceptionMessage.NotUnconnected);
                }
                mSession.Dispose();

                lSessionReplaced = true;

                mNamespaces = null;

                mInbox = null;
                mSynchroniser.InvokePropertyChanged(nameof(Inbox), lContext);
            }

            // initialise the SASLs
            foreach (var lSASL in lCredentials.SASLs)
            {
                lSASL.LastAuthentication = null;
            }

            mSession = new cSession(mSynchroniser, mIgnoreCapabilities, mMailboxCacheDataItems, mNetworkWriteConfiguration, mIdleConfiguration, mFetchCacheItemsConfiguration, mFetchBodyReadConfiguration, mEncoding, lContext);
            var lSession = mSession;

            if (lSessionReplaced)
            {
                mSynchroniser.InvokePropertyChanged(nameof(Capabilities), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(ConnectionState), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(IsConnected), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(IsUnconnected), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(ConnectedAccountId), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(EnabledExtensions), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(HomeServerReferral), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(ServerId), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(Namespaces), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(SelectedMailbox), lContext);
                mSynchroniser.InvokePropertyChanged(nameof(SelectedMailboxDetails), lContext);
            }

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

                try
                {
                    await lSession.ConnectAsync(lMC, lServer, lContext).ConfigureAwait(false);

                    if (lSession.Capabilities == null)
                    {
                        await lSession.CapabilityAsync(lMC, lContext).ConfigureAwait(false);
                    }

                    if (lSession.ConnectionState == eConnectionState.notauthenticated && !lSession.TLSInstalled && lSession.Capabilities.StartTLS)
                    {
                        await lSession.StartTLSAsync(lMC, lContext).ConfigureAwait(false);

                        await lSession.CapabilityAsync(lMC, lContext).ConfigureAwait(false);
                    }

                    object        lOriginalCapabilities = lSession.Capabilities;
                    cCapabilities lCurrentCapabilities  = lSession.Capabilities;

                    if (lSession.ConnectionState == eConnectionState.notauthenticated)
                    {
                        bool      lTLSIssue              = false;
                        bool      lTriedCredentials      = false;
                        Exception lAuthenticateException = null;

                        cAccountId lAccountId = new cAccountId(lServer.Host, lCredentials.Type, lCredentials.UserId);

                        bool lTLSInstalled = lSession.TLSInstalled;

                        if (lCredentials.TryAllSASLs)
                        {
                            foreach (var lSASL in lCredentials.SASLs)
                            {
                                if ((lSASL.TLSRequirement == eTLSRequirement.required && !lTLSInstalled) || (lSASL.TLSRequirement == eTLSRequirement.disallowed && lTLSInstalled))
                                {
                                    lTLSIssue = true;
                                }
                                else
                                {
                                    lTriedCredentials      = true;
                                    lAuthenticateException = await lSession.AuthenticateAsync(lMC, lAccountId, lSASL, lContext).ConfigureAwait(false);

                                    if (lSession.ConnectionState != eConnectionState.notauthenticated || lAuthenticateException != null)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            foreach (var lSASL in lCredentials.SASLs)
                            {
                                if (lCurrentCapabilities.AuthenticationMechanisms.Contains(lSASL.MechanismName)) // no case-invariance required because SASL (rfc 2222) says only uppercase is allowed
                                {
                                    if ((lSASL.TLSRequirement == eTLSRequirement.required && !lTLSInstalled) || (lSASL.TLSRequirement == eTLSRequirement.disallowed && lTLSInstalled))
                                    {
                                        lTLSIssue = true;
                                    }
                                    else
                                    {
                                        lTriedCredentials      = true;
                                        lAuthenticateException = await lSession.AuthenticateAsync(lMC, lAccountId, lSASL, lContext).ConfigureAwait(false);

                                        if (lSession.ConnectionState != eConnectionState.notauthenticated || lAuthenticateException != null)
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        if (lSession.ConnectionState == eConnectionState.notauthenticated && lAuthenticateException == null && !lCurrentCapabilities.LoginDisabled && lCredentials.Login != null)
                        {
                            if ((lCredentials.Login.TLSRequirement == eTLSRequirement.required && !lTLSInstalled) || (lCredentials.Login.TLSRequirement == eTLSRequirement.disallowed && lTLSInstalled))
                            {
                                lTLSIssue = true;
                            }
                            else
                            {
                                lTriedCredentials      = true;
                                lAuthenticateException = await lSession.LoginAsync(lMC, lAccountId, lCredentials.Login, lContext).ConfigureAwait(false);
                            }
                        }

                        if (lSession.ConnectionState != eConnectionState.authenticated)
                        {
                            lContext.TraceError("could not authenticate");

                            // log out
                            await lSession.LogoutAsync(lMC, lContext).ConfigureAwait(false);

                            // throw an exception that indicates why we couldn't connect

                            if (lTriedCredentials)
                            {
                                if (lAuthenticateException != null)
                                {
                                    throw lAuthenticateException;
                                }
                                throw new cCredentialsException(lContext);
                            }

                            throw new cAuthenticationMechanismsException(lTLSIssue, lContext); // the server has no mechanisms that we can try
                        }

                        // re-get the capabilities if we didn't get new ones as part of the authentication/ login OR if a security layer was installed (SASL requires this)
                        if (ReferenceEquals(lOriginalCapabilities, lSession.Capabilities) || lSession.SASLSecurityInstalled)
                        {
                            await lSession.CapabilityAsync(lMC, lContext).ConfigureAwait(false);
                        }
                        lCurrentCapabilities = lSession.Capabilities;
                    }

                    if (lCurrentCapabilities.Enable)
                    {
                        fEnableableExtensions lExtensions = fEnableableExtensions.none;
                        if (lCurrentCapabilities.UTF8Accept || lCurrentCapabilities.UTF8Only)
                        {
                            lExtensions = lExtensions | fEnableableExtensions.utf8;
                        }
                        if (lExtensions != fEnableableExtensions.none)
                        {
                            await lSession.EnableAsync(lMC, lExtensions, lContext).ConfigureAwait(false);
                        }
                    }

                    // enabled (lock in the capabilities and enabled extensions)
                    lSession.SetEnabled(lContext);

                    Task lIdTask;

                    if (lCurrentCapabilities.Id)
                    {
                        cId lClientId;

                        if ((lSession.EnabledExtensions & fEnableableExtensions.utf8) == 0)
                        {
                            lClientId = mClientId;
                        }
                        else
                        {
                            lClientId = mClientIdUTF8 ?? mClientId;
                        }

                        lIdTask = lSession.IdAsync(lMC, lClientId, lContext);
                    }
                    else
                    {
                        lIdTask = null;
                    }

                    if (lCurrentCapabilities.Namespace)
                    {
                        await lSession.NamespaceAsync(lMC, lContext).ConfigureAwait(false);

                        var lPersonalNamespaceNames = lSession.NamespaceNames?.Personal;

                        if (lPersonalNamespaceNames != null)
                        {
                            foreach (var lName in lPersonalNamespaceNames)
                            {
                                // special case, where the personal namespace is "INBOX/" (where "/" is the delimiter)
                                if (lName.Delimiter != null && lName.Prefix.Equals(cMailboxName.InboxString + lName.Delimiter, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    mInbox = new cMailbox(this, lSession.GetMailboxHandle(new cMailboxName(cMailboxName.InboxString, lName.Delimiter)));
                                    mSynchroniser.InvokePropertyChanged(nameof(Inbox), lContext);
                                    break;
                                }

                                cMailboxPathPattern lPattern = new cMailboxPathPattern(lName.Prefix, "%", lName.Delimiter);

                                if (lPattern.Matches(cMailboxName.InboxString))
                                {
                                    mInbox = new cMailbox(this, lSession.GetMailboxHandle(new cMailboxName(cMailboxName.InboxString, lName.Delimiter)));
                                    mSynchroniser.InvokePropertyChanged(nameof(Inbox), lContext);
                                    break;
                                }
                            }
                        }
                    }

                    if (mInbox == null)
                    {
                        var lDelimiter = await lSession.ListDelimiterAsync(lMC, lContext).ConfigureAwait(false);

                        if (!lCurrentCapabilities.Namespace)
                        {
                            mNamespaces = new cNamespaces(this, new cNamespaceName[] { new cNamespaceName("", lDelimiter) }, null, null);
                            mSynchroniser.InvokePropertyChanged(nameof(Namespaces), lContext);
                        }

                        mInbox = new cMailbox(this, lSession.GetMailboxHandle(new cMailboxName(cMailboxName.InboxString, lDelimiter)));
                        mSynchroniser.InvokePropertyChanged(nameof(Inbox), lContext);
                    }

                    // wait for id to complete
                    if (lIdTask != null)
                    {
                        await lIdTask.ConfigureAwait(false);
                    }

                    // initialised (namespaces set, inbox available, id available (if server supports it); user may now issue commands)
                    lSession.SetInitialised(lContext);
                }
                catch when(lSession.ConnectionState != eConnectionState.disconnected)
                {
                    lSession.Disconnect(lContext);
                    throw;
                }
            }
        }
Example #15
0
            public async Task <List <iMailboxHandle> > LSubAsync(cMethodControl pMC, string pListMailbox, char?pDelimiter, cMailboxPathPattern pPattern, bool pHasSubscribedChildren, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(LSubAsync), pMC, pListMailbox, pDelimiter, pPattern, pHasSubscribedChildren);

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

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

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

                    lBuilder.Add(kLSubCommandPart, lListMailboxCommandPart);

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

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

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

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, 0, lContext);
                    }
                    throw new cProtocolErrorException(lResult, 0, lContext);
                }
            }
Example #16
0
        private async Task ZRequestAsync(iMailboxHandle pMailboxHandle, fMailboxCacheDataSets pDataSets, cTrace.cContext pParentContext)
        {
            var lContext = pParentContext.NewMethod(nameof(cIMAPClient), nameof(ZRequestAsync), pMailboxHandle, pDataSets);

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

            var lSession = mSession;

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

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

            if (pMailboxHandle.MailboxName == null)
            {
                throw new ArgumentOutOfRangeException(nameof(pMailboxHandle));
            }
            if (pDataSets == 0)
            {
                return;
            }

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

                if (pDataSets == fMailboxCacheDataSets.status)
                {
                    await lSession.StatusAsync(lMC, pMailboxHandle, lContext).ConfigureAwait(false);

                    return;
                }

                string lListMailbox          = pMailboxHandle.MailboxName.Path.Replace('*', '%');
                cMailboxPathPattern lPattern = new cMailboxPathPattern(pMailboxHandle.MailboxName.Path, string.Empty, pMailboxHandle.MailboxName.Delimiter);

                var  lCapabilities = lSession.Capabilities;
                bool lList         = (pDataSets & fMailboxCacheDataSets.list) != 0;
                bool lLSub         = (pDataSets & fMailboxCacheDataSets.lsub) != 0;
                bool lStatus       = (pDataSets & fMailboxCacheDataSets.status) != 0;
                bool lListStatus   = lStatus && lCapabilities.ListStatus;

                List <Task> lTasks = new List <Task>();

                if (lCapabilities.ListExtended && (lList || (lLSub && (mMailboxReferrals || lListStatus))))
                {
                    if (lList)
                    {
                        lTasks.Add(lSession.ListExtendedAsync(lMC, eListExtendedSelect.exists, mMailboxReferrals, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, lListStatus, lContext));
                        if (lLSub)
                        {
                            lTasks.Add(lSession.ListExtendedAsync(lMC, eListExtendedSelect.subscribed, mMailboxReferrals, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, false, lContext));
                        }
                    }
                    else if (lLSub)
                    {
                        lTasks.Add(lSession.ListExtendedAsync(lMC, eListExtendedSelect.subscribed, mMailboxReferrals, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, lListStatus, lContext));
                    }

                    if (lStatus && !lListStatus)
                    {
                        lTasks.Add(lSession.StatusAsync(lMC, pMailboxHandle, lContext));
                    }
                }
                else
                {
                    if (lList)
                    {
                        if (mMailboxReferrals && lCapabilities.MailboxReferrals)
                        {
                            lTasks.Add(lSession.RListAsync(lMC, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, lContext));
                        }
                        else
                        {
                            lTasks.Add(lSession.ListMailboxesAsync(lMC, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, lContext));
                        }
                    }

                    if (lLSub)
                    {
                        if (mMailboxReferrals && lCapabilities.MailboxReferrals)
                        {
                            lTasks.Add(lSession.RLSubAsync(lMC, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, false, lContext));
                        }
                        else
                        {
                            lTasks.Add(lSession.LSubAsync(lMC, lListMailbox, pMailboxHandle.MailboxName.Delimiter, lPattern, false, lContext));
                        }
                    }

                    if (lStatus)
                    {
                        lTasks.Add(lSession.StatusAsync(lMC, pMailboxHandle, lContext));
                    }
                }

                await Task.WhenAll(lTasks).ConfigureAwait(false);
            }
        }
Example #17
0
 public cCommandHookLSub(cMailboxCache pCache, cMailboxPathPattern pPattern, bool pHasSubscribedChildren)
 {
     mCache   = pCache;
     mPattern = pPattern;
     mHasSubscribedChildren = pHasSubscribedChildren;
 }
Example #18
0
            public async Task <List <iMailboxHandle> > ListExtendedAsync(cMethodControl pMC, eListExtendedSelect pSelect, bool pRemote, string pListMailbox, char?pDelimiter, cMailboxPathPattern pPattern, bool pStatus, cTrace.cContext pParentContext)
            {
                var lContext = pParentContext.NewMethod(nameof(cSession), nameof(ListExtendedAsync), pMC, pSelect, pRemote, pListMailbox, pDelimiter, pPattern, pStatus);

                // caller needs to determine if list status is supported

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

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

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

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

                    lBuilder.BeginList(eListBracketing.none);

                    lBuilder.Add(kListExtendedCommandPartList);

                    lBuilder.BeginList(eListBracketing.ifany);

                    if (pSelect == eListExtendedSelect.subscribed)
                    {
                        lBuilder.Add(kListExtendedCommandPartSubscribed);
                    }
                    else if (pSelect == eListExtendedSelect.subscribedrecursive)
                    {
                        lBuilder.Add(kListExtendedCommandPartSubscribed);
                        lBuilder.Add(kListExtendedCommandPartRecursiveMatch);
                    }

                    if (pRemote)
                    {
                        lBuilder.Add(kListExtendedCommandPartRemote);
                    }

                    lBuilder.EndList();

                    lBuilder.Add(kListExtendedCommandPartMailbox);
                    lBuilder.Add(lListMailboxCommandPart);

                    // return options

                    lBuilder.BeginList(eListBracketing.ifany, kListExtendedCommandPartReturnSpace);

                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.subscribed) != 0)
                    {
                        lBuilder.Add(kListExtendedCommandPartSubscribed);
                    }
                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.children) != 0)
                    {
                        lBuilder.Add(kListExtendedCommandPartChildren);
                    }
                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.specialuse) != 0 && _Capabilities.SpecialUse)
                    {
                        lBuilder.Add(kListExtendedCommandPartSpecialUse);
                    }

                    if (pStatus)
                    {
                        lBuilder.Add(kListExtendedCommandPartStatus);
                        lBuilder.AddStatusAttributes(mStatusAttributes);
                    }

                    lBuilder.EndList();
                    lBuilder.EndList();

                    var lHook = new cListExtendedCommandHook(mMailboxCache, pSelect, pPattern, pStatus);
                    lBuilder.Add(lHook);

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

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

                    fCapabilities lTryIgnoring = 0;

                    if ((mMailboxCacheDataItems & fMailboxCacheDataItems.specialuse) != 0 && _Capabilities.SpecialUse)
                    {
                        lTryIgnoring |= fCapabilities.specialuse;
                    }
                    if (pStatus)
                    {
                        lTryIgnoring |= fCapabilities.liststatus;
                    }
                    if (lTryIgnoring == 0)
                    {
                        lTryIgnoring |= fCapabilities.listextended;
                    }

                    if (lResult.ResultType == eCommandResultType.no)
                    {
                        throw new cUnsuccessfulCompletionException(lResult.ResponseText, lTryIgnoring, lContext);
                    }
                    throw new cProtocolErrorException(lResult, lTryIgnoring, lContext);
                }
            }