I've revised the way that my git-mail method for downloading mail works. This system feels much more refined, results in far fewer commits, and resides entirely on the "client," system, which I think makes it easier to reproduce. I need to integrate local mail fetching (i.e. fetchmail) a bit more tightly, and I probably ought to work on porting it to something that isn't zsh/bash.
#!/bin/zsh
# download-mail
# Copyright (c) 2011 Sam Kleinman
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the 'Software'), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
## The following variables reflect the particular configuration of
## your environment. The $THRESHOLD value configures how many new
## messages must arrive on the server before a full sync is executed
## without a "FORCE" argument.
##
## The $REMOTE_HOSTNAME is the server where mail is delivered, and the
## MDIR is the path to the Maildir on both servers.
##
## $MULTI_ENDPOINT forces the remote server to push to a remote with
## the same name as the short hostname (`hostname -s`) of the local
## server. You must configure this manually. If set to 0, all pushes
## and pulls are from/to the "origin" remote.
##
## TODO fix branches in the push/pull for multiple machines.
REMOTE_HOSTNAME="remote.vpn"
THRESHOLD=5
MDIR=~/mail
MULTI_ENDPOINT=0
######################################################################
init-vars(){
COMMIT_MSG='"`hostname`: new messages."'
COMMIT_MSG_LOCAL='"`hostname`: mail changes."'
COMMIT_CMD="git commit -a -q -m"
FILTER="2>&1 | sed 's/^/ /'"
ADD_CMD="git add ."
PUSH_CMD="git push origin master"
PULL_CMD="git pull --rebase -q"
LOCALHOSTNAME=`hostname -s`
if [ $MULTI_ENDPOINT = 1 ]; then
REMOTE_PUSH_CMD="git push $LOCALHOSTNNAME master"
REMOTE_PULL_CMD="git pull --rebase -q $LOCALHOSTNAME master"
REMOTE_CMD="cd $MDIR ; $ADD_CMD ;$COMMIT_CMD $COMMIT_MSG ; $REMOTE_PULL_CMD ; $REMOTE_PUSH_CMD"
REMOTE_PULL="cd $MDIR ; $REMOTE_PULL_CMD ; $REMOTE_PUSH_CMD"
elif [ $MULTI_ENDPOINT = 0 ]; then
REMOTE_CMD="cd $MDIR ; $ADD_CMD ;$COMMIT_CMD $COMMIT_MSG ; $PULL_CMD ; $PUSH_CMD"
REMOTE_PULL="cd $MDIR ; $PULL_CMD ; $REMOTE_PUSH_CMD"
else
echo "Exiting: This script has been incorrectly configured."
xmpp-notify "<$LOCALHOSTNAME> mail *not* synced. There was a configuration error."
fi
NUMCHANGES=`ssh $REMOTE_HOSTNAME "cd ~/mail/; git ls-files -o --exclude-standard | wc -l"`
FORCE_KEYWORD="FORCE"
FORCE_TEST="`echo $@ | grep -i -c \"FORCE\"`"
PULL_TEST="`echo $@ | grep -i -c \"PULL\"`"
}
git-stage-all(){
if [ "`git ls-files -d | wc -l`" -gt "0" ]; then
git rm --quiet `git ls-files -d`
fi
git add .
}
fetch-mail(){
if [ -f ~/.fetchmailrc ]; then
echo -e "## Mail Fetched to #LOCALHOSTNAME from POP servers.\n\n- "
fetchmail
fi
}
msg-complete(){ echo -e "\nStatus: *complete*.\n\n" }
remote-sync(){
echo -e "# git-mail syncronization process \n"
echo -e "There are $NUMCHANGES new messages on $REMOTE_HOSTNAME. \n"
if [ $PULL_TEST = 1 ]; then
echo "## $REMOTE_HOSTNAME: pull"
ssh $REMOTE_HOSTNAME $REMOTE_PULL 2>&1 | sed 's/^/ /'
msg-complete
elif [ $NUMCHANGES -lt $THRESHOLD -a $FORCE_TEST = 0 ]; then
if [ $NUMCHANGES = 0 ]; then
echo -e "Exiting: There are no new messages, and this script requires $THRESHOLD."
xmpp-notify "<$LOCALHOSTNAME> mail *not* synced. There are no new messages, and $THRESHOLD new messages are required for sync." &&
else
echo -e "Exiting: There are $NUMCHANGES new messages, and this script requires $THRESHOLD."
xmpp-notify "<$LOCALHOSTNAME> mail *not* synced. There are $NUMCHANGES of $THRESHOLD new messages required for sync." &&
fi
exit 2
else
echo "## $REMOTE_HOSTNAME: pull, add, commit push"
ssh $REMOTE_HOSTNAME $REMOTE_CMD 2>&1 | sed 's/^/ /'
msg-complete
fi
}
local-sync(){
if [ $PULL_TEST = 1 ]; then
echo -e "## $LOCALHOSTNAME Sync \n\n Skipping the local sync. Commit changes manually, if desired.\n"
else
echo "## $LOCALHOSTNAME: pull; stage-all; commit push"
cd $MDIR
git-stage-all $FILTER
eval $COMMIT_CMD $COMMIT_MSG_LOCAL $FILTER
eval $PULL_CMD $FILTER
eval $PUSH_CMD $FILTER
msg-complete
fi
}
notify(){
echo -e "## Notifications \n"
if [ $PULL_TEST = 1 ]; then
echo "There might be new mail in ~/mail. \n\nIssuing Notification..."
if [ $NUMCHANGES = 0 ]; then
xmpp-notify "<$LOCALHOSTNAME> mail downloaded without sync." &&
else
xmpp-notify "<$LOCALHOSTNAME> mail downloaded. $NUMCHANGES messages not synced." &&
fi
msg-complete
else
echo "There is probably new mail in ~/mail. \n\nIssuing Notification..."
xmpp-notify "<$LOCALHOSTNAME> mail synced. $NUMCHANGES new messages downloaded." &&
msg-complete
fi
}
######################################################################
main(){
init-vars $@
# fetch-mail
remote-sync $@
local-sync
notify $@
}
main $@ &&