How to Fix Email Date-Time After Migration to Dovecot

Many mail clients show wrong email receiving date-time because the file creation time is wrong after migration or restore. Here is a short review on how to fix it for Dovecot on ISPConfig.

For proper email migration, the better solution is to sync all emails over IMAP. I use imapsync. But if emails are already in place with wrong data — it is not all lost, we can fix them.

I copy the script fix_imap_time_for_apple_mail_app.sh AS-IS.

Main script

#!/bin/bash
#
# Date : July 4th, 2005
# Author: Benson Wong
# tummytech@gmail.com
#
# This shell script corrects email messages where the file system
# date does not match the Date: header in the email.
#
# This will fix problems with mail clients like Apple's mail.app
# which uses the file system timestamp resulting in emails with the
# wrong file system timestamp to display the wrong received date
#
# This script has to be run by a user [root] with the
# necessary privileges to read/modify files in a user's Maildir.
#
# To run this script on OSX, first install the coreutils and gawk
# packages from Homebrew or MacPorts.
#

function usage() {
  if [ "$1" != "" ]; then
    echo "$1"
  fi
  echo "Usage: $0 /path/to/user/Maildir"
  exit 1
}

function email_date() {
  local DATELINE=`grep -e "^Date: " "$1" | head -1`
  local DELIVERYDATELINE=`grep -e "^Delivery-date: " "$1" | head -1`
  if [ -n "$DELIVERYDATELINE" ]; then
    local DATELINE="${DELIVERYDATELINE/elivery-d/}"
  fi

  local regex='^Date: ([A-Za-z]{3}, [0-9]{2} [A-Za-z]{3} [0-9]{2,4} [0-9]{1,2}:[0-9]{2}:[0-9]{2}) ([A-Za-z ]*)$'
  if [[ $DATELINE =~ $regex ]]; then
    EDATE=`$DATE -d "${BASH_REMATCH[1]}" "+%Y%m%d%H%M"`
    return 0
  fi

  local regex='^Date: ([A-Za-z]*, [0-9]* [A-Za-z]* [0-9]{4} [0-9]{1,2}:[0-9]{2}:[0-9]{2}) ([0-9]{4})$'
  if [[ $DATELINE =~ $regex ]]; then
    EDATE=`$DATE -d "${BASH_REMATCH[1]} +${BASH_REMATCH[2]}" "+%Y%m%d%H%M"`
    return 0
  fi

  local regex='^Date: ([A-Za-z]*,) (.*)$'
  if [[ $DATELINE =~ $regex ]]; then
    EDATE=`$DATE -d "${BASH_REMATCH[2]}" "+%Y%m%d%H%M"`
    return 0
  fi

  local regex='^Date: (.*)$'
  if [[ $DATELINE =~ $regex ]]; then
    EDATE=`$DATE -d "${BASH_REMATCH[1]}" "+%Y%m%d%H%M"`
    return 0
  fi
}

MDIR_PATH="$1"

if [ -x `which gls` ]; then
  LS=gls
  DATE=gdate
  AWK=gawk
else
  LS=ls
  DATE=date
  AWK=awk
fi

[ $# -lt 1 ] && usage
[ ! -d "$MDIR_PATH" ] && usage "Error: $MDIR_PATH does not exist"
[ ! -r "$MDIR_PATH" ] && usage "Error: $MDIR_PATH is not readable"
[ ! -w "$MDIR_PATH" ] && usage "Error: $MDIR_PATH is not writable"

IFS="
"
set -f
echo "start"

for i in `find $MDIR_PATH -type f | egrep -v "(courierimap|maildirsize|maildirfolder)"`; do
  email_date "$i"
  if [ -z "$EDATE" ]; then
    echo ""
    echo "Unparsable date for" `basename $i`
    continue
  fi
  FDATE=`$LS -l --time-style=long-iso "$i" | $AWK '{print $6,$7}'`
  ODATE=`$DATE -d "$FDATE" "+%Y%m%d%H%M"`
  if [ "$EDATE" -eq "$ODATE" ]; then
    echo -n "."
    continue
  fi
  echo ""
  echo `basename $i` "from $ODATE to $EDATE"
  touch -c -t "$EDATE" "$i"
done

echo ""
echo "done"

This script parses any email in Maildir and changes the file date to the email send date. On CentOS 7, you need to just keep ls, date, and awk.

Keep ls, date and awk

if [ -x `which gls` ]; then
  LS=gls
  DATE=gdate
  AWK=gawk
else
  LS=ls
  DATE=date
  AWK=awk
fi

Add more exception. "dovecot" files.

for i in `find $MDIR_PATH -type f | egrep -v "(courierimap|maildirsize|maildirfolder|dovecot)"`; do

Here you can rewrite to echo, for make some viability.

touch -c -t "$EDATE" "$i"

And after all you need remove cache.

find $1 -name 'dovecot.index.cache' -delete
Human Logic, AI Syntax... Note on Content: I'm a Systems Engineer, not a native English writer. To ensure my technical ideas are clear and accessible, I use AI tools to polish the grammar and style. The workflow is simple: I provide the logic, the code, and the real-world experience. The AI handles the "English-to-Human" translation layer. If you find a bug, that's on me. If you find a perfectly placed comma, that's probably the AI.

Comments

Popular posts from this blog

FreeRadius with Google Workspace LDAP

Fixing pssh (parallel-ssh) Problems on Debian 10 with Python 3.7