--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+""" Pour supprimer des mails présents en double dans un dossier Imap.
+ Supprimme toujours les doublons les plus lourds.
+
+ Des "doublons" sont des mails qui ont le même Message-Id. """
+
+from __future__ import print_function
+
+import sys
+import os
+import re
+import collections
+import argparse
+import pprint
+
+def get_files(dir):
+ """Donne les fichiers dans le dossier."""
+ l = [os.path.join(dir, f) for f in os.listdir(dir)]
+ return [f for f in l if os.path.isfile(f)]
+
+def message_id(file):
+ """Récupère le message-id du mail"""
+ l = re.findall("^Message-I(?:D|d): <(.*)>", open(file, "r").read(), flags=re.MULTILINE)
+ if l:
+ return l[0]
+
+def finddups(dir, verbose=False):
+ """Trouve les doublons dans ``dir``"""
+ todelete = []
+ l = get_files(dir)
+ d = collections.defaultdict(lambda : [])
+ for f in l:
+ d[message_id(f)].append(f)
+ # On affiche les fichiers pour lesquels on n'a pas réussi à trouver de Message-ID
+ if d[None]:
+ print("Attention : Fichiers sans Message-ID :", file=sys.stderr)
+ for f in d[None]:
+ print(f, file=sys.stderr)
+ # On ne les considère pas comme des doublons
+ del d[None]
+ d = {id : files for (id, files) in d.iteritems() if len(files) > 1}
+ if verbose:
+ print("Doublons trouvés :")
+ pprint.pprint(d)
+ return d
+
+def run(dir, verbose=False, dry=False):
+ """Do the job sur ``dir``"""
+ dups = finddups(dir, verbose)
+ if not dups:
+ print("Aucun doublon trouvé")
+ return
+ if dry:
+ print("**dry-run**, rien ne sera supprimé")
+ for (_, files) in dups.iteritems():
+ sizes = [os.path.getsize(f) for f in files]
+ msize = min(sizes)
+ keep = files[sizes.index(msize)]
+ removes = [f for f in files if f != keep]
+ if verbose or dry:
+ for f in removes:
+ print("Suppression de %s (doublon de %s)" % (f, keep))
+ if not dry:
+ for f in removes:
+ os.remove(f)
+
+parser = argparse.ArgumentParser(description="Suppression de mails identiques.")
+parser.add_argument("-v", "--verbose", help="Afficher ce qui est supprimé", action="store_true")
+parser.add_argument("-n", "--dry-run", help="Faire semblant", action="store_true")
+parser.add_argument("dir", help="Le dossier où chercher les doublons", type=str)
+
+if __name__ == "__main__":
+ args = parser.parse_args()
+ d = run(args.dir, verbose=args.verbose, dry=args.dry_run)