# smtp_server_auth_plain

```lua
kumo.on(
  'smtp_server_auth_plain',
  function(authz, authc, password, conn_meta) end
)
```

Called by the ESMTP server in response to the client issuing an `"AUTH PLAIN"`
authentication attempt.

KumoMTA will only allow `AUTH PLAIN` once STARTTLS has been successfully
enabled for the session.

At the time of writing KumoMTA doesn't provide a general authentication
solution, but through the use of this callback, you have some flexibility.

The event handler receives the following parameters:

* *authz* - the *authorization identity* which the client wishes to act as
* *authc* - the *authentication identity* which identifies the client for the
  purposes of validating who the client claims to be.  *authc* is paired
  with the *password* parameter.
* *password* - the password which belongs to the claimed *authc*
* *conn_meta* - represents the connection metadata and
    can be used to share state between the various SMTP listener
    event handlers. See [Connection Metadata](../connectionmeta.md)
    for more information.

{{since('2023.08.22-4d895015', indent=True)}}
    The *conn_metadata* parameter is new as of this release.

Note that [PLAIN SASL](https://www.rfc-editor.org/rfc/rfc4616) allows for *authz*
to be empty.  KumoMTA will assume the same value as *authc* in that case, so
this event will always be triggered with that value.

The SMTP server expects the event handler to return a bool value; if it returns
true then it considers the credentials to be valid and will associated the claimed
identities with the session, and yield an SMTP `235` successful authentication
response to the client.  The *authz* and *authc* parameters will be set
in the message meta object as `"authz_id"` and `"authn_id"` respectively.

If it returns false then the authentication attempt is considered to have failed
and will yield an SMTP `535` failed authentication response to the client.

This example shows how to implement a very simple inline password database
using a lua table:

```lua
-- Use this to lookup and confirm a user/password credential
kumo.on('smtp_server_auth_plain', function(authz, authc, password, conn_meta)
  -- This is just an example of how to populate the return value,
  -- not a recommended way to handle passwords in production!
  -- In particular, it is an absolutely terrible idea to hard code
  -- a password here in plain text!
  local password_database = {
    ['daniel'] = 'tiger',
  }
  if password == '' then
    return false
  end
  return password_database[authc] == password
end)
```

## Returning Group and identity Information

{{since('2026.03.04-bb93ecb1')}}

Rather than just returning a boolean to indicate whether authentication was
successful, you may now return an [AuthInfo](../kumo.aaa/auth_info.md) object
holding additional information.  Here's an expanded version of the example
above that shows how you can return group membership:

```lua
-- This is just an example of how to populate the return value,
-- not a recommended way to handle passwords in production!
-- In particular, it is an absolutely terrible idea to hard code
-- a password here in plain text!

local password_database = {
  ['daniel'] = {
    password = 'tiger',
    groups = { 'group1', 'group2' },
  },
}

kumo.on('smtp_server_auth_plain', function(authz, authc, password)
  local entry = password_database[authc]
  if not entry then
    return false
  end
  if entry.password ~= password then
    return false
  end

  -- Return an AuthInfo that lists out the identity and group
  -- membership
  return {
    identities = {
      { identity = authz, context = 'SmtpAuthPlainAuthorization' },
      { identity = authc, context = 'SmtpAuthPlainAuthentication' },
    },
    groups = entry.groups,
  }
end)
```
