Skip to content

Instantly share code, notes, and snippets.

@jas8522
Forked from cviebrock/dovecot-maildir-compress.sh
Last active December 15, 2020 21:41
Show Gist options
  • Save jas8522/29223a7c6822b998f0bdd413084b9d37 to your computer and use it in GitHub Desktop.
Save jas8522/29223a7c6822b998f0bdd413084b9d37 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
@jas8522
Copy link
Author

jas8522 commented Apr 18, 2018

Changes:

  • specify maildirlock_bin var to ensure a different binary location is easy to apply
  • Change shebang to bash to ensure the existing kill -s SIGTERM works properly. Running it with sh, it doesn't seem to like SIGTERM on CentOS and therefore leaves the lock in place
  • Plesk maildir base (easier for our use)
  • Include enabling of zlib support in Dovecot. Also enable automatic storage in gzip compressed format for new messages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment