A Guide to Extensions

How to create extensions for Thunderbird.

An extension is a Thunderbird add-on, that provides additional functionality by adding new user interface elements, alter content, or perform background tasks.

The manifest.json file

The main configuration file of an extension is called manifest.json, also referred to as the manifest. Besides defining some of the extension's basic properties like name, description and ID, it also defines how the extension hooks into Thunderbird:

manifest.json
{
    "manifest_version": 2,
    "name": "Hello World",
    "description": "A basic Hello World extension!",
    "version": "1.0",
    "author": "[Your Name Here]",
    "browser_specific_settings": {
        "gecko": {
            "id": "helloworld@yoursite.com",
            "strict_min_version": "128.0"
        }
    },
    "icons": {
        "64": "images/icon-64px.png",
        "32": "images/icon-32px.png",
        "16": "images/icon-16px.png"
    },
    "background": {
        "page": "background.html"
    },
    "options_ui": {
      "page": "options/options.html",
      "open_in_tab": false,
      "browser_style": true
    },
    "permissions": [
      "storage"
    ]
}

A list of all manifest keys supported by Thunderbird can be found in the following document:

The following manifest keys define basic properties:

  • manifest_version: A mandatory key defining the Manifest version used by the extension. Supported versions are 2 and 3 (since Thunderbird 128). The Manifest defines the basic rules how a WebExtension needs to be crafted and how it can interact with Thunderbird.

  • name : A mandatory key to set the name of the extension.

  • version : A mandatory key to define a number that denotes the version of the extension.

  • description : A brief description of what the extension does.

  • author : The name of a person or company representing the extension developer.

The name and the description of the shown example are only in English. This MDN article about Localization explains how to use the WebExtension i18n API to localize these keys.

The browser_specific_settings.gecko manifest key defines the following properties:

  • strict_min_version: Defines the lowest targeted version of Thunderbird.

  • strict_max_version: Defines the highest targeted version of Thunderbird. It can be set to a specific version or a broader match to limit it to a branch (for example 128.*). Usually only needed if Experiments are included.

  • id: The id serves as a unique identifier for the extension and is mandatory in order upload an extension to ATN or to be able to install it from an XPI file.

Best practice is to use an "email-address-style" id (but not a real email address) on a domain you control, for example name-of-your-addon@example.com, if you own example.com. As the id of your add-on cannot be changed once it is published, it is highly recommended to use a domain that you plan to keep for the forseeable future. If you don't have a domain to use, feel free to use: <atn-user-name>.<add-on-name>@addons.thunderbird.net\

Alternatively, you may use an UUID enclosed in curly braces, for example: {e4aa2097-8ee9-49a4-9ec7-c633b1e8dfda}

Extension Icons

The icons manifest key tells Thunderbird the location of icons, which should be used to represent the MailExtension. Thunderbird supports basic image types like PNG files, but also SVG files. Thunderbird uses different file icon sizes in different places and allows registering a dedicated file for each size. The MailExtension will use the standard puzzle icon, if no icons have been defined.

    "icons": {
        "64": "images/icon-64px.png",
        "32": "images/icon-32px.png",
        "16": "images/icon-16px.png"
    }

Background Page

The extension's background page is loaded in a hidden window when the add-on is started and can be used to load additional JavaScript files.

    "background": {
        "page": "background.html"
    }

The background page specifies the JavaScript files to be loaded:

<html lang="en">
    <head>
        <meta charset="utf-8">
        <script src="common.js"></script>
        <script type="module" src="background.js"></script>
    </head>
    <body>
    </body>
</html>

The type attribute in the shown script tag of background.js defines it as a top level module and enables it to use modern ES6 modules.

Defining one or more background scripts directly

Instead of defining a background page, the extension can specify a simple list of JavaScript files. This will auto-generate a background page and then load the JavaScript files.

    "background": {
        "scripts": [
            "common.js",
            "background.js"
        ],
        "type": "module"
    }

The optional type property in the shown background definition loads all specified scripts as modules, allowing all of them to use ES6 modules.

Options Page

The options_ui manifest key defines the standard MailExtension options page. The defined page will be displayed in the add-on manager by default.

    "options_ui": {
      "page": "options/options.html",
      "open_in_tab": false,
      "browser_style": true
    }

The appearance of the options page can be configured as follows:

  • open_in_tab : Open the options page in a tab instead of inline in the add-on manager.

  • browser_style: Use default browser styles for the options page (recommended).

An inline options page may look as follows:

User Interface Elements

Some UI elements Thunderbird WebExtensions can use are controlled by manifest keys, for example

  • browser_action (renamed to action in Manifest v3)

  • compose_action

  • message_display_action

