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

fetch_mailbox.sh (last edited 2009-07-15 18:08:22 by hnvr-4dbd68d1)