#!/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