Index > Scribe > Recursively Delete Duplicate Messages in nested folders | |
---|---|
Author/Date | Recursively Delete Duplicate Messages in nested folders |
Scott 17/06/2018 6:59am | Is there any way to create a script which recursively calls the DeleteDuplicateMessages() for all the folders contained in the current folder or even the entire mailbox (one folder at a time).
Occasionally, the ISP re-indexes the mail causing quite a few folders to contain duplicates and it's a pain going through each folder to remove the duplicates. |
fret 22/06/2018 8:27am | It's definitely possible, I just haven't had time to explore. You would have to iterate over the ThingContainer.Child and ThingContainer.Next to explore all the sub-folders. Then call the existing function with the folder object. |
fret 25/06/2018 11:29am | So recursive functions in the script engine are broken... sigh. |
fret 30/06/2018 9:18am | I've fixed the recursive functions in the scripting engine. With the next release you will be able to iterate over the folders with this script:
function RecurseFolder(Folder) { Print("Path="+Folder.Path+"\n"); for (c = Folder.Child; c; c = c.Next) { RecurseFolder(c); } } function RecurseFolders(App) { Roots = App.RootFolders; for (i=0; i<Roots.Length; i++) { f = GetFolder(Roots[i]); if (f) { RecurseFolder(f); } } } function Main(App) { if (!AddToolsMenuItem("Recurse Test", "RecurseFolders")) MsgBox(App, "Couldn't add hook for RecurseFolders"); return 1; } Then you could pull in the remove duplicates code from the other script and call it from inside RecurseFolder. |
Scott 30/03/2019 9:02pm | I've created the script (see below) as described, however, it only seems to detect duplicates in some folders. It is supposed to process all mail folders, but if I rerun the script it finds new duplicates in different folders. I have not been able to detect a pattern.
If I search from the App.CurrentFolder, using the commented-out code, I get several of the following errors: Code\ScribeApp.cpp:8412 - No option 'Folder-50' Here is the script: function DeleteDuplicateMessages(Folder) { if (Folder && Folder.ItemType == 0xAAFF0001) { Msgs = New("HashTable"); Dupes = New("List"); Len = Folder.Length; for (i=0; i<Len; i++) { t = Folder.Item[i]; if (t) { Id = t.MessageID; if (Id != NULL) { Existing = Msgs[Id]; if (Existing) { // Decide which email is older if (t.DateReceived < Existing.DateReceived) { // t is earlier, t replaces existing item Dupes[-1] = Existing; Msgs[Id] = t; } else { // existing is earlier, delete t Dupes[-1] = t; } } else { Msgs[Id] = t; } } else Print("No msgid at " + i + "\n"); } else Print("No item at " + i + "\n"); } if (Dupes.Length > 0) { Print("Path="+Folder.Path+"\n"); for (i=0; i<Dupes.Length; i++) { Print("Delete:"+Dupes[i].Subject+"\n"); DeleteThing(Dupes[i]); } } } } function RecurseFolder(Folder) { for (c = Folder.Child; c; c = c.Next) { DeleteDuplicateMessages(c); RecurseFolder(c); } } function RecurseFolders(App) { // Flder = App.CurrentFolder; Flder = App.RootFolders; for (i=0; i<Flder.Length; i++) { f = GetFolder(Flder[i]); Print("Deleting duplicates from Path="+f.Path+"\n"); if (f) { RecurseFolder(f); } } Print("done."+"\n"); } function Main(App) { if (!AddToolsMenuItem("Recursive Dupe Removal", "RecurseFolders")) MsgBox(App, "Couldn't add hook for RecurseFolders"); return 1; } |
Scott 30/03/2019 9:12pm | Hmm, I seem to have missed the trailing "[/pre]". The preview displayed correctly.
I'll send the file in an email. |
Scott 30/03/2019 9:16pm | It seems to be only looking in the current folder. Apart from some extra logging, it does the same thing as the regular delete duplicates script. |
Scott 19/04/2020 1:03am | Using 2.4.13, the recursive Folder.Length is returning 0 for most folders with messages. It works correctly for the default mail box and folders with filters or contacts.
This can be demonstrated in your original script, if you change this line: Print("Path="+Folder.Path+"\n"); with this one: Print("Path="+Folder.Path+":"+Folder.Length+"\n"); |
fret 19/04/2020 9:59am | In here add a 'LoadFolder' call:
function RecurseFolder(Folder) { for (c = Folder.Child; c; c = c.Next) { LoadFolder(c); DeleteDuplicateMessages(c); RecurseFolder(c); } } |
Scott 19/04/2020 11:30am | Thanks, works like a charm. |
Reply | |