mozilla

Revision 19786 of Thunderbird HowTos

  • Revision slug: Extensions/Thunderbird/HowTos
  • Revision title: Thunderbird HowTos
  • Revision id: 19786
  • Created:
  • Creator: Vor0nwe
  • Is current revision? No
  • Comment 3 words added, 1 words removed

Revision Content

As you develop your extension more and more you will find that there are small, common tasks that you are doing over and over. When you package these into a function, don't forget to come through here and add them to the list, for other people’s benefit! Some of these How-Tos may apply to Firefox development, though the main focus is on Thunderbird-specific information.

Detecting when a folder is opened

Some actions require execution every time you open a folder (for example, registering a custom column handler. To do this you need to capture the select event of the folder [{{ mediawiki.external('XUL:tree|tree') }} whose id is (conveniently) folderTree like so:

window.document.getElementById('folderTree').addEventListener("select", testColumns, false);

Accessing a stringbundle from an overlay

Stringbundles are handy for localizing your project by removing all of your strings into a separate, easy to access text file. Unfortunately adding the bundles into Thunderbird isn't as easy as adding them to your XUL overlay. The most efficient way to append these strings is by attaching them to an existing stringbundleset as such:

<stringbundleset id="stringbundleset">
  <stringbundle src="chrome://your_extension/locale/overlay.properties" id="your-extension-strings" /> 
</stringbundleset>

Now that your stringbundle is attached you can access it from JavaScript as follows:

var str = document.getElementById("your-extension-strings"); //get the stringbundle object itself 
str.getString("propertyName");                                 //get a string (and do something with it) 

How do I watch for new Mail?

This question was originally answered in the news groups, see the original answer for more background.

Thunderbird2 gives us the nsiMsgFolderNotificationService interface which we pass a nsIMsgFolderListener interface to receive the events we want.

 var newMailListener = {
   itemAdded: function(item){   
     alert("Got mail.  Look at item's properties for more details.");
     var hdr = item.QueryInterface(Components.interfaces.nsIMsgDBHdr);
   }
 }
 function init() {
   var notificationService = Components.classes["@mozilla.org/messenger/msgnotificationservice;1"].getService(Components.interfaces.nsIMsgFolderNotificationService);
   notificationService.addListener(newMailListener); 
 }

How do I use an SQLite database in my Thunderbird extension?

If you'd like to use an SQLite database in your extension you'll need to look over the Storage docs for an API reference, however this code should get you started. Be careful of multi-thread access to your database.

This will create an SQLite db named tbird.sqlite inside your profile directory with a table called attachments. You can see the schema for the attachments table in the code. To double check the information you've inserted you can query the tbird.sqlite file using regular SQLite programs.

const Cc = Components.classes;
const Ci = Components.interfaces;

var tbirdsqlite = {

  onLoad: function() {
    // initialization code
    this.initialized = true;
    this.dbInit();
  },

  dbConnection: null,

  dbSchema: {
     tables: {
       attachments:"id           INTEGER PRIMARY KEY, \
                    name         TEXT \
                    encoded      TEXT NOT NULL"
    }
  },

  dbInit: function() {
    var dirService = Cc["@mozilla.org/file/directory_service;1"].
      getService(Ci.nsIProperties);

    var dbFile = dirService.get("ProfD", Ci.nsIFile);
    dbFile.append("tbird.sqlite");

    var dbService = Cc["@mozilla.org/storage/service;1"].
      getService(Ci.mozIStorageService);

    var dbConnection;

    if (!dbFile.exists())
      dbConnection = this._dbCreate(dbService, dbFile);
    else {
      dbConnection = dbService.openDatabase(dbFile);
    }
    this.dbConnection = dbConnection;
  },

  _dbCreate: function(aDBService, aDBFile) {
    var dbConnection = aDBService.openDatabase(aDBFile);
    this._dbCreateTables(dbConnection);
    return dbConnection;
  },

  _dbCreateTables: function(aDBConnection) {
    for(var name in this.dbSchema.tables)
      aDBConnection.createTable(name, this.dbSchema.tables[name]);
  },
};
window.addEventListener("load", function(e) { tbirdsqlite.onLoad(e); }, false);

Access Particular Parts of the Thunderbird Window

To access particular parts of the Thunderbird window you can use these helper methods. An alternative to these methods is to directly access the element by it's ID as in the #Detecting when a folder is opened example.

 var folderTree = GetFolderTree();
 var searchInput = GetSearchInput();
 var messagePane = GetMessagePane();
 var messagePaneFrame = GetMessagePaneFrame();
 var mailToolBox = getMailToolbox();
 var currentMsgFolder = GetLoadedMsgFolder();

see the msgMail3PaneWindow.js for other helper methods

Revision Source

<p>As you develop your extension more and more you will find that there are small, common tasks that you are doing over and over. When you package these into a function, don't forget to come through here and add them to the list, for other people’s benefit! Some of these How-Tos may apply to Firefox development, though the main focus is on Thunderbird-specific information.</p>
<h3 name="Detecting_when_a_folder_is_opened">Detecting when a folder is opened</h3>
<p>Some actions require execution every time you open a folder (for example, registering a <a href="/en/Extensions/Thunderbird/Creating_a_Custom_Column" title="en/Extensions/Thunderbird/Creating_a_Custom_Column">custom column handler</a>. To do this you need to capture the <strong>select</strong> event of the folder [{{ mediawiki.external('XUL:tree|tree') }} whose id is (conveniently) <strong>folderTree</strong> like so:</p>
<pre>window.document.getElementById('folderTree').addEventListener("select", testColumns, false);</pre>
<h3 name="Accessing_a_stringbundle_from_an_overlay">Accessing a stringbundle from an overlay</h3>
<p><a href="/en/XUL/stringbundle" title="en/XUL/stringbundle">Stringbundles</a> are handy for localizing your project by removing all of your strings into a separate, easy to access text file. Unfortunately adding the bundles into Thunderbird isn't as easy as adding them to your <a href="/en/XUL" title="en/XUL">XUL</a> overlay. The most efficient way to append these strings is by attaching them to an existing <a href="/en/XUL/stringbundleset" title="en/XUL/stringbundleset">stringbundleset</a> as such:</p>
<pre class="eval">&lt;stringbundleset id="stringbundleset"&gt;
  &lt;stringbundle src="<a class=" external" href="chrome://your_extension/locale/overlay.properties" rel="freelink">chrome://your_extension/locale/overlay.properties</a>" id="your-extension-strings" /&gt; 
&lt;/stringbundleset&gt;
</pre>
<p>Now that your <a href="/en/XUL/stringbundle" title="en/XUL/stringbundle">stringbundle</a> is attached you can access it from JavaScript as follows:</p>
<pre class="eval">var str = document.getElementById("your-extension-strings"); //get the stringbundle object itself 
str.getString("propertyName");                                 //get a string (and do something with it) 
</pre>
<h3 name="How_do_I_watch_for_new_Mail.3F">How do I watch for new Mail?</h3>
<p><em>This question was originally answered in the news groups, see <a href="/en/Extensions/Questions_and_answers_from_the_newsgroups_2006_11_24#Is_it_possible_to_get_the_event_if_a_mail_has_been_received_in_thunderbird.3F" title="en/Extensions/Questions_and_answers_from_the_newsgroups_2006_11_24#Is_it_possible_to_get_the_event_if_a_mail_has_been_received_in_thunderbird.3F"> the original answer</a> for more background.</em></p>
<p>Thunderbird2 gives us the <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIMsgFolderNotificationService.html">nsiMsgFolderNotificationService</a> interface which we pass a <a class="external" href="http://www.xulplanet.com/references/xpcomref/ifaces/nsIMsgFolderListener.html">nsIMsgFolderListener</a> interface to receive the events we want.</p>
<pre class="eval"> var newMailListener = {
   itemAdded: function(item){   
     alert("Got mail.  Look at item's properties for more details.");
     var hdr = item.QueryInterface(Components.interfaces.nsIMsgDBHdr);
   }
 }
</pre>
<pre class="eval"> function init() {
   var notificationService = Components.classes["@mozilla.org/messenger/msgnotificationservice;1"].getService(Components.interfaces.nsIMsgFolderNotificationService);
   notificationService.addListener(newMailListener); 
 }
</pre>
<h3 name="How_do_I_use_an_SQLite_database_in_my_Thunderbird_extension.3F">How do I use an SQLite database in my Thunderbird extension?</h3>
<p>If you'd like to use an SQLite database in your extension you'll need to look over the <a href="/en/Storage" title="en/Storage">Storage</a> docs for an API reference, however this code should get you started. Be careful of <a href="/en/Storage#How_to_corrupt_your_database" title="en/Storage#How_to_corrupt_your_database">multi-thread access</a> to your database.</p>
<p>This will create an SQLite db named <strong>tbird.sqlite</strong> inside your profile directory with a table called <em>attachments</em>. You can see the schema for the attachments table in the code. To double check the information you've inserted you can query the <em>tbird.sqlite</em> file using regular SQLite programs.</p>
<pre>const Cc = Components.classes;
const Ci = Components.interfaces;

var tbirdsqlite = {

  onLoad: function() {
    // initialization code
    this.initialized = true;
    this.dbInit();
  },

  dbConnection: null,

  dbSchema: {
     tables: {
       attachments:"id           INTEGER PRIMARY KEY, \
                    name         TEXT \
                    encoded      TEXT NOT NULL"
    }
  },

  dbInit: function() {
    var dirService = Cc["@mozilla.org/file/directory_service;1"].
      getService(Ci.nsIProperties);

    var dbFile = dirService.get("ProfD", Ci.nsIFile);
    dbFile.append("tbird.sqlite");

    var dbService = Cc["@mozilla.org/storage/service;1"].
      getService(Ci.mozIStorageService);

    var dbConnection;

    if (!dbFile.exists())
      dbConnection = this._dbCreate(dbService, dbFile);
    else {
      dbConnection = dbService.openDatabase(dbFile);
    }
    this.dbConnection = dbConnection;
  },

  _dbCreate: function(aDBService, aDBFile) {
    var dbConnection = aDBService.openDatabase(aDBFile);
    this._dbCreateTables(dbConnection);
    return dbConnection;
  },

  _dbCreateTables: function(aDBConnection) {
    for(var name in this.dbSchema.tables)
      aDBConnection.createTable(name, this.dbSchema.tables[name]);
  },
};
window.addEventListener("load", function(e) { tbirdsqlite.onLoad(e); }, false);
</pre>
<h3 name="Access_Particular_Parts_of_the_Thunderbird_Window">Access Particular Parts of the Thunderbird Window</h3>
<p>To access particular parts of the Thunderbird window you can use these helper methods. An alternative to these methods is to directly access the element by it's ID as in the <a href="#Detecting_when_a_folder_is_opened">#Detecting when a folder is opened</a> example.</p>
<pre class="eval"> var folderTree = GetFolderTree();
 var searchInput = GetSearchInput();
 var messagePane = GetMessagePane();
 var messagePaneFrame = GetMessagePaneFrame();
 var mailToolBox = getMailToolbox();
 var currentMsgFolder = GetLoadedMsgFolder();
</pre>
<p><em>see the <a class="external" href="http://mxr.mozilla.org/mozilla/source/mail/base/content/msgMail3PaneWindow.js#1254">msgMail3PaneWindow.js</a> for other helper methods</em></p>

<div style="border: 1px dashed grey; padding: 2px; position: absolute; display: inline; visibility: hidden; font-family: arial,sans-serif; font-size: 9px;"><img alt="" src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAWCAYAAAAfD8YZAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAABd0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYyLjW8h8n+AAADKUlEQVQ4T5WT/U+aVxTHm/pb/4Jlf8L+if05S5Z0WbqtWbPauFotrR1aRVQQEORNivUFtYoFBSpqi0pB8KXV4gsyK4qKqIDw2X1YIjbYJTvJfe597j2fc77n3Oe5ceMaA74X46rdvM6vYq9YLJJOn95NHaX5e3efvWRq4fw8R1VV1bf/GUACUwdHGA02/qx+RFurCr3OjM0+RCi8TD5/wbUBJDC6tEZdfSNtSu3I9vbOd9JePp/Hanph+O33WoILYaS9LwJIxWUyZww5XqHTWUoOkklOYroprd0uL+rOLpLJg8uzUhDpLbaxg7Klg/39VIU0cfxNLpdHJmsiEAhVwlP+eYf8WQvn2ey1dUmEUqkrmMy9lfBrt9/R1KQgm8t9FTZ09xbaVfpKeOSVN9yqUCHJ+8rdYzC+LDxvVn8JSw3yemboUKrICtkX+dytYuHiclAs3JJ8jEYbjY2KzGXHpTAhj2X9w1Q3u5EBjj+OkYnPkD2MkE0GySRmOY5Pk1hxEvXb8Pa3YFHe/ze79Fj0mteXfF0kQnbSa6OcbnjI7wU42/aRWh1lJ/iC6KSaqb6/GNbX0t34axkOe4zrK2/0wsnG8YcRMpsesiLjqZiTEQdbAQthVzteewNDuhr08l/KcNDdtRWZ1LA9Z+FwdZj0JzdncX9p/hzpJ/bWxPtxJZO2Jzi0NXTJ71yBXRpK8LyFg2WHgFycJ6ZF5kk+L/ay+c5McEwhYJmAH6Br+LkML7zWsOTVEhfw4aqDk9iEkD0t5E+wJ5q48c5E0NmKu6eeAc0DtFfhOWcHSz4dO+97RM3DnG2JmndnhHQfe9FBNgMis1OJ2/pYwNVonl7JHBhVsuzTEA9aOVgZJB0TNYvMJyLz7mIfsVkDC0K2y1JHf2c1nU9+Kst+O9JCxKNma95MSoJFo0qyRZBEuJdPs93MjzUzbq6lT30ftex2GZ4alBOa6GBzzkQy2sfR2riQ/oaTjQmhxs5Hv5YZ4TNmfIi9/R5tj34sw/26+rxD/5hRkwyXTY6r5zlOayvjPc0MaOt4qarBqvgD7dM7KB7epuHeD+Xvu7T6nyb9PP8AgwuHCQc/gYgAAAAASUVORK5CYII=" style="display: inline;">

</div>
Revert to this revision