Files
wino-mail-dtkqt/scripts/rethread.py
T

96 lines
2.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Recupera In-Reply-To/References del .eml y recalcula threadId en Wino Mail.
Uso: python3 rethread2.py <bd.sqlite> <carpeta_mails>
"""
import sys, re, sqlite3, os, email
bd = sys.argv[1]
mails_dir = sys.argv[2]
conn = sqlite3.connect(bd)
cur = conn.cursor()
cur.execute("SELECT id, messageId FROM MailCopy")
rows = cur.fetchall()
# indexar emls por message-id en nombre de archivo
eml_by_mid = {}
for root, _, files in os.walk(mails_dir):
for f in files:
if not f.endswith(".eml"):
continue
# nombre base contiene el message-id antes de .eml
base = f[:-4]
eml_by_mid[base] = os.path.join(root, f)
def parse_headers(p):
try:
msg = email.message_from_bytes(open(p, "rb").read())
except Exception:
return None
mid = msg.get("Message-ID", "")
irt = msg.get("In-Reply-To", "")
refs = msg.get("References", "")
return mid, irt, refs
def thread_id(mid, irt, refs):
if refs:
m = re.search(r"<([^>]+)>", refs)
return m.group(1) if m else refs.strip("<>")
if irt:
m = re.search(r"<([^>]+)>", irt)
return m.group(1) if m else irt.strip("<>")
if mid:
m = re.search(r"<([^>]+)>", mid)
return m.group(1) if m else mid.strip("<>")
return ""
upd_thread = 0
upd_irt = 0
upd_refs = 0
not_found = 0
no_headers = 0
for rid, mid in rows:
mid = (mid or "").strip()
# buscar eml: por nombre base == mid, o mid contenido
p = None
if mid in eml_by_mid:
p = eml_by_mid[mid]
if p is None:
# intentar coincidencia parcial (dominio distinto)
mid_nodot = mid.split("@")[0][:20]
for base, path in eml_by_mid.items():
if mid_nodot and mid_nodot in base:
p = path
break
if p is None:
not_found += 1
continue
hdrs = parse_headers(p)
if hdrs is None:
not_found += 1
continue
emid, eirt, erefs = hdrs
tid = thread_id(emid or mid, eirt, erefs)
# guardar headers recuperados
cur.execute("UPDATE MailCopy SET inReplyTo=?, \"references\"=?, threadId=? WHERE id=?",
(eirt.strip() if eirt else "", erefs.strip() if erefs else "", tid or "", rid))
if tid: upd_thread += 1
if eirt.strip(): upd_irt += 1
if erefs.strip(): upd_refs += 1
conn.commit()
print(f"correos: {len(rows)}")
print(f"eml no encontrados: {not_found}")
print(f"inReplyTo recuperado: {upd_irt}")
print(f"references recuperado: {upd_refs}")
print(f"threadId asignado: {upd_thread}")
# agrupar en hilos
print("\n=== hilos detectados (threadId con >1 correo) ===")
cur.execute("SELECT threadId, COUNT(*), MAX(sender) FROM MailCopy WHERE threadId!='' GROUP BY threadId HAVING COUNT(*)>1 ORDER BY COUNT(*) DESC LIMIT 15")
for row in cur.fetchall():
print(row)
conn.close()