#!/bin/bash

#                       This Script
# !!!!!! DOES NOT HANDLE SPACES IN FILE OR DIRECTORY NAMES !!!!!!
#
# You will need to go to the mailstore path and change any folder
# names with spaces to something without spaces.  Leave "inbox"
# as is; that's an icewarp default mailbox.  This script was
# not tested with any spaces or special characters
# (ie '.', '-', or '_') in the imap folder name.

FILES=`find /path/to/icewarp/mailstore -name \*.imap`
SCRAP=$PWD/scrap
ODIR=$PWD/output

PID=12345
SNAME=icewarp

# Icewarp filename specifics:
#  200612171259060055-000001020000000535916763.imap
#  XXXXXXXXTTTTTTDDDD-ZZZZZZFFUUUUUUUUHHHHHHHH.imap
#                     000000000000000035916763  (first line of email)
# XXXXXXXX - year, month, day
# TTTTTT   - hour, minute, seconds
# DDDD     - unknown
# ZZZZZ    - always seems to be 00001
# FF       - flags
# UUUUUUUU - appears to be a sequence number
# HHHHHHHH - appears to be the Message-Id in hex.
#
# Icewarp flags:
# * OK [PERMANENTFLAGS (\Seen \Answered \Flagged \Draft \Deleted)]
# Not documented.  Discovered through querying the icewarp server
# and observing returned flags vs filename stored on disk.  The flags
# are likely bitmasks of bytes 26 and 27 of the filename:
SEEN=0x02       # 0000 0010   /Seen
ANSD=0x04       # 0000 0100   /Answered
FLGD=0x08       # 0000 1000   /Flagged
DRFT=0x10       # 0001 0000   /Draft
DLTD=0x40       # 0100 0000   /Deleted or (no flags)


# Dovecot filename specifics:
# ,S=<size>: <size> contains the file size.
# ,W=<vsize>: <vsize> contains the file's RFC822.SIZE,
#             ie. the file size with linefeeds being CR+LF characters.
#             If the message was stored with CR+LF linefeeds,
#             <size> and <vsize> are the same.
#
# Dovecot flags:
#Flag "P" (passed):  the user has resent/forwarded/bounced
#                      this message to someone else.
#Flag "R" (replied): the user has replied to this message.
#Flag "S" (seen):    the user has viewed this message, though
#                      perhaps he didn't read all the way through it.
#Flag "T" (trashed): the user has moved this message to the trash;
#                      the trash will be emptied by a later user action.
#Flag "D" (draft):   the user considers this message a draft; toggled
#                       at user discretion.
#Flag "F" (flagged): user-defined flag; toggled at user discretion. 


for f in $FILES; do
	fname=${f##*/}
	path=${f%/*}
	dir=${path##*/}

#	echo $path
#	echo $dir
	echo $fname

	# If there are filenames that don't match, put them somewhere
	# for future investigation.  Checking for filename length is
	# convenient and easy, but not necessarily robust...
	if [ 48 -ne ${#fname} ]; then
		echo "This file is not recognised.  Copied to $SCRAP."
		mkdir -p $SCRAP/$dir
		cp $f $SCRAP/$dir 
		continue
	fi

	# Grab the date from the filename, convert to unix timestamp.
        Y=`echo $fname | cut -c 1-4`
        T=`echo $fname | cut -c 5-6`
        D=`echo $fname | cut -c 7-8`
	H=`echo $fname | cut -c 9-10`
	M=`echo $fname | cut -c 11-12`
	S=`echo $fname | cut -c 13-14`
	DATE=`date -d "$Y-$T-$D $H:$M:$S" "+%s"`

	# icewarp stores mail with crlf so the size from stat will be
	# the same as RFC822.SIZE except that the .imap file stores 
	# the Message-Id in hex as the first line (26 bytes):
	# 00000000000000003639BBEE + line feed
	fsz=`stat -c %s $f`

	# Remove 26 bytes from the file size.  This will become
	# <size> and <vsize>
	S=`echo $fsz - 26 | bc`

	# Grab the flags from the filename.
	F=0x`echo $fname | cut -c 26-27`
#	echo $F

	# Since I'm not a fan of tagging messages for deletion and I
	# prefer moving messages to the trash, any messages marked for
	# deletion will be ignored and simply marked as "not /Seen".
	FLAGS=
        # Flags must be stored in ASCII order: e.g., "2,FRS".
        [[ $DRFT -eq $(( ($F & $DRFT) )) ]] && FLAGS+=D
        [[ $FLGD -eq $(( ($F & $FLGD) )) ]] && FLAGS+=F
        [[ $ANSD -eq $(( ($F & $ANSD) )) ]] && FLAGS+=R
	[[ $SEEN -eq $(( ($F & $SEEN) )) ]] && FLAGS+=S

	# If no flags were found (other than deleted, perhaps)
	# then tag as /Seen
#	[[ -z "$FLAGS" ]] && FLAGS=S

	newname="$DATE.M000000P$PID.$SNAME,S=$S,W=$S:2,$FLAGS"
#	echo "$fname => \n$newname"

	# Special handling for certain mailboxes.
	case $dir in
	inbox)
		NEWDIR=cur
		;;
	sent | Sent)
		NEWDIR=.Sent/cur
		;;
	drafts | Drafts)
		NEWDIR=.Drafts/cur
		;;
	trash | Trash)
		NEWDIR=.Trash/cur
		;;
	junk | Junk)
		NEWDIR=.Junk/cur
		;;
	*)
		NEWDIR=.$dir/cur
		;;
	esac

	# create in new location minus the first line
	# (ie. the icewarp single line header).
	mkdir -p $ODIR/$NEWDIR
	tail -n +2 $f > $ODIR/$NEWDIR/$newname

	# change the access and modified times to match the file
	touch -c -a -m -d @$DATE $ODIR/$NEWDIR/$newname

	echo $ODIR/$NEWDIR/$newname
done

chown -R mail:mail $ODIR

