Ștefan-Mihai MOGA
Ștefan-Mihai MOGA

Reputation: 343

Save e-mail body and its attachments from Thunderbird

I'm trying to save the e-mail body and its attachments from javascript using a custom addin, and I'm not able to do it as described in http://forums.mozillazine.org/viewtopic.php?f=19&t=2030903 Do you have any suggestions? Does the e-mail body can be saved into the native EML format? Thank you!

alert("Messages selected: " + gFolderDisplay.selectedCount);
let enumerator = gFolderDisplay.selectedMessages;
for each (let msgHdr in fixIterator(enumerator, Ci.nsIMsgDBHdr)) {
    var messageID = msgHdr.messageId;
    alert("MessageID: " + messageID);
    var subject = msgHdr.mime2DecodedSubject;
    alert("Subject: " + subject);
    MsgHdrToMimeMessage(msgHdr, null, function (aMsgHdr, aMimeMsg) {
        try {
            alert("Size of the message: " + aMimeMsg.size);
            alert("Structure of the message:\n" + aMimeMsg.prettyString(true, undefined, true));
            let attachments = aMimeMsg.allUserAttachments || aMimeMsg.allAttachments;
            alert("Number of attachments: " + attachments.length);
            for (let [index, att] in Iterator(attachments))
            {
                alert ("URL: " + att.url  + " Name: " + att.name);
                let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);  
                let neckoURL = null;  
                neckoURL = ioService.newURI(att.url, null, null);  
                neckoURL.QueryInterface(Ci.nsIMsgMessageUrl);  
                let uri = neckoURL.uri;  
                let attInfo = new AttachmentInfo(att.contentType, att.url, att.name, uri, att.isExternal);
                attInfo.save();
            }
        } catch (err) {
            alert(err);
        }
    }, true, { examineEncryptedParts: true, });
}

[EDIT] The above code does save the attachments but it opens the SaveAs dialog. Can it be done quietly? Does the e-mail body can be saved into the native EML format? Thank you! [/EDIT]

Upvotes: 2

Views: 2184

Answers (1)

Jonathan Protzenko
Jonathan Protzenko

Reputation: 1739

I wrote the example above. You're almost done, and you figured out the hardest parts. Here's what I just did to figure out how to answer your question.

  1. I ran an mxr search on AttachmentInfo which turns out to be defined at http://mxr.mozilla.org/comm-central/source/mail/base/content/msgHdrViewOverlay.js#1643
  2. Turns out save is just a proxy for nsIMessenger::saveAttachment, defined at http://mxr.mozilla.org/comm-central/source/mailnews/base/public/nsIMessenger.idl#81
  3. It also turns out that there's a saveAttachmentToFile method there! Probably what you need. Reading the definition, it seems like a good candidate http://mxr.mozilla.org/comm-central/source/mailnews/base/src/nsMessenger.cpp#614

You probably need to pass the function an already opened nsIFile (see https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile as there's good reference material there), as well as the URI of the attachment (available as uri in your code), the message's uri (probably something along the lines of msgHdr.folder.getUriForMsg(msgHdr)), the content type (att.contentType here), and a listener implementing nsIUrlListener (defined here: http://mxr.mozilla.org/comm-central/source/mailnews/base/public/nsIUrlListener.idl#48, see https://github.com/protz/GMail-Conversation-View/blob/master/modules/message.js#L1492 for a very barebones implementation -- you should probably hook your own functions there to check that everything went fine).

I didn't try this code but I'm pretty confident the guidelines are sound.

Upvotes: 4

Related Questions