Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save youri--/93f7e2cc1e525f34b2abdb0ee6ee5b8f to your computer and use it in GitHub Desktop.
Save youri--/93f7e2cc1e525f34b2abdb0ee6ee5b8f to your computer and use it in GitHub Desktop.
Compresses email in maildir format
#!/bin/bash
# Enable zlib in Dovecot alongside automatic writing of new emails in gzipped format
echo '# Enable zlib plugin for reading/writing:
protocol imap {
mail_plugins = $mail_plugins zlib
}
protocol pop3 {
mail_plugins = $mail_plugins zlib
}
# Enable these only if you want compression while saving:
plugin {
zlib_save_level = 6 # 1..9; default is 6
zlib_save = gz # or bz2, xz or lz4
}' > /etc/dovecot/conf.d/10-websavers-compression.conf
# Restart Dovecot
service dovecot restart
## Convert Existing Emails using process described with the pseudocode here: https://wiki.dovecot.org/Plugins/Zlib
##
## <http://ivaldi.nl/blog/2011/12/06/compressed-mail-in-dovecot/>
##
store=/var/qmail/mailnames/
compress=gzip
#compress=bzip2
maildirlock_bin=/usr/libexec/dovecot/maildirlock
find "$store" -type d -name "cur" | while read maildir;
do
tmpdir=$(cd "$maildir/../tmp" &>/dev/null && pwd) || exit 1
find=$(find "$maildir" -type f -name "*,S=*" -mtime +30 ! -name "*,*:2,*,*Z*" -printf "%f\n")
if [ -z "$find" ];
then
continue
fi
echo "Before compression:"
du -b "$maildir"
echo "$find" | while read filename;
do
srcfile="$maildir/$filename"
tmpfile="$tmpdir/$filename"
$compress --best --stdout "$srcfile" > "$tmpfile" &&
# Copy over some things
chown --reference="$srcfile" "$tmpfile" &&
chmod --reference="$srcfile" "$tmpfile" &&
touch --reference="$srcfile" "$tmpfile"
done
# Should really check dovecot-uidlist is in $maildir/..
if lock=$($maildirlock_bin "$maildir/.." 10);
then
# The directory is locked now
echo "$find" | while read filename;
do
flags=$(echo $filename | awk -F:2, '{print $2}')
if echo $flags | grep ',';
then
newname=$filename"Z"
else
newname=$filename",Z"
fi
srcfile=$maildir/$filename
tmpfile=$tmpdir/$filename
dstfile=$maildir/$newname
if [ -f "$srcfile" ] && [ -f "$tmpfile" ];
then
#echo "$srcfile -> $dstfile"
mv "$tmpfile" "$srcfile" &&
mv "$srcfile" "$dstfile"
else
rm -f "$tmpfile"
fi
done
kill -s SIGTERM $lock
echo "After compression:"
du -b "$maildir"
find "$maildir" -type f -name dovecot.index\* -delete
else
echo "Failed to lock: $maildir" >&2
echo "$find" | while read filename;
do
rm -f "$tmpdir/$filename"
done
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment