As a workaround I created smovemail
, a shell script which runs movemail
on a local copy of the remote mailbox:
#!/bin/bash
# initialize variables
status=0
src=
dest=
remotefs=
copy=
mountpoint=
lockfile=
# function to print errors
function error {
echo "(E) ${1}" >&2
status=1
}
# function to tear down created environment
function tear_down {
# remove local copy of remote mailbox
if [[ "${copy}" ]]; then
rm -- "${copy}" ||
error "Unable to remove local copy of remote mailbox '${copy}.'"
fi
# remove lockfile
if [[ "${lockfile}" ]]; then
rm -- "${lockfile}" ||
error "Unable to remove lockfile '${lockfile}. Remote mailbox may still be locked.'"
fi
# unmount SSHFS
mount | cut -d " " -f 3 | grep "${mountpoint}" >/dev/null &&
fusermount -u "${mountpoint}" 2>/dev/null ||
error "Unable to unmount remote filesystem mounted at '${mountpoint}'"
# remove mountpoint
if [[ "${mountpoint}" ]]; then
rmdir "${mountpoint}" 2>/dev/null ||
error "Unable to remove mountpoint '${mountpoint}'"
fi
exit ${status}
}
# register tear down function to run in any case
trap tear_down EXIT
# print usage
if [[ ${#} -ne 2 ]]; then
error "Usage: $(basename ${0}) remote_mailbox local_mailbox"
exit
fi
# TODO implement better parameter sanitization
# create mountpoint
mountpoint=$(mktemp -d 2>/dev/null) || {
error "Unable to create mountpoint."
exit
}
# determine locations
src="${mountpoint}/"$(basename "${1}" 2>/dev/null)
remotefs=$(dirname "${1}" 2>/dev/null)
dest="${2}"
# mount SSHFS
sshfs "${remotefs}" "${mountpoint}" -o workaround=rename,reconnect,uid=$(id -u),gid=$(id -g) >/dev/null 2>&1 || {
error "Unable to mount remote filesystem '${remotefs}'"
exit
}
# lock remote mailbox
lockfile=$(mktemp -p "${mountpoint}" 2>/dev/null) || {
error "Unable to create lockfile"
exit
}
mv -n "${lockfile}" "${src}.lock"
if [[ -f "${lockfile}" ]]; then
error "Unable to lock mailbox."
exit
fi
lockfile="${src}.lock"
# create local copy
copy=$(mktemp 2>/dev/null) || {
error "Unable to create copy of remote mailbox."
exit
}
cp "${src}" "${copy}" 2>/dev/null || {
error "Unable to copy remote mailbox."
exit
}
# run movemail
movemail "${copy}" "${dest}" || {
error "Unable to move mails."
exit
}
# play back copy
cp "${copy}" "${src}" 2>/dev/null || {
error "Unable to play back local copy."
exit
}
It can be invoked by $ smovemail remoteuser@remotehost:/var/mail/remoteuser /var/mail/localuser
If you want to use this script, feel free to do so, but please note: This script leverages the mv -n
command to lock the remote mailbox and therefore is based on the assumption that this command is atomic on SSHFS filesystems. Based on my research this assumption does not always hold! However, I ran some tests and was not able to crash it, so for me it is good enough.
Comments and suggestions for improvements are very welcome.