#!/usr/bin/env bash if [[ -z "${TARGET_UID}" ]]; then echo "Error: The TARGET_UID environment variable was not specified."; exit 1; fi if [[ -z "${TARGET_GID}" ]]; then echo "Error: The TARGET_GID environment variable was not specified."; exit 1; fi if [[ "${EUID}" -ne 0 ]]; then echo "Error: This Docker container must run as root because fetchmail is a pain, and to allow customisation of the target UID/GID (although all possible actions are run as non-root users)"; exit 1; fi dir_mail_root="/tmp/maildir"; dir_newmail="${dir_mail_root}/Mail/new"; target_dir="/mnt/output"; fetchmail_uid="$(id -u "fetchmail")"; fetchmail_gid="$(id -g "fetchmail")"; temp_dir="$(mktemp --tmpdir -d "imap-download-XXXXXXX")"; on_exit() { rm -rf "${temp_dir}"; } trap on_exit EXIT; run_as_user() { run_as_uid="${1}"; shift; run_as_gid="${1}"; shift; if [[ -z "${run_as_uid}" ]]; then echo "run_as_user: No target UID specified."; return 1; fi if [[ -z "${run_as_gid}" ]]; then echo "run_as_user: No target GID specified."; return 2; fi # Ref https://github.com/SinusBot/docker/pull/40 # WORKAROUND for `setpriv: libcap-ng is too old for "all" caps`, previously "-all" was used here # create a list to drop all capabilities supported by current kernel cap_prefix="-cap_"; caps="$cap_prefix$(seq -s ",$cap_prefix" 0 "$(cat /proc/sys/kernel/cap_last_cap)")"; setpriv --inh-caps="${caps}" --reuid "${run_as_uid}" --clear-groups --regid "${run_as_gid}" "$@"; return "$?"; } do_fetchmail() { log_msg "Starting fetchmail"; while :; do run_as_user "${fetchmail_uid}" "${fetchmail_gid}" fetchmail --mda "/usr/bin/procmail -m /srv/procmail.conf"; exit_code="$?"; if [[ "$exit_code" -eq 127 ]]; then log_msg "setpriv failed, exiting with code 127"; exit 127; fi log_msg "Fetchmail exited with code ${exit_code}, sleeping 60 seconds"; sleep 60 done } log_msg() { echo "$(date -u +"%Y-%m-%d %H:%M:%S") imap-download: $*"; } mkdir -p "${dir_newmail}"; chown -R "${fetchmail_uid}:${fetchmail_gid}" "${dir_mail_root}"; do_attachments() { while :; do # : = infinite loop # Wait for an update # inotifywait's non-0 exit code forces an exit for some reason :-/ inotifywait -qr --event create --format '%:e %f' "${dir_newmail}"; while read -r filename; do log_msg "Processing email ${filename}"; # Move the email to a temporary directory for processing mv "${filename}" "${temp_dir}"; filepath_temp="${temp_dir}/$(basename "${filename}")" # Unpack the attachments munpack -C "${temp_dir}" "${filepath_temp}"; # Delete the original email file and any description files rm "${filepath_temp}"; find "${temp_dir}" -iname '*.desc' -delete; chown -R "${TARGET_UID}:${TARGET_GID}" "${temp_dir}"; chmod -R a=rX,ug+w "${temp_dir}"; ls -lahR "${temp_dir}"; # Move the attachment files to the output directory while read -r attachment; do log_msg "Extracted attachment ${attachment}"; chmod 0775 "${attachment}"; run_as_user "${TARGET_UID}" "${TARGET_GID}" mv "${attachment}" "${target_dir}"; done < <(find "${temp_dir}" -type f); done < <(find "${dir_newmail}" -type f); done } do_fetchmail & do_attachments