2021-05-25 21:19:37 +00:00
#!/usr/bin/env bash
2021-05-26 12:44:47 +00:00
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
2021-05-25 23:33:35 +00:00
2021-05-26 21:20:22 +00:00
dir_mail_root = "/tmp/maildir" ;
dir_newmail = " ${ dir_mail_root } /Mail/new " ;
2021-05-25 23:33:35 +00:00
target_dir = "/mnt/output" ;
fetchmail_uid = " $( id -u "fetchmail" ) " ;
fetchmail_gid = " $( id -g "fetchmail" ) " ;
2021-05-25 21:19:37 +00:00
temp_dir = " $( mktemp --tmpdir -d "imap-download-XXXXXXX" ) " ;
on_exit( ) {
rm -rf " ${ temp_dir } " ;
}
trap on_exit EXIT;
2021-05-26 12:44:47 +00:00
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 " $? " ;
}
2021-05-25 21:19:37 +00:00
do_fetchmail( ) {
2021-05-25 23:33:35 +00:00
log_msg "Starting fetchmail" ;
while :; do
2021-05-26 12:44:47 +00:00
run_as_user " ${ fetchmail_uid } " " ${ fetchmail_gid } " fetchmail --mda "/usr/bin/procmail -m /srv/procmail.conf" ;
2021-05-25 23:33:35 +00:00
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
2021-05-25 21:19:37 +00:00
}
log_msg( ) {
echo " $( date -u +"%Y-%m-%d %H:%M:%S" ) imap-download: $* " ;
}
2021-05-25 23:33:35 +00:00
mkdir -p " ${ dir_newmail } " ;
2021-05-26 21:20:22 +00:00
chown -R " ${ fetchmail_uid } : ${ fetchmail_gid } " " ${ dir_mail_root } " ;
2021-05-25 21:19:37 +00:00
2021-05-26 12:44:47 +00:00
# Moves an attachment to the output directory as the target uid/gid.
# chowns the file before moving.
# $1 The path to the file to move.
move_attachment( ) {
local filename = " ${ 1 } " ;
chown " ${ TARGET_UID } : ${ TARGET_GID } " " ${ filename } " ;
run_as_user " ${ TARGET_UID } " " ${ TARGET_GID } " mv " ${ filename } " " ${ target_dir } " ;
}
2021-05-25 21:19:37 +00:00
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 } " ;
# Unpack the attachments
munpack -C " ${ temp_dir } " " ${ filename } " ;
# Delete the original email file and any description files
2021-05-26 21:40:40 +00:00
rm " ${ temp_dir } / ${ filename } " ;
2021-05-25 21:19:37 +00:00
find " ${ temp_dir } " -iname '*.desc' -delete;
# Move the attachment files to the output directory
while read -r attachment; do
log_msg " Extracted attachment ${ attachment } " ;
2021-05-25 21:31:11 +00:00
chmod 0775 " ${ temp_dir } / ${ attachment } " ;
2021-05-26 12:44:47 +00:00
move_attachment " ${ attachment } " ;
2021-05-25 21:19:37 +00:00
done < <( find " ${ temp_dir } " -type f) ;
done < <( find " ${ dir_newmail } " -type f) ;
done
}
do_fetchmail &
do_attachments