# DirectAdmin Exim MailBaby Relay: Smarthost Setup

Source: https://srvscripts.com/guides/directadmin-exim-mailbaby-relay/
Updated: 2026-10-03
Publisher: srvScripts (https://srvscripts.com/)

DirectAdmin ships a versioned `exim.conf` that CustomBuild replaces on every Exim update, so anything you write into it directly is lost at the next `da build exim`. The supported mechanism is the set of `.pre.conf` and `.post.conf` files in `/etc/`, which are included before or after the corresponding section of the main configuration. This tutorial uses three of them to send all remote mail through MailBaby with authentication and TLS. It assumes DirectAdmin 1.70x with Exim 4.100 and a MailBaby account from the InterServer portal.

In short: Create three override files: /etc/exim.authenticators.post.conf with a plaintext LOGIN authenticator holding your mbXXXXX credentials, /etc/exim.transports.pre.conf with two smtp transports that enforce hosts_require_auth = * and…

**Short answer:** Create three override files: `/etc/exim.authenticators.post.conf` with a `plaintext` LOGIN authenticator holding your `mbXXXXX` credentials, `/etc/exim.transports.pre.conf` with two `smtp` transports that enforce `hosts_require_auth = *` and `hosts_require_tls = *` and sign with the domain’s `/etc/virtual/<domain>/dkim.private.key` (one of them rewriting the return path with SRS for forwards), and `/etc/exim.routers.pre.conf` with `manualroute` routers pointing non-local domains at `relay.mailbaby.net::25` with `no_more`. Leave out the old `check_limits` condition on DirectAdmin 1.702 and later, then run `exim -bV` and restart Exim.

## Authenticator

Create `/etc/exim.authenticators.post.conf`. The `post` file is included after DirectAdmin’s own authenticators, which is what you want; the client authenticator only needs to exist, its position is irrelevant.

```
auth_login:
  driver = plaintext
  public_name = LOGIN
  hide client_send = ": mb12345 : YOUR_PASSWORD"
```

The username is the bare account name with no `@domain`. Keep the leading colon: LOGIN is a two-step challenge and the empty first field tells Exim to wait for the first prompt.

## Transports

Create `/etc/exim.transports.pre.conf` with two transports. One handles ordinary outbound mail; the other handles forwarded messages and rewrites the envelope sender with SRS so the destination’s SPF check passes and MailBaby’s strict forwarding rules are not triggered.

```
auth_relay:
  driver = smtp
  port = 25
  hosts_require_auth = *
  hosts_require_tls = *
  tls_tempfail_tryclear = false
  dkim_domain = ${lc:${domain:$h_from:}}
  dkim_selector = x
  dkim_private_key = ${if exists{/etc/virtual/${dkim_domain}/dkim.private.key}{/etc/virtual/${dkim_domain}/dkim.private.key}{0}}
  dkim_canon = relaxed

auth_relay_forward:
  driver = smtp
  port = 25
  hosts_require_auth = *
  hosts_require_tls = *
  tls_tempfail_tryclear = false
  return_path = ${if eq{$sender_address_domain}{}{}{SRS0=${srs_encode{SRS_SECRET}{$sender_address_local_part}{$sender_address_domain}}@$domain}}
  dkim_domain = ${lc:${domain:$h_from:}}
  dkim_selector = x
  dkim_private_key = ${if exists{/etc/virtual/${dkim_domain}/dkim.private.key}{/etc/virtual/${dkim_domain}/dkim.private.key}{0}}
```

DirectAdmin stores per-domain DKIM keys under `/etc/virtual/<domain>/` with selector `x`, so the transport signs with the customer’s key whenever one exists. Signing locally is the recommended arrangement; MailBaby passes the signature through, and without it recipients see MailBaby’s transport signature and “via mailbaby.net” instead. If your build already defines an SRS secret macro, reuse it; otherwise define `SRS_SECRET` at the top of `/etc/exim.variables.conf.custom` with a long random string. `hosts_require_auth` and `hosts_require_tls` are mandatory: MailBaby refuses unauthenticated and unencrypted sessions.

## Routers

Create `/etc/exim.routers.pre.conf`. Because it is a `pre` file, these routers run before DirectAdmin’s own `lookuphost` router, which is exactly what a smarthost needs. The first router catches forwards; the second catches everything else that is not local.

```
smart_route_forward:
  driver = manualroute
  domains = ! +local_domains
  condition = ${if and{{def:h_X-Forwarded-For:}{eq{$original_domain}{$domain}}}{no}{yes}}
  senders = : *@+local_domains
  transport = auth_relay_forward
  route_list = * relay.mailbaby.net::25
  no_more

smart_route:
  driver = manualroute
  domains = ! +local_domains
  transport = auth_relay
  route_list = * relay.mailbaby.net::25
  no_more
```

Older DirectAdmin examples include `condition = "${perl{check_limits}}"` on these routers to enforce per-user send limits. From DirectAdmin 1.702 the limit check moved and that Perl function is no longer present in the default configuration, so leave the line out; keeping it produces “unknown Perl subroutine” errors and Exim refuses to start. Per-user limits are still enforced by DirectAdmin’s own ACL.

The `no_more` directive is important: if MailBaby defers or rejects a message, Exim must not fall back to direct delivery from your IP, which would bypass SPF and leak the very mail you are trying to filter.

## Apply and restart

```
exim -bV -C /etc/exim.conf
systemctl restart exim
systemctl status exim --no-pager
```

`exim -bV` exits non-zero and prints the line number on any syntax error. Fix it before restarting; a broken Exim on a shared server means no mail moves at all.

DirectAdmin’s `FORCED_MX_DNS_CHECK` and forwarder loop protections introduced in 1.693 and 1.703 are unaffected by this change; they act on inbound routing. If you see forwarded mail misbehaving, check [the forwarder loop guide](/guides/directadmin-mail-delivery-problems/) first.

## Verify

Send a message from a DirectAdmin mailbox to an external address and watch `/var/log/exim/mainlog`:

```
tail -f /var/log/exim/mainlog
```

A working delivery shows `=> recipient@example.org R=smart_route T=auth_relay H=relay.mailbaby.net [IP]:25 X=TLS1.3 ... A=auth_login`. If `A=auth_login` is missing, authentication did not happen, usually because `hosts_require_auth` was misspelled or the authenticator file was not picked up. Confirm the file is being included with `exim -bP authenticators | grep auth_login`. Check the received message’s headers for `dkim=pass` on the customer domain, and confirm the message appears in the InterServer portal log. The common pitfall is running `da build exim_conf` later and assuming it overwrote the relay: it does not, but it does regenerate `/etc/exim.conf`, so re-run `exim -bV` after every CustomBuild mail update to make sure the includes still parse cleanly.

## DirectAdmin Exim MailBaby relay at a glance

**Official documentation:** [Exim documentation](https://www.exim.org/docs.html), [DirectAdmin documentation](https://docs.directadmin.com/), [RFC 5321 (SMTP)](https://www.rfc-editor.org/rfc/rfc5321).

**Related guides:** [Warm up a new mail server IP or sending domain without landing in spam](https://srvscripts.com/guides/warm-up-new-mail-server-ip-domain/) · [Newsletters and mailing lists through MailBaby: staying under the 6,000/hour limit and out of spam folders](https://srvscripts.com/guides/mailbaby-newsletter-sending-limit/) · [MailBaby DKIM transport signing explained: why some mail shows “via mailbaby.net”](https://srvscripts.com/guides/mailbaby-dkim-transport-signing/).

## Frequently asked questions

### Will da build exim or exim_conf overwrite the MailBaby relay settings?

No. CustomBuild replaces `/etc/exim.conf` but leaves the `.pre.conf` and `.post.conf` include files alone, which is why the relay lives in `/etc/exim.authenticators.post.conf`, `/etc/exim.transports.pre.conf` and `/etc/exim.routers.pre.conf`. Run `exim -bV` after each mail rebuild to confirm the includes still parse.

### Why does Exim fail to start with “unknown Perl subroutine check_limits” on DirectAdmin?

Older relay examples put `condition = "${perl{check_limits}}"` on the smarthost routers, but from DirectAdmin 1.702 that function no longer exists in the default configuration. Remove the line; per-user send limits are still enforced by DirectAdmin’s own ACL.

### Does DirectAdmin’s DKIM still work when mail goes through MailBaby?

Yes, as long as the transport carries the `dkim_domain`, `dkim_selector = x` and `dkim_private_key` options pointing at `/etc/virtual/<domain>/dkim.private.key`. MailBaby passes the signature through untouched; without local signing, recipients see MailBaby’s transport signature and a “via mailbaby.net” label instead.
