breaking: Refactor getmail support (#4156)

Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com>
Co-authored-by: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com>
This commit is contained in:
Casper 2024-08-17 12:14:59 +02:00 committed by GitHub
parent fb57905aa3
commit b2978fd760
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 198 additions and 59 deletions

View file

@ -5,9 +5,20 @@ source /usr/local/bin/helpers/log.sh
# shellcheck source=../scripts/startup/setup-stack.sh
source /usr/local/bin/setup.d/getmail.sh
_setup_getmail
# Setup getmail, even if not enabled.
ENABLE_GETMAIL=1 _setup_getmail
GETMAILDIR=/tmp/docker-mailserver/getmail
for FILE in /etc/getmailrc.d/getmailrc*; do
getmail --getmaildir "${GETMAILDIR}" --rcfile "${FILE}" --dump | tail -n +6
# Directory, where "oldmail" files are stored.
# Getmail stores its state - its "memory" of what it has seen in your POP/IMAP account - in the oldmail files.
GETMAIL_DIR=/var/lib/getmail
# If no matching filenames are found, and the shell option nullglob is disabled, the word is left unchanged.
# If the nullglob option is set, and no matches are found, the word is removed.
shopt -s nullglob
# Dump configuration from each RC file.
for RC_FILE in /etc/getmailrc.d/*; do
echo "${RC_FILE##*/}:"
echo
getmail --getmaildir "${GETMAIL_DIR}" --rcfile "${RC_FILE}" --dump | tail -n +6
done

View file

@ -1,8 +0,0 @@
#! /bin/bash
GETMAILDIR=/tmp/docker-mailserver/getmail
for FILE in /etc/getmailrc.d/getmailrc*; do
if ! pgrep -f "${FILE}$" &>/dev/null; then
getmail --getmaildir "${GETMAILDIR}" --rcfile "${FILE}"
fi
done

View file

