aboutsummaryrefslogtreecommitdiff
# SPDX-License-Identifier: GPL-2.0-or-later and CC0-1.0
# Copyright (c) 2004-2023 University of Cambridge
# Copyright (C) 2023, 2024 Wojtek Kosior <koszko@koszko.org>

# Changes by Wojtek are available under CC0.

# Adapted from
# https://git.exim.org/exim.git/blob/3e6d406e8ae9681a8cc1b404e7f5d1bd6d65d201:/src/src/configure.default

exim_group = vmail
deliver_drop_privilege

spool_directory = /var/spool/exim
log_file_path = $spool_directory/log/%slog
log_selector = +smtp_protocol_error +smtp_syntax_error \
        +tls_certificate_verified +tls_peerdn

domainlist    local_domains = @ : localhost : happyhacking.pl : koszko.org : \
                              koszkonutek-tmp.pl.eu.org
domainlist    relay_to_domains =
hostlist      relay_from_hosts = <; ; 127.0.0.1 ; ::1
localpartlist vmail_usernames = ${sg {${readfile{/var/vmail/passwd}{:::}}}\
                                     {\N:?[^:]+:::\N}\
                                     {:}}

acl_smtp_rcpt =         acl_check_rcpt
.ifdef _HAVE_PRDR
# currently does nothing
acl_smtp_data_prdr =    acl_check_prdr
.endif
acl_smtp_data =         acl_check_data

tls_certificate = /etc/certs/smtp.koszko.org/fullchain.pem
tls_privatekey = /etc/certs/smtp.koszko.org/privkey.pem

tls_verify_certificates = ${if exists{/etc/ssl/certs/ca-certificates.crt}\
                               {/etc/ssl/certs/ca-certificates.crt}\
			       {/dev/null}}

.ifdef _HAVE_GNUTLS
tls_dhparam = historic
.endif

# For OpenSSL, prefer EC- over RSA-authenticated ciphers
.ifdef _HAVE_OPENSSL
tls_require_ciphers = ECDSA:RSA:!COMPLEMENTOFDEFAULT
.endif

daemon_smtp_ports = 25 : 12525 : 465 : 587
tls_on_connect_ports = 465 : 587

primary_hostname = salamina.koszko.org
qualify_domain = koszko.org

never_users = root

host_lookup = *

dns_dnssec_ok = 1

#rfc1413_hosts = *
#rfc1413_query_timeout = 5s

.ifdef _HAVE_PRDR
prdr_enable = true
.endif

ignore_bounce_errors_after = 2d

timeout_frozen_after = 7d

freeze_tell = admin

check_rfc2047_length = false

accept_8bitmime = false

keep_environment =

received_header_text =\
Received: from dummy-client.koszko.org ([192.168.193.169])\n\t\
          by $primary_hostname\
          ${if def:received_protocol\
               { with $received_protocol}}\
          ${if def:tls_in_ver\
               { ($tls_in_ver)}}\
          ${if def:tls_in_cipher_std\
               { tls $tls_in_cipher_std\n\t}}\
          (Exim $version_number)\n\t\
          ${if def:sender_address\
               {(envelope-from <$sender_address>)\n\t}}\
          id $message_exim_id\
          ${if def:received_for\
               {\n\tfor $received_for}}

begin acl

acl_check_rcpt:

  accept  hosts = :
          control = dkim_disable_verify

  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|`#&?]

  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!`#&?] : ^.*/\\.\\./

  accept  local_parts   = postmaster
          domains       = +local_domains

  warn    !verify       = sender
          log_message   = $acl_verify_message: $sender_verify_failure

  deny    condition     = ${if and {\
                            {>{$rcpt_count}{10}}\
                            {<{$recipients_count}{${eval:$rcpt_count/2}}}\
                            }}
          message       = Rejected for too many bad recipients
          logwrite      = REJECT [$sender_host_address]: \
                          bad recipient count high \
                          [${eval:$rcpt_count-$recipients_count}]

  accept  hosts         = +relay_from_hosts
          control       = submission/sender_retain
          control       = dkim_disable_verify

  accept  authenticated = *
          condition     = ${lookup{$authenticated_id}\
                            lsearch{/var/vmail/admin-users}\
                            {yes}{no}}
          control       = submission/sender_retain
          control       = dkim_disable_verify

  accept  authenticated = *
          control       = submission
          control       = dkim_disable_verify

  require message = relay not permitted
          domains = +local_domains : +relay_to_domains

  require verify = recipient

  accept


