#!/bin/sh
# Fetch all emails out of a mailbox on a local Dovecot server,
# printing them to stdout.
# Optionaly delete them afterwards.
#
# Usage: fetch_mailbox [-d] <mailbox>
#
# Requirements:
# * Unix shell including sed, grep and head
# * empty (http://empty.sourceforge.net/)
# * Dovecot (http://dovecot.org/)
# * Mailbox must be on the local server and accessible by the current user
#
# Useful for:
# * Training your spamfilter
# * Debugging
#
# What is missing:
# * Error checking
# In case of errors the script will usually hang until empty times out.
## invariant data ##
usage_info="Usage: $0 [-d] <mailbox>"
#debug=true # comment out to disable
## names of temporary fifos ##
in="imap_fetch_mailbox.$$.fifo.in"
out="imap_fetch_mailbox.$$.fifo.out"
## delete after fetch? ##
if [ "$1" = "-d" ] ; then
delete=true
shift
fi
## which mailbox to fetch? ##
mailbox="$1"
if [ -z "$mailbox" ] ; then
echo "$usage_info"
exit 1
fi
shift
## initiate imap connection, setup fifo ##
empty -f -i $in -o $out /usr/sbin/dovecot --exec-mail imap
## select mailbox ##
[ $debug ] && echo "0 SELECT $mailbox"
echo "0 SELECT $mailbox" > $in
## wait for server to finish transaction and parse number of emails ##
num_mails=$(empty -w -v -i $out -o $in '0 OK' \
| sed -rn 's/^\* ([[:digit:]]+) EXISTS\r$/\1/p')
[ $debug ] && echo "NUM_MAILS: $num_mails"
## fetch all emails ##
for i in $(seq 1 $num_mails) ; do
[ $debug ] && echo "$i FETCH $i BODY.PEEK[]"
echo "$i FETCH $i BODY.PEEK[]" > $in
body_size_received=0
body_size=0
## search for body size ##
while [ $body_size_received -ne 1 ] ; do
### read response ##
[ $debug ] && echo "RECEIVING RESPONSE $line"
read line < $out
[ $debug ] && echo "GOT METADATA: $line"
## look for metadata ##
if echo "$line" | grep "^\* $i FETCH" > /dev/null ; then
body_size_received=1
## cut the size out of the response ##
body_size=$(echo "$line" \
| sed -rn 's/^.*BODY\[\] \{([[:digit:]]+)\}\r$/\1/p')
fi
done
## receive body ##
[ $debug ] && echo "RECEIVING BODY: $body_size"
body=$(head -c $body_size < $out | sed 's/\r$//')
[ $debug ] && echo "GOT BODY: $body"
## wait for server to finish transaction ##
empty -w -i $out -o $in "$i OK"
## output email to stdout ##
echo "$body"
## optionaly delete email ##
if [ $delete ] ; then
[ $debug ] && echo "d$i STORE $i +FLAGS \\deleted"
echo "d$i STORE $i +FLAGS \\deleted" > $in
## wait for server to finish transaction ##
empty -w -i $out -o $in "d$i OK"
fi
done
## execute delete ##
[ $debug ] && echo "eee EXPUNGE"
echo "eee EXPUNGE" > $in
## wait for server to finish transaction ##
empty -w -i $out -o $in "eee OK"
## logout ##
[ $debug ] && echo 'xxx LOGOUT'
echo 'xxx LOGOUT' > $in