Exim4 smarthost

Use sendmail on your VPS and relay outbound email through Sendy with Exim4.

Keep using sendmail on your VPS. Configure Exim4 to relay outbound email through Sendy, and your applications and scripts can keep submitting mail through the local /usr/sbin/sendmail interface. Configure Sendy’s SMTP credentials once in Exim4 instead of adding them to each application.

Exim queues local submissions and relays nonlocal mail to Sendy over STARTTLS on port 2525. These steps use Debian and Ubuntu’s split configuration. Your applications still need valid message headers and sender addresses on a verified domain; the prerequisites cover sender rewriting for system mail.

Before you begin

  • Verify a sending domain, create an API key, and have available email credits in your Sendy account.
  • Use an installed Exim4 server with TLS support, the ca-certificates package, and root access to its configuration. Allow outbound TCP connections on port 2525.
  • In /etc/exim4/update-exim4.conf.conf, use dc_use_split_config='true'. These paths do not apply if you maintain a standalone /etc/exim4/exim4.conf, which takes precedence over generated configuration.

Sendy requires a verified domain for both the message’s From header and any nonempty envelope sender. Configure your applications accordingly. System mail from root@hostname needs sender rewriting; Debian’s /etc/email-addresses can rewrite local users’ addresses.

  1. Store the API key

    Create /etc/exim4/sendy-api-key with a privileged editor. Put your full API key, including snd_key_, on its own line without quotes. Restrict access:

    API key file permissions · terminal
    sudo chown root:Debian-exim /etc/exim4/sendy-api-key
    sudo chmod 0640 /etc/exim4/sendy-api-key

    The authenticator reads this file at delivery time. You do not need to put the key in a configuration fragment or a shell command.

  2. Route nonlocal mail to Sendy

    Create /etc/exim4/conf.d/router/150_local_sendy with this router:

    150_local_sendy · Exim router
    sendy_smarthost:
      driver = manualroute
      domains = ! +local_domains
      transport = sendy_smtp
      route_list = * smtp.usesendy.com byname
      no_more

    Keep your existing local_domains list. With custom routers, place this router before any router that delivers nonlocal mail directly. Local delivery remains with your existing local routers.

  3. Require authenticated TLS delivery

    Create /etc/exim4/conf.d/transport/30_local_sendy with this transport:

    30_local_sendy · Exim transport
    sendy_smtp:
      driver = smtp
      port = 2525
      hosts_require_auth = *
      hosts_require_tls = *
      tls_verify_hosts = *
      tls_verify_cert_hostnames = *
      tls_verify_certificates = /etc/ssl/certs/ca-certificates.crt

    Exim must authenticate and verify the server’s certificate and hostname. A TLS or authentication failure defers delivery instead of falling back to an unencrypted session.

  4. Add client authentication

    Create /etc/exim4/conf.d/auth/00_local_sendy with this authenticator:

    00_local_sendy · Exim authentication
    sendy_login:
      driver = plaintext
      public_name = LOGIN
      client_condition = ${if and{\
        {eq{$host}{smtp.usesendy.com}}\
        {def:tls_out_cipher}}{yes}{no}}
      hide client_send = : apikey : ${readfile{/etc/exim4/sendy-api-key}{}}

    Use the literal username apikey. This client-only LOGIN authenticator is restricted to Sendy’s hostname and an encrypted connection. Keep it before other LOGIN client authenticators, and keep the backslashes that continue the condition across lines. The file reader removes the API key file’s line ending.

  5. Check and apply the configuration

    Check the generated configuration first. If the check succeeds, restart Exim4 and test routing to an address outside your local domains:

    Validate, apply, and inspect routing · terminal
    sudo update-exim4.conf --check &&
      sudo invoke-rc.d exim4 restart &&
      sudo exim4 -bt [email protected]

    Replace [email protected] with your test recipient. The routing output should identify sendy_smarthost, sendy_smtp, and Sendy’s SMTP host. This routing test does not send an email or test authentication.

  6. Submit a test email

    Save this as email.eml. Replace the sender with an address on your verified domain and the recipient with an external test address:

    email.eml
    From: My App <[email protected]>
    To: [email protected]
    Subject: Welcome
    MIME-Version: 1.0
    Content-Type: text/html; charset=UTF-8
    Content-Transfer-Encoding: quoted-printable
    
    <h1>Welcome</h1><p>Your account is ready.</p>

    Submit it through Exim. Replace the envelope sender with the same verified sender:

    Submit through Exim4 · terminal
    sudo /usr/sbin/sendmail -f [email protected] -t < email.eml

    This test runs as root so Exim accepts the explicit envelope sender without adding a Sender header. For application submissions, account for Exim’s local sender policy: untrusted users can have their envelope sender replaced or a Sender header added. Sendy does not accept Sender headers; see SMTP message requirements.

Check the result

Open Emails to confirm Sendy queued the message and follow its delivery status. A successful local submission only confirms that Exim accepted the email. If it has not reached Sendy, inspect the local queue:

Inspect the Exim4 queue · terminal
sudo exim4 -bp

Check Exim’s main log, normally /var/log/exim4/mainlog on Debian and Ubuntu. Review TLS trust, API-key permissions, sender verification, and credits before resubmitting. See SMTP errors for Sendy’s responses.

Configuration references: Exim manualroute router, SMTP transport, client authentication, and Debian configuration generation.