-
Notifications
You must be signed in to change notification settings - Fork 0
/
init-exim4.sh
executable file
·165 lines (146 loc) · 5.15 KB
/
init-exim4.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/bash
set -ex
join_by () {
local d=${1-} f=${2-}
if shift 2; then
printf %s "$f" "${@/#/$d}"
fi
}
#### Main configuration ####
# Process network relay list
export EXIM4_RELAY_NETS="${EXIM4_RELAY_NETS:-}"
declare -a networks
for network in $EXIM4_RELAY_NETS; do
if [[ "$network" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9](/[0-9]+)?$ ]]; then
# IPv4
networks+=( "$network" )
elif [[ "$network" =~ ^.*:.*$ ]]; then
# IPv6
networks+=( "$network" )
else
# hostname
ip="$(host "$network" | grep -Ev 'IPv6|not found' | awk '{print $4}')"
if [ -n "$ip" ]; then
network=$(ip -br -4 a sh | grep " $ip/" | awk '{print $3}')
if [ -n "$network" ]; then
# local network from local hostname
networks+=( "$network" )
else
# external hostname
networks+=( "$ip" )
fi
fi
fi
done
IFS=$'\n' sorted_networks=($(sort -u <<<"${networks[*]}")); unset IFS
EXIM4_RELAY_NETS="$(join_by " ; " "${sorted_networks[@]}")"
# Exim4 configuration the Debian way
cat <<EOF >/etc/exim4/update-exim4.conf.conf
dc_eximconfig_configtype='internet'
dc_other_hostnames='$LOCAL_DOMAINS'
dc_local_interfaces=''
dc_readhost=''
dc_relay_domains=''
dc_minimaldns='false'
dc_relay_nets='$EXIM4_RELAY_NETS'
dc_smarthost=''
CFILEMODE='644'
dc_use_split_config='true'
dc_hide_mailname=''
dc_mailname_in_oh='true'
dc_localdelivery='mail_spool'
dc_postmaster='root'
EOF
echo "$SERVER_MAILNAME" >/etc/mailname
# /etc/aliases
sed -i '/# CHANGES BELOW THIS LINE ARE NOT PERSISTENT/,$d' /etc/aliases
echo '# CHANGES BELOW THIS LINE ARE NOT PERSISTENT' >>/etc/aliases
if [ -n "$EXIM4_BLACKHOLE" ]; then
for alias in $EXIM4_BLACKHOLE; do
echo "$alias: :blackhole:"
done >>/etc/aliases
fi
# Redirect logs to syslog-ng and configure it to forward them to stdout
echo 'log_file_path = syslog' >/etc/exim4/conf.d/main/00_logs
sed -i 's/(d_mail)/(d_stdout)/' /etc/syslog-ng/syslog-ng.conf
# Tell syslog-ng to reload conf
killall -SIGHUP syslog-ng
# TLS defaults to FALSE
export EXIM4_TLS_ENABLE="${EXIM4_TLS_ENABLE:-FALSE}"
# DKIM signature defaults to FALSE
export EXIM4_DKIM_SIGNATURE_ENABLE="${EXIM4_DKIM_SIGNATURE_ENABLE:-FALSE}"
#### Custom configuration files ####
# Substitute every @EXIM4_*@ placeholder with the corresponding environment variable value
exim4_vars=$(env | sed -En '/^(EXIM4_[^=]+)=.*$/{s//\1/;p}')
subst=()
for varname in $exim4_vars; do
value="${!varname}"
subst+=(-e "s/@${varname}@/${value//\//\\\/}/g")
done
cd /var/spool/exim4/conf.d
for conf in $(find * -type f -print); do
sed "${subst[@]}" /var/spool/exim4/conf.d/$conf >/etc/exim4/conf.d/$conf
done
#### Plugins configuration ####
# Plugin spec example
# PLUGIN_SPEC_MAILMAN={"plugin": "mailman", "instances": [{"domainlist": "lists1.example.com", "host": "mailman-core1"}, {"domainlist": "lists2.example.com", "host": "mailman-core2"}]}
# plugin name^
# array of instances for this plugin^
# Each instance is a flat json object with key/value definitions for the corresponding plugin configuration
# Collect the PLUGIN_SPEC_* environment variables
plugin_specs=$(env | sed -En '/^(PLUGIN_SPEC_[^=]+)=.*$/{s//\1/;p}')
# Set current directory to the plugins' parent dir
cd /var/spool/exim4/plugins
# For each PLUGIN_SPEC_* environment variable
for spec in $plugin_specs; do
plugin=
while read line; do
# First line of the jq command's output is the plugin name
[ -n "$plugin" ] || {
# Retrieve the file list for this plugin and reset the instance index
plugin="$line"
plugin_files=$(find "$plugin/conf.d" -type f -print)
for file in $plugin_files; do
rm -f "/etc/exim4/${file#*/}"
done
idx=0
continue
}
# Current line is a sed substitution command for an instance of the
# plugin
# For each file from the plugin's dir do the key/value substitutions
# + the one for the instance index (idx) and put the result into the
# corresponding exim4 configuration path
for file in $plugin_files; do
sed -e "$line" -e "s/@idx@/$idx/g" "$file" >>"/etc/exim4/${file#*/}"
done
# Don't forget to increment the instance index before looping
idx=$((idx+1))
done < <(echo "${!spec}" |
# jq program to build the input for the above shell loop
# The first output line is the plugin's name
# Then one output line per instance, being the sed substitution command
# to use for this instance. Constructed from the key/value pairs defined
# into the instance
# Use <tab> "\t" as separator in substitution expressions
# For the above PLUGIN_SPEC_MAILMAN example, the output would be:
# mailman
# s @domainlist@ lists1.example.com g;s @host@ mailman-core1 g
# s @domainlist@ lists2.example.com g;s @host@ mailman-core2 g
# ^tab ^tab ^tab ^tab ^tab ^tab
jq -r '
.plugin + "\n" +
(
[
.instances[] |
[
to_entries[] | "s\t@" + .key + "@\t" + .value + "\tg"
] | join(";")
] | join("\n")
)
'
)
done
#### Finalize config and run ####
# Update exim4 configuration
/usr/sbin/update-exim4.conf