Further information about these UI elements can be found in the following document:

Permissions

A core principle of the WebExtension technology is the use of permissions, so users can see which areas of Thunderbird an add-on wants to access. Add-on developers can predefine all requested permissions in the permissions manifest key:

    "permissions": [
      "storage"
    ]

Information about required permissions can be found in the following document:

For most permissions, the user must either accept all of the requested permissions during add-on install, or abort the install. Some permissions however can be requested as optional permissions, which can be managed by the user during runtime.

WebExtension Scripts

All JavaScript files loaded by an extension have access to:

  • Standard JavaScript methods

  • Web API (if the browser compatibility chart lists Firefox, the API also works in Thunderbird)

  • WebExtension APIs (see restrictions for content scripts and cloudFile scripts below)

A list of all WebExtension APIs supported by Thunderbird can be found in the following document:

Content Scripts

Content scripts (including compose scripts and message display scripts) can only use the following WebExtension APIs:

Content scripts can communicate with background scripts using runtime messaging, and thereby can indirectly access the WebExtension APIs. See our messageDisplayScript example extension.

CloudFile Management Scripts

A script loaded from a CloudFile management_url can only use the following WebExtension APIs:

CloudFile management scripts can communicate with background scripts using runtime messaging, and thereby can indirectly access the WebExtension APIs.

Experiment APIs

The currently available WebExtension APIs are not yet sufficient, as some areas of Thunderbird are not accessible through these APIs. We are working on improving the situation.

Currently and for the foreseeable future Thunderbird supports Experiment APIs (a.k.a. Experiments), which are WebExtension APIs that are bundled and shipped together with a MailExtension. They interact directly with Thunderbird's internal APIs and allow add-ons to use additional features not yet available via built-in WebExtension APIs.

These additional APIs can be registered in the manifest.json file by defining an implementation script and a schema file describing the interface:

    "experiment_apis": {
        "LegacyPrefs": {
            "schema": "api/LegacyPrefs/schema.json",
            "parent": {
                "scopes": ["addon_parent"],
                "paths": [["LegacyPrefs"]],
                "script": "api/LegacyPrefs/implementation.js",
                "events": ["startup"]
            }
        }
    }

Experiment APIs have full access to Thunderbird's core functions and can bypass the WebExtension permission system entirely. Including one or more Experiment APIs will therefore disable the individual permission prompt and instead prompt the user only for the Have full, unrestricted access to Thunderbird, and your computer permission.

The use of optional permissions is not supported for the same reason.

If you'd like to learn more about experiments, check out this detailed introduction:

Sharing Experiment APIs

Developers can share and re-use Experiments, if their add-ons have similar needs. Before starting to work on your own Experiment, check if any of the following APIs could already provide the functionality you need. Using them and providing feedback to their developers will help to improve these APIs.

Name
Description

Draft for calendar-related APIs in Thunderbird.

Adds missing functionality to add headers to a newly composed message.

Note: Adding X- headers is supported by the compose API since Thunderbird 102.

A generic UI extension framework based on iframes registered at fixed extension points. Note: Does not yet fully support Thunderbird Supernova

Load custom CSS files into Thunderbird windows.

Access Thunderbird system preferences.

Show notifications inside Thunderbird.

Permit WebExtensions to perform (time-limited) cleanup tasks after the add-on is disabled or uninstalled.

TCP support based on ArrayBuffers (currently client side only).

If you have created an Experiment API which you think could be beneficial to other developers, please tell us about it, so we can include it here.

Proposing APIs to be included in Thunderbird

Creating a good WebExtension API for Thunderbird is not an easy task. New APIs need to be generic and distinct from other APIs. Their interfaces have to be designed with foresight as we should avoid scenarios, where we have to make backward incompatible changes later because we have missed something.

If you want to propose and maybe collaborate on a new API, the following process is suggested:

  1. Announcing the idea and a first outline of the suggested API on discuss.thunderbird.net. An actual implementation is not yet needed, but a general concept of how the API is supposed to work is helpful. This allows the add-on developer community to provide feedback and to make sure the design will cover their needs as well.

  2. Publishing a detailed API description, which can be viewed and commented. Google docs have worked quite well (see here and here), but any platform that allows to collaborate will be sufficient. The goal is to shape out the event, function and type definitions of the API.

  3. Creating a tracking bug on bugzilla, referencing the API description, so the core development team is notified and can comment as well.

  4. Publishing a working implementation, so add-on developers can use it and provide feedback.

  5. Adding a patch to the tracking bug and request review.

Last updated