summaryrefslogtreecommitdiff
path: root/fix-mail-duplicates.sh
diff options
context:
space:
mode:
Diffstat (limited to 'fix-mail-duplicates.sh')
-rwxr-xr-xfix-mail-duplicates.sh85
1 files changed, 85 insertions, 0 deletions
diff --git a/fix-mail-duplicates.sh b/fix-mail-duplicates.sh
new file mode 100755
index 0000000..7803649
--- /dev/null
+++ b/fix-mail-duplicates.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+# fix-mail-duplicates.sh
+# Usage: fix-mail-duplicates.sh /path/to/maildir 682
+
+set -e
+
+# Check if arguments were provided
+if [ $# -ne 2 ]; then
+ echo "Usage: $0 /path/to/maildir UID_NUMBER"
+ echo "Example: $0 ~/Mail/ben@bensima.com/Archive 682"
+ exit 1
+fi
+
+MAILDIR="$1"
+UID_NUM="$2"
+
+# Validate the arguments
+if [ ! -d "$MAILDIR" ]; then
+ echo "Error: Maildir '$MAILDIR' does not exist or is not a directory"
+ exit 1
+fi
+
+if ! [[ "$UID_NUM" =~ ^[0-9]+$ ]]; then
+ echo "Error: UID must be a number, got '$UID_NUM'"
+ exit 1
+fi
+
+echo "Looking for duplicate UID $UID_NUM in $MAILDIR..."
+
+# Find all files with the EXACT UID (using word boundaries)
+DUPLICATE_FILES=$(find "$MAILDIR" -type f -name "*,U=$UID_NUM[,:]*")
+FILE_COUNT=$(echo "$DUPLICATE_FILES" | wc -l)
+
+if [ "$FILE_COUNT" -le 1 ]; then
+ echo "No duplicates found. Nothing to fix."
+ exit 0
+fi
+
+echo "Found $FILE_COUNT files with the same UID $UID_NUM"
+
+# Get timestamps for each file to determine which is newer
+declare -A FILE_TIMES
+for f in $DUPLICATE_FILES; do
+ # Get the message Date: header if possible, otherwise use file time
+ if command -v formail >/dev/null 2>&1; then
+ DATE_HDR=$(formail -xDate: < "$f" 2>/dev/null)
+ if [ -n "$DATE_HDR" ]; then
+ # Convert to epoch seconds if possible
+ MSG_TIME=$(date -d "$DATE_HDR" +%s 2>/dev/null)
+ if [ $? -eq 0 ]; then
+ FILE_TIMES["$f"]="$MSG_TIME"
+ continue
+ fi
+ fi
+ fi
+
+ # Fallback to file modification time
+ FILE_TIMES["$f"]=$(stat -c %Y "$f")
+done
+
+# Find the oldest file (we'll keep its UID)
+OLDEST_FILE=""
+OLDEST_TIME=9999999999
+for f in "${!FILE_TIMES[@]}"; do
+ if [ "${FILE_TIMES[$f]}" -lt "$OLDEST_TIME" ]; then
+ OLDEST_TIME="${FILE_TIMES[$f]}"
+ OLDEST_FILE="$f"
+ fi
+done
+
+echo "Keeping original UID on oldest file: $OLDEST_FILE"
+
+# Rename all newer files by removing the UID part
+for f in $DUPLICATE_FILES; do
+ if [ "$f" != "$OLDEST_FILE" ]; then
+ # More precise sed pattern to avoid partial UID matches
+ NEW_NAME=$(echo "$f" | sed "s/,U=$UID_NUM\([,:]\)/, \1/" | sed "s/:2,/,/")
+ echo "Renaming newer duplicate:"
+ echo " From: $f"
+ echo " To: $NEW_NAME"
+ mv "$f" "$NEW_NAME"
+ fi
+done
+
+echo "Fixed UID collision for UID $UID_NUM. Please run mbsync again."