DBMail with Exim

DBMail is a Message Delivery Agent and receives messages from any of a Message Transfer Agent, Message Submission Agent or Message User Agent. These can be delivered directly using dbmail-deliver or using any of the protocols LMTP, IMAP or POP. Exim can deliver email using dbmail-lmtp or dbmail-deliver. This article, together with the example template shows how to integrate DBMail with Exim.

DBMail clients

Exim and DBMail are natural partners and the following example, found at https://github.com/dbmail/dbmail/blob/main/contrib/exim-dbmail-configure, uses dbmail-deliver to deliver incoming email to a users inbox. If a user has sieve scripts then dbmail will use them to ensure the email is delivered in the right location.

Exim and DBMail are natural partners. This article can be used with the exim config template exim-dbmail-configure to use Exim as the SMTP Message Transfer Agent (MTA) to deliver and store emails in DBMail as the Message Delivery Agent (MDA) for retrieval by any IMAP client. Both Exim and DBMail speak SQL and LDAP and both are included in this article and the template.

General settings

Exim defines various things such as servers and queries at the beginning of the configuration file, then access control lists for incoming smtp email, routers for how email should be handled, transports for how email should be delivered, then authentication.

Although straightforward, there are many configuration choices for email and organisations so this readme and the exim-dbmail-configuration template can only be a guide. As with any critical infrastructure, testing is essential.

DBMail can use PostgreSQL, MySQL and Oracle. The template uses sql authentication with PostgreSQL so if you use MySQL or Oracle change quote_pgsql to quote_mysql or quote_oracle. Also lookups ${lookup pgsql{}} ${lookup mysql{}} ${lookup oracle{}}. For LDAP uncomment the various sections in the template and comment out sql applying any changes for your organisation.

PostgreSQL

hide pgsql_servers = host/database/user/password

MySQL

hide mysql_servers = host/database/user/password

Oracle

hide oracle_servers = oracle.plc.example//user/password

LDAP

ldap_default_servers = example.com::389

The LDAP lookup needs configuring for your organisation

ALIAS_LDAP_VIRT_USER = \
  user="uid=lookup,dc=example,dc=com" \
  pass="password" \
  ldap:///ou=users,dc=example,dc=com?uid?sub?(mail=${quote_ldap:$local_part}@${quote_ldap:$domain})} \
  {$value}fail

It's essential to know who is authorised to send mail and when receiving where those emails should go. DBMail uses either SQL or LDAP for authentication and those are available to Exim.

Macro definitions

Exim uses macros for SQL queries, this template doesn't use them for LDAP. The three SQL queries to identify acceptable emails, domains for outgoing email and user authentication are:

  • ALIAS_VIRT_USER for identifying valid emails;
  • ALIAS_VIRT_DOMAIN for identifying domains;
  • ALIAS_SERVER_AUTH_LOGIN for authenticating users.

For ldap:

  • ALIAS_LDAP_VIRT_USER for identifying valid emails;
  • ALIAS_LDAP_SERVER_AUTH_LOGIN for authenticating users.

Domain lookup can be either the SQL lookup or as LDAP is less flexible, simply revert to one of the exim suggestions:

# Define local_domains
domainlist local_domains = my.first.domain : my.second.domain
# Use local_domains
domains = +local_domains

Incoming mail

When exim receives mail, it checks with various ACLs. If you're using DBMail's sql authenticator, then it can check against known aliases:

require message = relay not permitted
      domains = ${lookup pgsql{ALIAS_VIRT_DOMAIN}}

Ldap is less flexible so either revert to exim suggestions or you may prefer a local_domains sql table.

The local router checks if it can receive mail for a user and forwards it to the transport dbmail_delivery. Simply swap the condition for sql/ldap.

localuser:
  driver = accept
  condition = ${lookup pgsql{ALIAS_VIRT_USER}}
  #condition = hide ${lookup ldap{ALIAS_LDAP_VIRT_USER}}
  transport = dbmail_delivery
  cannot_route_message = Unknown user

Delivering email

The transport dbmail_delivery calls dbmail-deliver to deliver the email. You may need to change the user and path depending on your distribution.

dbmail_delivery:
  driver = pipe
  command = "/usr/local/sbin/dbmail-deliver -d ${local_part}\@$domain"
  return_fail_output
  user = mail

If you have large volumes of mail you may prefer to have them delivered via lmtp.

dbmail_delivery:
    driver = smtp
    protocol = lmtp
    hosts = localhost
    allow_localhost
    return_path_add

Authentication

Exim can authenticate users who submit email for forwarding with the same sql or ldap credentials as DBMail.

dbmail_login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = Username:: : Password::
  server_condition = ${lookup pgsql{ALIAS_SERVER_AUTH_LOGIN}}
  server_set_id = uid=$auth1
dbmail_login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = Username:: : Password::
  server_condition = ${if and {{ \
    !eq{}{$auth1} }{ \
    ldapauth{user="uid=${quote_ldap_dn:$auth1},dc=example,dc=com" \
    pass=${quote:$auth2} \
    ldap://example.com} }} }
  server_set_id = uid=$auth1

The exim-dbmail-configure template is kindly sponsored by XML Team llp.

DBMail is sponsored by