def __authenticate(self, login, password, authz_id=b"", authmech=None):
        """AUTHENTICATE command

        Actually, it is just a wrapper to the real commands (one by
        mechanism). We try all supported mechanisms (from the
        strongest to the weakest) until we find one supported by the
        server.

        Then we try to authenticate (only once).

        :param login: username
        :param password: clear password
        :param authz_id: authorization ID
        :param authmech: prefered authentication mechanism
        :return: True on success, False otherwise
        """
        if "SASL" not in self.__capabilities:
            raise Error("SASL not supported by the server")
        srv_mechanisms = self.get_sasl_mechanisms()

        if authmech is None or authmech not in SUPPORTED_AUTH_MECHS:
            mech_list = SUPPORTED_AUTH_MECHS
        else:
            mech_list = [authmech]

        for mech in mech_list:
            if mech not in srv_mechanisms:
                continue
            mech = mech.lower().replace("-", "_")
            auth_method = getattr(self, "_%s_authentication" % mech)
            if auth_method(login, password, authz_id):
                self.authenticated = True
                return True
            return False

        self.errmsg = b"No suitable mechanism found"
        return False
AUTHENTICATE command

        Actually, it is just a wrapper to the real commands (one by
        mechanism). We try all supported mechanisms (from the
        strongest to the weakest) until we find one supported by the
        server.

        Then we try to authenticate (only once).

        :param login: username
        :param password: clear password
        :param authz_id: authorization ID
        :param authmech: prefered authentication mechanism
        :return: True on success, False otherwise