跳到正文
cccskills
免费在 GitHub 公开

thunderbird-extension

Use when developing Thunderbird MailExtensions - Manifest V2/V3 configuration, messenger.* APIs for accounts, messages, folders and compose, UI actions, message display scripts, Experiment APIs, ATN submission, or migration from legacy extensions

中文简介正在准备中。当前显示原文说明。

查看安装方法

包含的文件(5)

  • SKILL.md11.7 KB
  • references/atn-submission.md2.3 KB
  • references/experiment-apis.md3.5 KB
  • references/messenger-apis.md6.8 KB
  • references/testing-migration.md3.7 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Thunderbird MailExtension Development

Complete reference for building, testing, and publishing email extensions for Mozilla Thunderbird.

Overview

Thunderbird extensions use the MailExtension API (based on WebExtensions) with the messenger.* namespace. Thunderbird supports both Manifest V2 and V3 since version 128.

Key Characteristics:

  • Global namespace: messenger (Thunderbird-specific) + browser (standard WebExtensions)
  • Both MV2 and MV3 supported (Thunderbird 128+)
  • Thunderbird-specific APIs: accounts, addressBooks, compose, folders, mailTabs, messages, messageDisplay
  • Submission via ATN (addons.thunderbird.net)

Version Requirements

VersionStatusNotes
128.x (ESR)CurrentFull MV2 + MV3 support
115.xLegacyEnd of support
< 115DeprecatedNot recommended

Best Practice: Set strict_min_version to "128.0"

Manifest Structure

Manifest V3 (Recommended, Thunderbird 128+)

{
  "manifest_version": 3,
  "name": "My Thunderbird Extension",
  "version": "1.0.0",
  "description": "Extension description",
  "author": "Your Name",

  "browser_specific_settings": {
    "gecko": {
      "id": "extension@example.com",
      "strict_min_version": "128.0"
    }
  },

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

  "background": {
    "service_worker": "background.js",
    "type": "module"
  },

  "action": {
    "default_popup": "popup.html",
    "default_title": "My Extension",
    "default_icon": "icons/icon-32.png"
  },

  "permissions": [
    "storage",
    "messagesRead",
    "addressBooks"
  ]
}

Manifest V2 (Still Supported)

{
  "manifest_version": 2,
  "name": "My Thunderbird Extension",
  "version": "1.0.0",
  "author": "Your Name",

  "browser_specific_settings": {
    "gecko": {
      "id": "extension@example.com",
      "strict_min_version": "128.0"
    }
  },

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

  "browser_action": {
    "default_popup": "popup.html",
    "default_title": "My Extension"
  },

  "permissions": [
    "storage",
    "messagesRead",
    "addressBooks"
  ]
}

MV2 vs MV3 Key Differences

FeatureMV2MV3
Toolbar buttonbrowser_actionaction
Backgroundbackground.scriptsbackground.service_worker
Execute scripttabs.executeScriptmessenger.scripting.messageDisplay.executeScript
Compose scriptscomposeScriptsscripting.compose
Contacts APImessenger.contacts.*messenger.addressBooks.contacts.* (vCard only)

All Manifest Keys Reference

Metadata:

  • name (required) - Extension name
  • version (required) - Version string
  • description - Short description
  • author - Author name
  • icons - Extension icons

Thunderbird-Specific:

  • browser_specific_settings.gecko.id - Required for ATN
  • browser_specific_settings.gecko.strict_min_version - Minimum version

Background & Scripts:

  • background - Service worker (MV3) or scripts (MV2)
  • message_display_scripts (MV2) - Scripts for displayed messages

UI Components:

  • action (MV3) / browser_action (MV2) - Main toolbar button
  • compose_action - Compose window toolbar button
  • message_display_action - Message view toolbar button

Permissions:

  • permissions - API permissions
  • experiment_apis - Custom Experiment APIs

Other:

  • commands - Keyboard shortcuts
  • options_ui - Options page

UI Actions (Toolbar Buttons)

Main Toolbar (action / browser_action)