.ifdef _HAVE_PRDR
acl_check_prdr:

  warn  set acl_m_did_prdr = y

  accept
.endif

acl_check_data:

  deny    !verify =     header_syntax
          message =     header syntax
          log_message = header syntax ($acl_verify_message)

  accept

begin routers

dnslookup:
  driver = dnslookup
  domains = ! +local_domains
  transport = remote_smtp
  same_domain_copy_routing = yes
  ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; 192.168.0.0/16 ;\
                        172.16.0.0/12 ; 10.0.0.0/8 ; 169.254.0.0/16 ;\
			255.255.255.255 ; ::1
  dnssec_request_domains = *
  no_more

dot_stripping:
  driver = redirect
  data = ${sg{$local_part}{[.]}{}}@$domain

system_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup{$local_part}lsearch{/etc/aliases}}

vmail_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup{$local_part}lsearch{/var/vmail/aliases}}

vmail_user:
  driver = accept
  local_parts = +vmail_usernames
  transport = vmail_delivery
  cannot_route_message = Unknown user

begin transports

remote_smtp:
  driver = smtp
  dkim_domain = ${sender_address_domain}
  helo_data = ${sender_address_domain}

dkim_selector = mail-salamina
dkim_private_key = /etc/exim/dkim.key

.ifdef _HAVE_DANE
dnssec_request_domains = *
hosts_try_dane = *
.endif

vmail_delivery:
  driver = appendfile
  maildir_format
  create_directory
  delivery_date_add
  envelope_to_add
  return_path_add
  no_check_owner
  group = vmail
  directory = /var/vmail/maildirs/$local_part_data
  directory_mode = 0770
  mode = 0660
  mode_fail_narrower = false

begin retry

# Address or Domain    Error       Retries
# -----------------    -----       -------

*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h

begin rewrite

begin authenticators

# PLAIN authentication has no server prompts. The client sends its
# credentials in one lump, containing an authorization ID (which we do not
# use), an authentication ID, and a password. The latter two appear as
# $auth2 and $auth3 in the configuration and should be checked against a
# valid username and password. In a real configuration you would typically
# use $auth2 as a lookup key, and compare $auth3 against the result of the
# lookup, perhaps using the crypteq{}{} condition.

PLAIN:
 driver                     = plaintext
 server_set_id              = $auth2
 server_prompts             = :
 server_condition           = "${if crypteq{$auth3}{${extract{1}{:}{${lookup{$auth2}lsearch{/var/vmail/passwd}{$value}{*:*}}}}}{1}{0}}"
 server_advertise_condition = ${if def:tls_in_cipher }

# LOGIN authentication has traditional prompts and responses. There is no
# authorization ID in this mechanism, so unlike PLAIN the username and
# password are $auth1 and $auth2. Apart from that you can use the same
# server_condition setting for both authenticators.

LOGIN:
 driver                     = plaintext
 server_set_id              = $auth1
 server_prompts             = <| Username: | Password:
 server_condition           = "${if crypteq{$auth2}{${extract{1}{:}{${lookup{$auth1}lsearch{/var/vmail/passwd}{$value}{*:*}}}}}{1}{0}}"
 server_advertise_condition = ${if def:tls_in_cipher }

# Hehe
HAPPY_HACKING:
 driver                     = plaintext
 server_prompts             = <| Login hackera: \
                               | Hasło hackera: \
                               | Ulubiony kolor: \
                               | Imię pierwszego zwierzątka domowego: \
                               | Panieńskie nazwisko Babci od strony Mamy:
 server_condition           = 0
 server_advertise_condition = 1