Actually it is doable with FiltaQuilla. (Tried FiltaQuilla 1.1.0, with Thunderbird 3.1.9).
Below is a test script put under "javascript action with body" supplied by FiltaQuilla. It does show all the header properties and the body in the error console.
Once those data fields are available to the code, it needs to traverse through messenger folders and messages to compare them. Maybe using the "threadParent" property on the hdr can simplify the logic, refer to nsIMsgDBHdr on MDC for a hint. In the code, extra properties can be set. For example, set "hdr.myvar='1234'" in the code for duplicated messages, then in a later filter match myvar to 1234 and do a normal action to delete them.
Since this script is the action part of a filter, the condition part of the filter needs to match all messages of interest. In this test the script is arranged after an action to copy the message to a local folder, that may or may not be necessary but it does download the message body to the local machine on an IMAP account so the action will do have a body to access.
//FiltaQuilla filter action script:
for (let index = 0; index < msgHdrs.length; index++)
{ //get msg hdr:
let hdr = msgHdrs.queryElementAt(index, Ci.nsIMsgDBHdr);
//show subject: get it in two ways
let s = hdr.getStringProperty("subject");
if ( s != undefined && s.length != undefined && s.length > 0)
Cu.reportError(" flt log1: " + s.length + " " + s);
Cu.reportError(" flt log2: " + hdr.subject );
//show all properties of hdr: uncomment to show.
//let e = hdr.propertyEnumerator;
//while ( e.hasMore() ) Cu.reportError(" flt log3: " + e.getNext() );
//get body: from an example on MDC: getMessageBody(aMessageHeader)
//Actions configured in the filter: Without [1], it takes long long time.
// [1] copy msg to a local folder.
// [2] "Javascript Action with Body" with this script.
{ let messenger = Components.classes["@mozilla.org/messenger;1"]
.createInstance(Components.interfaces.nsIMessenger);
let listener = Components.classes["@mozilla.org/network/sync-stream-listener;1"]
.createInstance(Components.interfaces.nsISyncStreamListener);
let uri = hdr.folder.getUriForMsg(hdr);
messenger.messageServiceFromURI(uri)
.streamMessage(uri, listener, null, null, false, "");
let folder = hdr.folder;
let body = folder.getMsgTextFromStream(listener.inputStream,
hdr.Charset, 65536, 32768, false, true, { });
//show body:
Cu.reportError(" flt log4: " + body.length + " " + body);
}
}