def _login(self, caps, username, password):
        """
        Continue the process of logging in to the server.

        This callback function runs after the server capabilities are received.

        If the server provided a challenge in the greeting, proceed with an
        APOP login.  Otherwise, if the server and the transport support
        encrypted communication, try to switch to TLS and then complete
        the login process with the L{_loginTLS} callback function.  Otherwise,
        if insecure authentication is allowed, do a plaintext login.
        Otherwise, fail with an L{InsecureAuthenticationDisallowed} error.

        @type caps: L{dict} mapping L{bytes} to L{list} of L{bytes} and/or
            L{bytes} to L{None}
        @param caps: The server capabilities.

        @type username: L{bytes}
        @param username: The username with which to log in.

        @type password: L{bytes}
        @param password: The password with which to log in.

        @rtype: L{Deferred <defer.Deferred>} which successfully fires with
            L{bytes}
        @return: A deferred which fires when the login process is complete.
            On a successful login, it returns the server's response minus the
            status indicator.
        """
        if self.serverChallenge is not None:
            return self._apop(username, password, self.serverChallenge)

        tryTLS = b'STLS' in caps

        # If our transport supports switching to TLS, we might want to
        # try to switch to TLS.
        tlsableTransport = interfaces.ITLSTransport(self.transport, None) is not None

        # If our transport is not already using TLS, we might want to
        # try to switch to TLS.
        nontlsTransport = interfaces.ISSLTransport(self.transport, None) is None

        if not self.startedTLS and tryTLS and tlsableTransport and nontlsTransport:
            d = self.startTLS()

            d.addCallback(self._loginTLS, username, password)
            return d

        elif self.startedTLS or not nontlsTransport or self.allowInsecureLogin:
            return self._plaintext(username, password)
        else:
            return defer.fail(InsecureAuthenticationDisallowed())

        Continue the process of logging in to the server.

        This callback function runs after the server capabilities are received.

        If the server provided a challenge in the greeting, proceed with an
        APOP login.  Otherwise, if the server and the transport support
        encrypted communication, try to switch to TLS and then complete
        the login process with the L{_loginTLS} callback function.  Otherwise,
        if insecure authentication is allowed, do a plaintext login.
        Otherwise, fail with an L{InsecureAuthenticationDisallowed} error.

        @type caps: L{dict} mapping L{bytes} to L{list} of L{bytes} and/or
            L{bytes} to L{None}
        @param caps: The server capabilities.

        @type username: L{bytes}
        @param username: The username with which to log in.

        @type password: L{bytes}
        @param password: The password with which to log in.

        @rtype: L{Deferred <defer.Deferred>} which successfully fires with
            L{bytes}
        @return: A deferred which fires when the login process is complete.
            On a successful login, it returns the server's response minus the
            status indicator.
        
stackoverflow/venv/lib/python3.6/site-packages/twisted/mail/pop3client.py