Developing Thunderbird Addons

What to expect

Who's developed Firefox addons already?

Depends on the audience.

This presentation

A demo addon

Customize your main toolbar and add the demo button.

Part one

(for those of you who don't know Thunderbird)

Thunderbird: an old beast

/* ****************************************************************************
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * 
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * 
 * Dear Mortals,
 * 
 * Please be advised that if you are adding something here, you should also
 * strongly consider adding it to the other place it goes too!  These can be
 * found in paths like so: mailnews/.../build/WhateverFactory.cpp
 * 
 * If you do not, your (static) release builds will be quite pleasant, but
 * (dynamic) debug builds will disappoint you by not having your component in
 * them.
 * 
 * Yours truly,
 * The ghost that haunts the MailNews codebase.
 * 
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * 
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION!
 * ****************************************************************************/
 

Thunderbird: an old beast

These guys still look happy!

And they're Thunderbird developers!

Thunderbird: I CAN HAZ FUN

OpenSearch, account provisioner
Big potential for addons!
Everyone likes to have email their own way. Everyone has a strong sense of what email should be. Everyone wants an option to enable their favorite feature.

Part two

(getting started with addons)

Getting started

Demo addon @ http://xulforum.org/fosdem2012

One thing before we get going

Apply every single piece of advice from “Setting up an extension development environment” on MDN.

We're going to use

Basic structure of an addon

myaddon.xpi
|- content/
|- chrome.manifest
\- install.rdf

Of course there's much more. But let's keep it simple.

An overlay: adding elements to the UI

In chrome.manifest:

content demo content/
overlay ↵
 chrome://messenger/content/messenger.xul ↵
 chrome://demo/content/overlay.xul

Adding elements to the UI

In content/overlay.xul:

<overlay id="messengerWindow" xmlns="...">
  <script src="demo.js" />
  <toolbarpalette id="MailToolbarPalette">
    <toolbarbutton id="demo-button"
      class="demo-button toolbarbutton-1"
      label="Demo, yay!" type="button"
      oncommand="Demo.load();"
      />
  </toolbarpalette>
</overlay>

Stuff happening

var Demo = {};

(function () {
  Demo.load = function () {
    let tabmail =
      document.getElementById("tabmail");
    tabmail.openTab("chromeTab", {
      chromePage:
        "chrome://demo/content/main.html",
    });
  };
})();
AMO-Compliant!

(No global namespace pollution.)

Lesson 1: how to open a tab in Thunderbird

You just learnt how to open a tab in Thunderbird.

Many types of tabs: chrome, content, folder, message, as well as your own tab types if you wish.

Lesson 1: now do something with the tab

Part three

before moving on...

Your first enemy: the attacker

Your second enemy: the AMO reviewer

https://wiki.mozilla.org/AMO:Editors/EditorGuide/AddonReviews

One golden rule

Steal as much code as you can.
Parler des trucs un peu tricky sur les nsIMsgDBHdr

Part four

(some cool Thunderbird stuff)

Listing the accounts

Pro trick: Thunderbird (and Seamonkey) have a module called iteratorUtils.js that will help you deal with XPCOM oddities.

 

XPCOM? JSM?

Proof by example

Before:

for (var i = 0; i < accounts.Count(); i++) {
  let account = accounts
    .QueryElementAt(i, Ci.nsIMsgAccount);

After:

for each (let account in
  fixIterator(MailServices.accounts.accounts,
    Ci.nsIMsgAccount)) {

Advantages

STOP IT!

First demo

See the list of accounts in your Thunderbird profile.

Moving on...

We would like to inspect the folders of a given account.

Learn how to use MXR! What is MXR?

Moving on...

Learn how to use MXR!

Second demo

let isInbox =
  folder.getFlag(Ci.nsMsgFolderFlags.Inbox);

A common pattern

Same technique applicable to get the items in an address book (hint: use MailServices.ab.directories, and then directory.childCards).

Now talking about messages

Same old story

Examining a single message

A nsIMsgDBHdr contains everything to display an entry in the message list: date, author, subject, but no attachments, etc.

 

It is also the entry point to modify messages: mark them read, change tags, etc. (use thunderbird-stdlib!).

Examining a single message

However, nsIMsgDBHdrs are just entry points.

 

Solution: get the entire message contents and analyze it. This is called streaming the message.

Streaming a message

MsgHdrToMimeMessage(msgHdr, this,
  function (aMsgHdr, aMimeMsg) {
    if (aMimeMsg.has("reply-to"))
      // do stuff
    let atts = aMimeMsg.allUserAttachments;
    // name, size, content type, url
  }, true, {
    aPartsOnDemand: true,
  });

Streaming a message

Allows one to:

More stuff you can do

Ask me!

Demo...

Bottom part of the second demo.

And now for something completely different

What if you want to search messages? Accross all folders? According to some criterion?

Gloda is your friend

Gloda is your friend

Gloda is your friend

let query = Gloda.newQuery(
  Gloda.NOUN_MESSAGE);
query.subjectMatches(searchTerm);
let myListener = {
  // ...
};
let collection =
  query.getCollection(myListener);

 

The query is asynchronous.

More Gloda

Get the thread a message belongs to

onQueryCompleted: function (aCollection) {
  aCollection.items[0]
    .conversation.getMessageCollection({
      // ...
      onQueryCompleted: function (aColl) {
      },
  });
},

Get all emails involving someone

A small chunk of code

Part four

(just kidding, it's a recap)

Thunderbird add-ons

Final demo: Email Chat

End!

 

Send me an email or post to mozilla.dev.apps.thunderbird with any questions.

 

Q&A session