class Net::IMAP::SASL::AuthenticationExchange


def authenticate(…) = sasl_adapter.authenticate(…)
Likewise, ClientAdapter#authenticate delegates to #authenticate:
end
SASL::AuthenticationExchange.authenticate(sasl_adapter, …)
def authenticate(…)
As a convenience, ::authenticate combines ::build and #authenticate:
end
.authenticate
SASL::AuthenticationExchange.build(sasl_adapter, …)
def authenticate(…)
Or delegate creation of the authenticator to ::build:
def sasl_adapter = MyClientAdapter.new(self, &method(:send_command))
private
end
).authenticate
sasl_adapter, mechanism, authenticator
SASL::AuthenticationExchange.new(
authenticator = SASL.authenticator(mechanism, …)
def authenticate(mechanism, …)
authenticator:
Create an AuthenticationExchange from a client adapter and a mechanism
TODO: use with more clients, to verify the API can accommodate them.
TODO: raise an error if the command succeeds after being canceled.
TODO: catch exceptions in #process and send #cancel_response.
This API is experimental, and may change.

def self.authenticate(...) build(...).authenticate end

Convenience method for build(...).authenticate
def self.authenticate(...) build(...).authenticate end

def self.build(client, mechanism, *args, sasl_ir: true, **kwargs, &block)

Use +registry+ to override the global Authenticators registry.
def self.build(client, mechanism, *args, sasl_ir: true, **kwargs, &block)
  authenticator = SASL.authenticator(mechanism, *args, **kwargs, &block)
  new(client, mechanism, authenticator, sasl_ir: sasl_ir)
end

def authenticate

drop the connection.
exception. Any exceptions other than those in RESPONSE_ERRORS will
using #authenticator. Authentication failures will raise an
Call #authenticate to execute an authentication exchange for #client
def authenticate
  client.run_command(mechanism, initial_response) { process _1 }
    .tap { raise AuthenticationIncomplete, _1 unless done? }
rescue *client.response_errors
  raise # but don't drop the connection
rescue
  client.drop_connection
  raise
rescue Exception # rubocop:disable Lint/RescueException
  client.drop_connection!
  raise
end

def done?

def done?
  authenticator.respond_to?(:done?) ? authenticator.done? : @processed
end

def initial_response

def initial_response
  return unless send_initial_response?
  client.encode_ir authenticator.process nil
end

def initialize(client, mechanism, authenticator, sasl_ir: true)

def initialize(client, mechanism, authenticator, sasl_ir: true)
  @client = client
  @mechanism = -mechanism.to_s.upcase.tr(?_, ?-)
  @authenticator = authenticator
  @sasl_ir = sasl_ir
  @processed = false
end

def process(challenge)

def process(challenge)
  client.encode authenticator.process client.decode challenge
ensure
  @processed = true
end

def send_initial_response?

def send_initial_response?
  @sasl_ir &&
    authenticator.respond_to?(:initial_response?) &&
    authenticator.initial_response? &&
    client.sasl_ir_capable? &&
    client.auth_capable?(mechanism)
end