Demo Addon

Warning: This content is for older versions of Thunderbird. Much of it may no longer be relevant. See developer.thunderbird.net for newer information.

Overview

This demo add-on has been created by Jonathan Protzenko for his presentation at MozCamp 2011. It shows how to achieve various goals in a working live example, such as working with Gloda.

You can download it at the bottom of the page.

How to use

After installing the demo add-on in Thunderbird, right click on the toolbar and choose "Customize". Drag the "Demo" button into the toolbar. Afterwards, just click that button to show the demo overview.

All three demos are explained in the following sections. Only the interesting parts are shown, it's recommended that you download the add-on and have a look at its files.

The basics

The interesting parts covered in this article are in the content folder. The toolbar button and its functionality are defined in overlay.xul and overlay.js.

We make use of fixIterator(). It is a handy library that keeps your code cleaner and simpler. It lets you iterate over any collection and transforms your collection elements in the given objects, To use fixIterator, you have to import it with Cu.import("resource:///modules/iteratorUtils.jsm");.

Demo 1 - Iterate over all the accounts

This demo is implemented in demo1.html in the content folder. It lists all your email accounts with their account type - either pop3 or imap - and the associated email addresses.

let data = [];
for each (let account in fixIterator(MailServices.accounts.accounts, Ci.nsIMsgAccount)) {
    let info = {
        server: null,
        type: null,
        emails: [],
        name: null,
    };

    let server = account.incomingServer;
    if (server) {
        info.server = server.prettyName;
        info.type = server.type;
    }
    for each (let id in fixIterator(account.identities, Ci.nsIMsgIdentity)) {
        // We're only interested in identities that have a real email.
        if (id.email)
            info.emails.push(id.email);
    }
    data.push(info);
}

First, we use fixIterator() here to get all accounts in your profile. Each account is a nsIMsgAccount.

To get the the server name, we access the incomingServer property of our account, which is a nsIMsgIncomingServer object. From this, we get its name and type.

Because an account can have multiple identities of type nsIMsgIdentity and therefore multiple associated email addresses, with use fixIterator() again to go over all identities and get every email address.

Demo 2 - Find the Inbox

This demo shows various information: It lists all folders of an account (in this case the first one) and marks the inbox folder with a *. Furthermore, it shows some messages in the inbox and lists a random attachment.

We start with listing all folders and marking the inbox:

let server = accounts[0].incomingServer;
let folder = server.rootFolder;
// ...
let inbox;
let print = function (indent, folder) {
    let isInbox = folder.getFlag(Ci.nsMsgFolderFlags.Inbox);
    if (isInbox)
        inbox = folder;
    str += indent + folder.prettiestName + (isInbox ? " *" : "") + "\n";
    if (folder.hasSubFolders)
        for each (let folder in fixIterator(folder.subFolders, Ci.nsIMsgFolder))
            print(indent + "  ", folder);
};
print("  ", folder);

As in the previous example, we get the incomingServer of the account in question. Beginning with the rootFolder, with folder.getFlag(Ci.nsMsgFolderFlags.Inbox) we check whether the folder is the inbox. Then we store the folder name in a string to display it later on the screen and mark it with an * if it is the inbox. Afterwards, we check every folder for subfolders. We then go into each subfolder and start over.

To list some messages of the folder we use:

for each (let msgHdr in fixIterator(inbox.msgDatabase.EnumerateMessages(), Ci.nsIMsgDBHdr)) {
    if (++i >= 10 && lastMsgHdr != null)
        break;

    messages.push({
        author: msgHdr.mime2DecodedAuthor,
        subject: msgHdr.mime2DecodedSubject,
        date: new Date(msgHdr.date/1000),
    });

//...

}

To get a collection of messages in the inbox, we use inbox.msgDatabase.EnumerateMessages(). Each message is a nsIMsgDBHdr. We iterate over the first ten of them and extract author, subject and date for each one.

Demo 3- Search messages by subject

This demo shows how to find messages by a subject accross all folders using Gloda.

let query = Gloda.newQuery(Gloda.NOUN_MESSAGE);
query.subjectMatches(searchTerm);
let myListener = {
    /* called when new items are returned by the database query or freshly indexed */
    onItemsAdded: function myListener_onItemsAdded(aItems, aCollection) {
    },
    /* called when items that are already in our collection get re-indexed */
    onItemsModified: function myListener_onItemsModified(aItems, aCollection) {
    },
    /* called when items that are in our collection are purged from the system */
    onItemsRemoved: function myListener_onItemsRemoved(aItems, aCollection) {
    },
    /* called when our database query completes */
    onQueryCompleted: function myListener_onQueryCompleted(aCollection) {
        let items = aCollection.items;
        let data = {
            messages: [],
        };
        for (let i in items) {
            data.messages.push({
                subject: items[i].subject,
                date: items[i].date,
                author: items[i].from.value,
            });
        // ...
        };
    }
    // ...
  };
let collection = query.getCollection(myListener);

At first, a new Gloda query for finding messages is created. The subject is assigned as search criterion. In the Gloda query result listener the variable aCollection is a GlodaCollections. It contains a collection of GlodaConversation objects which itself is a thread that contains one or more GlodaMessages. For every Gloda message subject, date and author is extracted.

The last line of this example executes the Gloda query.

Download

Demo Addon Download


See also