{
  "action": {
    "default_popup": "popup.html",
    "default_title": "My Extension",
    "default_icon": {
      "16": "icons/icon-16.png",
      "32": "icons/icon-32.png"
    }
  }
}
// Listen for clicks (if no popup)
messenger.action.onClicked.addListener((tab) => {
  console.log("Action clicked");
});

// Update badge
await messenger.action.setBadgeText({ text: "5" });
await messenger.action.setBadgeBackgroundColor({ color: "#ff0000" });

// Update icon
await messenger.action.setIcon({ path: "icons/icon-active.png" });

Compose Window (compose_action)

{
  "compose_action": {
    "default_popup": "compose_popup.html",
    "default_title": "Compose Tool",
    "default_icon": "icons/compose-icon.png"
  }
}
// Listen for clicks in compose window
messenger.composeAction.onClicked.addListener((tab) => {
  const details = await messenger.compose.getComposeDetails(tab.id);
  console.log("Compose action clicked:", details.subject);
});

Message Display (message_display_action)

{
  "message_display_action": {
    "default_popup": "message_popup.html",
    "default_title": "Message Tool",
    "default_icon": "icons/message-icon.png"
  }
}
// Listen for clicks on message
messenger.messageDisplayAction.onClicked.addListener(async (tab) => {
  const message = await messenger.messageDisplay.getDisplayedMessage(tab.id);
  console.log("Message action clicked:", message.subject);
});

Message Display Scripts

MV2 Configuration

{
  "message_display_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["message_content.js"],
      "css": ["message_styles.css"]
    }
  ]
}

MV3 Configuration

// In background.js
await messenger.scripting.messageDisplay.executeScript({
  tabId: tabId,
  files: ["message_content.js"]
});

Available APIs in Display Scripts

Limited APIs available:

  • messenger.runtime.connect(), messenger.runtime.sendMessage()
  • messenger.runtime.onConnect, messenger.runtime.onMessage
  • messenger.i18n.getMessage(), messenger.i18n.getAcceptLanguages()
  • messenger.storage.*
// message_content.js
// Send message to background
const response = await messenger.runtime.sendMessage({
  action: "processMessage",
  content: document.body.innerText
});

// Listen for messages from background
messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === "highlight") {
    // Highlight text in message
    document.body.innerHTML = document.body.innerHTML.replace(
      message.text,
      `<mark>${message.text}</mark>`
    );
  }
});

Deep Dives

For detailed reference on specific topics, load these reference files on demand:

  • Messenger APIs - Complete messenger.* API reference (accounts, messages, folders, addressBooks, compose, mailTabs): ./references/messenger-apis.md
  • Experiment APIs - Custom Experiment API development guide: ./references/experiment-apis.md
  • ATN Submission - Publishing workflow and review criteria: ./references/atn-submission.md
  • Testing & Migration - Debugging, testing workflow, and legacy migration: ./references/testing-migration.md

Best Practices

Code Organization

my-extension/
├── manifest.json
├── background.js
├── popup.html
├── popup.js
├── compose_popup.html
├── compose_popup.js
├── api/
│   └── myapi/
│       ├── schema.json
│       └── implementation.js
├── icons/
│   ├── icon-16.png
│   ├── icon-32.png
│   └── icon-64.png
├── _locales/
│   ├── en/
│   │   └── messages.json
│   └── it/
│       └── messages.json
└── README.md

Error Handling

async function safeAsync(fn) {
  try {
    return await fn();
  } catch (error) {
    console.error("Error:", error);
    return { error: error.message };
  }
}

// Usage
const result = await safeAsync(() => messenger.messages.get(messageId));
if (result.error) {
  console.error("Failed to get message:", result.error);
}

Performance

  • Use pagination for large message lists
  • Cache frequently accessed data
  • Debounce rapid events
  • Use messages.query() with filters instead of list() + filter manually

Security

  • Validate all user input
  • Sanitize HTML before display
  • Use minimal permissions
  • Don't store sensitive data in storage.local unencrypted
  • Validate message content before processing

Differences from Firefox WebExtensions

