Skip to content

Exim Smart Host

How to properly send out email messages on a server when having an external mail server to your local area network. If this process is not done, email most likely will not be received as it would be invalid and/or blocked by spam filtering. These instructions will help set up an email server as a smart host.

Note

This example configuration was last tested circa 2019 using Exim v4.93.

Fedora

  1. Install Exim and Mailx packages.
    # dnf exim mailx
    
  2. Create Exim configuration.

    Make sure the TLS paths are correctly set along with routers and transports values.

    # nano /etc/exim/exim.conf
    
    CONFDIR = /etc/exim
    daemon_smtp_port = 25 : 465
    tls_on_connect_ports = 465
    tls_certificate = /etc/pki/tls/certs/ssl-bundle.crt
    tls_privatekey = /etc/pki/tls/private/betelgeuse.key
    disable_ipv6
    hostlist hl_localhost = @ : 127.0.0.1 : ::::1
    domainlist dl_local = @
    hostlist hl_relay_from = +hl_localhost
    local_interfaces = 127.0.0.1 : ::::1
    gecos_pattern = ^([^,:]*)
    gecos_name = $1
    smtp_banner = DSI ESMTP
    keep_environment =
    ignore_bounce_errors_after = 12h
    add_environment = PATH=/usr/bin::/bin
    #message_id_header_domain = vps.example.com
    acl_smtp_connect = acl_check_connect
    acl_smtp_helo = acl_check_helo
    acl_smtp_mail = acl_check_mail
    acl_smtp_rcpt = acl_check_rcpt
    acl_smtp_data = acl_check_data
    
    ##############################################################################
    # ACL CONFIGURATION
    ##############################################################################
    begin acl
    
    acl_check_connect:
    # accept from local hosts
    accept
        hosts = +hl_localhost
    
    # accept from all others after a connection delay
    # some spammers will not wait for a connection
    accept
        delay = 1s
    
    acl_check_helo:
    # accept from local hosts
    accept
        hosts = +hl_localhost
    
    # prevent remote site claiming to be local site
    deny
        message = invalid HELO host
        condition = ${if \
        match_domain {${lc:$sender_helo_name}}{+dl_local} \
        {true}{false} \
        }
    
    accept
    
    acl_check_mail:
    # deny if no HELO command given
    deny
        condition = ${if def:sender_helo_name {no}{yes}}
        delay = 10s
        message = no HELO given before MAIL command
    
    accept
    
    acl_check_rcpt:
    # accept if the source is local SMTP (not TCP/IP)
    accept
        hosts = :
    
    deny
        domains = +dl_local
        local_parts = ^[.] : ^.*[@%!/|`\#&?]
        message = restricted characters in address
    
    deny
        domains = !+dl_local
    local_parts = ^[./|] : ^.*[@%!`\#&?] : ^.*/\\.\\./
        message = restricted characters in address from non-local connection
    
    # accept for relay hosts
    accept
        hosts = +hl_relay_from
        control = submission/sender_retain
    
    # allow relaying for authenticated connection
    accept
        authenticated = *
        control = submission/sender_retain
    
    deny
        !domains = +dl_local
        message = relay not permitted
    
    deny
        !verify = recipient
    
    acl_check_data:
    accept
    
    ##############################################################################
    # ROUTERS CONFIGURATION
    ##############################################################################
    begin routers
    
    smarthost:
    driver = manualroute
    domains = !+dl_local
    transport = remote_smtp
    route_list = * mail.example.com
    ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
    #  headers_remove = received:message-id
    
    ##############################################################################
    # TRANSPORTS CONFIGURATION
    ##############################################################################
    begin transports
    
    remote_smtp:
    debug_print = "T: remote_smtp for $local_part@$domain"
    driver = smtp
    hosts_require_auth = mail.example.com
    #hosts_try_auth = ${if exists {CONFDIR/passwd.client}{DCsmarthost}{}}
    
    begin rewrite
    
    *@*.example.com $1@example.com
    *@example.com systems@example.com Ffrs
    
    begin authenticators
    
    fixed_plain:
    driver = plaintext
    public_name = PLAIN
    hide client_send = ^sh.relay@example.com^put-password-here
    
    1. Set owner and group.
    # chown root:root /etc/exim/exim.conf
    
    1. Enable and start Exim service.
    # systemctl enable exim.service
    # systemctl start exim.service
    
    1. Test rewrite rules.
    $ exim -brw webmaster@betelgeuse.ad.example.com
    
    sender: systems@example.com
        from: systems@example.com
        to: webmaster@example.com
        cc: webmaster@example.com
        bcc: webmaster@example.com
    reply-to: systems@example.com
    env-from: systems@example.com
    env-to: webmaster@example.com
    
    1. Test routing rules.
    $ exim -bt webmaster@example.com
    
    webmaster@example.com
    router = smarthost, transport = remote_smtp
    host mail.example.com [10.10.0.1]
    
    1. Send a test email message.

    When done typing the body of the email press enter and then CTRL-D to send/quit.

    $ mailx -v -s "This is a test" webmaster@example.com
    This is a test of the email smarthost configuration.
    
    EOT
    LOG: MAIN
    <= systems@example.com U=adam P=local S=633
    [adam@betelgeuse ~]$ delivering 1h1EDi-0003SN-16
    T: remote_smtp for webmaster@example.com
    Connecting to mail.example.com [10.10.0.1]:25 ... connected
    SMTP<< 220-vps.example.com ESMTP Exim 4.91 #1 Tue, 05 Mar 2019 12:51:14 -0500
            220-We do not authorize the use of this system to transport unsolicited,
            220 and/or bulk e-mail.
    SMTP>> EHLO betelgeuse.ad.example.com
    SMTP<< 250-vps.example.com Hello betelgeuse.ad.example.com [172.16.0.56]
            250-SIZE 52428800
            250-8BITMIME
            250-PIPELINING
            250-STARTTLS
            250 HELP
    SMTP>> STARTTLS
    SMTP<< 220 TLS go ahead
    SMTP>> EHLO betelgeuse.ad.example.com
    SMTP<< 250-vps.example.com Hello betelgeuse.ad.example.com [172.16.0.56]
            250-SIZE 52428800
            250-8BITMIME
            250-PIPELINING
            250-AUTH PLAIN LOGIN
            250 HELP
    SMTP>> AUTH PLAIN ************************************************************************
    SMTP<< 235 Authentication succeeded
    SMTP>> MAIL FROM:<systems@example.com> SIZE=1671 AUTH=adam@betelgeuse.ad.example.com
    SMTP>> RCPT TO:<webmaster@example.com>
    SMTP>> DATA
    SMTP<< 250 OK
    SMTP<< 250 Accepted
    SMTP<< 354 Enter message, ending with "." on a line by itself
    SMTP>> writing message and terminating "."
    SMTP<< 250 OK id=1h1EDi-0007wP-IH
    SMTP>> QUIT
    SMTP(close)>>
    LOG: MAIN
    => webmaster@example.com R=smarthost T=remote_smtp H=mail.example.com [10.10.0.1] X=TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256 CV=yes A=fixed_plain C="250 OK id=1h1EDi-0007wP-IH"
    LOG: MAIN
    Completed