<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def discover(email, credentials):
 """ Performs the autodiscover dance and returns the primary SMTP address of the account and a Protocol on success. The autodiscover and EWS server might not be the same, so we use a different Protocol to do the autodiscover request, and return a hopefully-cached Protocol to the callee. """

    log.debug('Attempting autodiscover on email %s', email)
    if not isinstance(credentials, Credentials):
        raise ValueError("'credentials' %r must be a Credentials instance" % credentials)
    domain = get_domain(email)
    # We may be using multiple different credentials and changing our minds on TLS verification. This key combination
    # should be safe.
    autodiscover_key = (domain, credentials)
    # Use lock to guard against multiple threads competing to cache information
    log.debug('Waiting for _autodiscover_cache_lock')
    with _autodiscover_cache_lock:
        # Don't recurse while holding the lock!
        log.debug('_autodiscover_cache_lock acquired')
        if autodiscover_key in _autodiscover_cache:
            protocol = _autodiscover_cache[autodiscover_key]
            if not isinstance(protocol, AutodiscoverProtocol):
                raise ValueError('Unexpected autodiscover cache contents: %s' % protocol)
            log.debug('Cache hit for domain %s credentials %s: %s', domain, credentials, protocol.server)
            try:
                # This is the main path when the cache is primed
                return _autodiscover_quick(credentials=credentials, email=email, protocol=protocol)
            except AutoDiscoverFailed:
                # Autodiscover no longer works with this domain. Clear cache and try again after releasing the lock
                del _autodiscover_cache[autodiscover_key]
            except AutoDiscoverRedirect as e:
                log.debug('%s redirects to %s', email, e.redirect_email)
                if email.lower() == e.redirect_email.lower():
                    raise_from(AutoDiscoverCircularRedirect('Redirect to same email address: %s' % email), None)
                # Start over with the new email address after releasing the lock
                email = e.redirect_email
        else:
            log.debug('Cache miss for domain %s credentials %s', domain, credentials)
            log.debug('Cache contents: %s', _autodiscover_cache)
            try:
                # This eventually fills the cache in _autodiscover_hostname
                return _try_autodiscover(hostname=domain, credentials=credentials, email=email)
            except AutoDiscoverRedirect as e:
                if email.lower() == e.redirect_email.lower():
                    raise_from(AutoDiscoverCircularRedirect('Redirect to same email address: %s' % email), None)
                log.debug('%s redirects to %s', email, e.redirect_email)
                # Start over with the new email address after releasing the lock
                email = e.redirect_email
    log.debug('Released autodiscover_cache_lock')
    # We fell out of the with statement, so either cache was filled by someone else, or autodiscover redirected us to
    # another email address. Start over after releasing the lock.
    return discover(email=email, credentials=credentials)