Un seul echec de dossier (empty response) generait 4 events GlitchTip :
- le bloc de detection de suppression rappelait listMessages quand le
fetch initial avait echoue, forcant une reconnexion IMAP refusee par OVH
(AUTHENTICATIONFAILED, throttling) ;
- chaque echec etait logge 2x en error (provider + service).
Fix :
- garde `if (null !== $remoteHeaders)` autour de la detection de
suppression : si le fetch a echoue, on saute le diff (reprise au
cycle suivant), plus de reconnexion parasite ;
- le log service des MailProviderException passe en warning (le provider
reste la source unique au niveau error pour GlitchTip, couvre aussi les
chemins HTTP).
Net : 1 event GlitchTip par echec de dossier.
Test de regression : testSyncFolderDoesNotRefetchMessagesWhenInitialFetchFails.
Deux causes racines généraient ~170 erreurs/cycle (toutes les 10 min) sur
la prod : "syncFolder[...] listMessages failed: Folder ... not found".
1. Double-encodage UTF7-IMAP : listFolders() stocke le chemin brut UTF7-IMAP,
mais ImapMailProvider rappelait getFolder($path) qui ré-encode UTF8->UTF7-IMAP
(webklex Client::getFolderByPath, utf7=false). Le caractère de shift "&" était
ré-encodé, rendant introuvables les dossiers à accents/specials. Fix :
getFolder($path, null, utf7: true) partout dans ImapMailProvider.
2. Dossiers fantômes jamais purgés : syncFolderStructure() gardait en DB les
dossiers disparus du serveur, re-tentés à chaque cycle. Fix :
syncFolderStructure() retourne le set des chemins présents sur le serveur ;
doSyncAll() skip silencieusement les dossiers DB absents (conservés en DB
pour les liens messages/tâches). Fallback historique si listFolders échoue.
Test : testSyncAllSkipsFoldersNoLongerPresentOnServer.
Trois causes racines révélées par une vraie synchro complète (139 dossiers) :
- contrainte UNIQUE globale sur message_id : fausse pour IMAP (un même Message-ID
existe dans plusieurs dossiers) → violation → fermeture de l'EntityManager →
cascade qui tuait tous les dossiers suivants. Migration : index simple à la place.
- 139 connexions IMAP (une par dossier) → throttling OVH (failed to authenticate) :
réutilisation d'une seule connexion (closeConnection() ajouté à l'interface).
- état de connexion corrompu après un dossier en erreur (must be in SELECTED state) :
reconnexion ciblée après chaque dossier en échec.
- garde anti-cascade : reset du ManagerRegistry + arrêt propre si l'EM se ferme.
Résultat : 456 messages sur 57 dossiers (avant : 188/30 puis crash). Les rares
dossiers à encodage spécial sont skippés proprement et réessayés au cycle suivant.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>