@ -0,0 +1,47 @@
#!/bin/bash
# shellcheck source=../scripts/helpers/log.sh
source /usr/local/bin/helpers/log.sh
# Directory, where "oldmail" files are stored.
# getmail stores its state - its "memory" of what it has seen in your POP/IMAP account - in the oldmail files.
GETMAIL_DIR=/var/lib/getmail
# Kill all child processes on EXIT.
# Otherwise 'supervisorctl restart getmail' leads to zombie 'sleep' processes.
trap 'pkill --parent ${$}' EXIT
function _syslog_error() {
logger --priority mail.err --tag getmail "${1}"
}
function _stop_service() {
_syslog_error "Stopping service"
exec supervisorctl stop getmail
}
# Verify the correct value for GETMAIL_POLL. Valid are any numbers greater than 0.
if [[ ! ${GETMAIL_POLL} =~ ^[0-9]+$ ]] || [[ ${GETMAIL_POLL} -lt 1 ]]; then
_syslog_error "Invalid value for GETMAIL_POLL: ${GETMAIL_POLL}"
_stop_service
fi
# If no matching filenames are found, and the shell option nullglob is disabled, the word is left unchanged.
# If the nullglob option is set, and no matches are found, the word is removed.
shopt -s nullglob
# Run each getmailrc periodically.
while :; do
for RC_FILE in /etc/getmailrc.d/*; do
_log 'debug' "Processing ${RC_FILE}"
getmail --getmaildir "${GETMAIL_DIR}" --rcfile "${RC_FILE}"
done
# Stop service if no configuration is found.
if [[ -z ${RC_FILE} ]]; then
_syslog_error 'No configuration found'
_stop_service
fi
sleep "${GETMAIL_POLL}m"
done

View file

@ -1,3 +1,5 @@
# https://getmail6.org/configuration.html#conf-options
[options]
verbose = 0
read_all = false
@ -5,3 +7,5 @@ delete = false
max_messages_per_session = 500
received = false
delivered_to = false
message_log_syslog = true

View file

@ -161,6 +161,7 @@ function _register_functions() {
[[ ${ENABLE_CLAMAV} -eq 1 ]] && _register_start_daemon '_start_daemon_clamav'
[[ ${ENABLE_AMAVIS} -eq 1 ]] && _register_start_daemon '_start_daemon_amavis'
[[ ${ACCOUNT_PROVISIONER} == 'FILE' ]] && _register_start_daemon '_start_daemon_changedetector'
[[ ${ENABLE_GETMAIL} -eq 1 ]] && _register_start_daemon '_start_daemon_getmail'
}
# ------------------------------------------------------------

View file

@ -34,6 +34,7 @@ function _start_daemon_clamav { _default_start_daemon 'clamav' ;
function _start_daemon_cron { _default_start_daemon 'cron' ; }
function _start_daemon_dovecot { _default_start_daemon 'dovecot' ; }
function _start_daemon_fail2ban { _default_start_daemon 'fail2ban' ; }
function _start_daemon_getmail { _default_start_daemon 'getmail' ; }
function _start_daemon_opendkim { _default_start_daemon 'opendkim' ; }
function _start_daemon_opendmarc { _default_start_daemon 'opendmarc' ; }
function _start_daemon_postgrey { _default_start_daemon 'postgrey' ; }

View file

@ -4,38 +4,46 @@ function _setup_getmail() {
if [[ ${ENABLE_GETMAIL} -eq 1 ]]; then
_log 'trace' 'Preparing Getmail configuration'
local GETMAILRC ID CONFIGS
local GETMAIL_RC ID GETMAIL_DIR
GETMAILRC='/etc/getmailrc.d'
CONFIGS=0
local GETMAIL_CONFIG_DIR='/tmp/docker-mailserver/getmail'
local GETMAIL_RC_DIR='/etc/getmailrc.d'
local GETMAIL_RC_GENERAL_CF="${GETMAIL_CONFIG_DIR}/getmailrc_general.cf"
local GETMAIL_RC_GENERAL='/etc/getmailrc_general'
mkdir -p "${GETMAILRC}"
# Create the directory /etc/getmailrc.d to place the user config in later.
mkdir -p "${GETMAIL_RC_DIR}"
# Generate getmailrc configs, starting with the `/etc/getmailrc_general` base config,
# Add a unique `message_log` config, then append users own config to the end.
for FILE in /tmp/docker-mailserver/getmail-*.cf; do
if [[ -f ${FILE} ]]; then
CONFIGS=1
ID=$(cut -d '-' -f 3 <<< "${FILE}" | cut -d '.' -f 1)
local GETMAIL_CONFIG="${GETMAILRC}/getmailrc-${ID}"
cat /etc/getmailrc_general >"${GETMAIL_CONFIG}"
echo -e "message_log = /var/log/mail/getmail-${ID}.log\n" >>"${GETMAIL_CONFIG}"
cat "${FILE}" >>"${GETMAIL_CONFIG}"
fi
done
if [[ ${CONFIGS} -eq 1 ]]; then
cat >/etc/cron.d/getmail << EOF
*/${GETMAIL_POLL} * * * * root /usr/local/bin/getmail-cron
EOF
chmod -R 600 "${GETMAILRC}"
# Check if custom getmailrc_general.cf file is present.
if [[ -f "${GETMAIL_RC_GENERAL_CF}" ]]; then
_log 'debug' "Custom 'getmailrc_general.cf' found"
cp "${GETMAIL_RC_GENERAL_CF}" "${GETMAIL_RC_GENERAL}"
fi
# Both the debug command and cron job (that runs getmail) for getmail
# expect this location to exist.
GETMAILDIR=/tmp/docker-mailserver/getmail
mkdir -p "${GETMAILDIR}"
# If no matching filenames are found, and the shell option nullglob is disabled, the word is left unchanged.
# If the nullglob option is set, and no matches are found, the word is removed.
shopt -s nullglob
# Generate getmailrc configs, starting with the `/etc/getmailrc_general` base config, then appending users own config to the end.
for FILE in "${GETMAIL_CONFIG_DIR}"/*.cf; do
if [[ ${FILE} =~ /getmail/(.+)\.cf ]] && [[ ${FILE} != "${GETMAIL_RC_GENERAL_CF}" ]]; then
ID=${BASH_REMATCH[1]}
_log 'debug' "Processing getmail config '${ID}'"
GETMAIL_RC=${GETMAIL_RC_DIR}/${ID}
cat "${GETMAIL_RC_GENERAL}" "${FILE}" >"${GETMAIL_RC}"
fi
done
# Strip read access from non-root due to files containing secrets:
chmod -R 600 "${GETMAIL_RC_DIR}"
# Directory, where "oldmail" files are stored.
# For more information see: https://getmail6.org/faq.html#faq-about-oldmail
# The debug command for getmail expects this location to exist.
GETMAIL_DIR=/var/lib/getmail
_log 'debug' "Creating getmail state-dir '${GETMAIL_DIR}'"
mkdir -p "${GETMAIL_DIR}"
else
_log 'debug' 'Getmail is disabled'
fi

View file

@ -23,6 +23,7 @@ function _setup_save_states() {
[[ ${ENABLE_CLAMAV} -eq 1 ]] && SERVICEDIRS+=('lib/clamav')
[[ ${ENABLE_FAIL2BAN} -eq 1 ]] && SERVICEDIRS+=('lib/fail2ban')
[[ ${ENABLE_FETCHMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/fetchmail')
[[ ${ENABLE_GETMAIL} -eq 1 ]] && SERVICEDIRS+=('lib/getmail')
[[ ${ENABLE_MTA_STS} -eq 1 ]] && SERVICEDIRS+=('lib/mta-sts')
[[ ${ENABLE_POSTGREY} -eq 1 ]] && SERVICEDIRS+=('lib/postgrey')
[[ ${ENABLE_RSPAMD} -eq 1 ]] && SERVICEDIRS+=('lib/rspamd')

View file

@ -170,3 +170,12 @@ stderr_logfile=/var/log/supervisor/%(program_name)s.log
command=/usr/bin/mta-sts-daemon --config /etc/mta-sts-daemon.yml
user=_mta-sts
environment=HOME=/var/lib/mta-sts
[program:getmail]
startsecs=0
stopwaitsecs=55
autostart=false
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
command=/bin/bash -l -c /usr/local/bin/getmail-service.sh