FeatureFirefoxThunderbird
Namespacebrowser.*messenger.* (mail) + browser.* (common)
ContextWeb browserEmail client
Content scriptsWork on web pagesOnly in web tabs, not email content
Main actionbrowser_action / actionSame + compose_action, message_display_action
Mail APIsNoneaccounts, compose, messages, etc.
ExperimentsLimitedCommon for email-specific features
StoreAMOATN

File Structure Template

my-thunderbird-extension/
├── manifest.json
├── background.js
├── popup.html
├── popup.js
├── compose_popup.html
├── compose_popup.js
├── message_popup.html
├── message_popup.js
├── message_content.js
├── styles/
│   └── popup.css
├── icons/
│   ├── icon-16.png
│   ├── icon-32.png
│   └── icon-64.png
├── api/
│   └── myapi/
│       ├── schema.json
│       └── implementation.js
├── _locales/
│   ├── en/
│   │   └── messages.json
│   └── it/
│       └── messages.json
└── README.md

Quick Reference

Essential Permissions

{
  "permissions": [
    "storage",           // Data storage
    "messagesRead",      // Read messages
    "messagesMove",      // Move/copy/delete messages
    "addressBooks",      // Access contacts
    "compose",           // Compose windows
    "accountsRead",      // Read accounts
    "accountsFolders"    // Access folders
  ]
}

Essential APIs

// Messages
messenger.messages.list(folderId)
messenger.messages.get(messageId)
messenger.messages.query({ from, unread })
messenger.messages.update(messageId, { read: true })

// Folders
messenger.folders.get(folderId)
messenger.folders.getSubFolders(account)

// Compose
messenger.compose.beginNew({ to, subject, body })
messenger.compose.getComposeDetails(tabId)

// Address Books
messenger.addressBooks.list()
messenger.addressBooks.contacts.create(addressBookId, { vCard })

// Display
messenger.messageDisplay.getDisplayedMessage(tabId)
messenger.messageDisplayAction.onClicked

Workflow Summary

  1. Develop: Write code, load temporarily
  2. Debug: Use Debug Add-ons → Inspect
  3. Test: Test all functionality
  4. Build: Create .zip with manifest and scripts
  5. Submit: Upload to ATN
  6. Review: Respond to reviewer feedback
  7. Publish: Extension goes live

References

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

aiohttp

免费

Use when building Python async HTTP services or clients with aiohttp - web server routing, middleware, WebSocket, SSE, streaming, client sessions, pytest-aiohttp testing, or troubleshooting SSL and timeout issues

中文简介正在准备中。当前显示原文说明。

CodeAtCode/oss-ai-skills242026年10月9日 更新

ast-grep

免费

Use when doing structural code search and rewriting - ast-grep linting, refactoring, multi-language patterns

中文简介正在准备中。当前显示原文说明。

CodeAtCode/oss-ai-skills242026年10月9日 更新

Use when building GBA games with the BPCore Lua engine - entity, sprite and tilemap functions, SRAM save and load, link cable multiplayer protocol, camera and scrolling, or optimization patterns

中文简介正在准备中。当前显示原文说明。

CodeAtCode/oss-ai-skills242026年10月9日 更新

celery

免费

Use when running background tasks with Celery - worker and broker configuration (Redis, RabbitMQ), task routing by name vs queue, chains/groups/chords, retry patterns (autoretry_for, retry_backoff), acks_late semantics, failure detection, and monitoring with Flower

中文简介正在准备中。当前显示原文说明。

CodeAtCode/oss-ai-skills242026年10月9日 更新

django

免费

Use when building Django applications - security hardening, authentication and permissions, ORM optimization, PostgreSQL features, Django 6.0, migrations, testing, and ecosystem libraries

中文简介正在准备中。当前显示原文说明。

CodeAtCode/oss-ai-skills242026年10月9日 更新

Use when customizing Django Admin - save_formset, get_search_results, formsets, queryset optimization, db_index, custom URLs

中文简介正在准备中。当前显示原文说明。

CodeAtCode/oss-ai-skills242026年10月9日 更新

查看 CodeAtCode 的全部技能

报告此技能的问题