Search code examples
javascriptthunderbirdthunderbird-addonthunderbird-webextensions

Uploading a file to remote server from background script in Thunderbird


I am developing a Thunderbird extension that can upload attached files in mail. The flow of the extension is as follows:

  1. Clicking the extension icon shows a popup for selecting one of "Read All", "Read Selected" and "Read Unread" options
  2. When I select an email that contains an attachment and choose "Read Selected" option, the listener for the "Read Selected" onclick event is fired.
  3. The onclick listener sends a message to the background script to handle the upload

Here's the code I have so far:

popup.js

async function readSelected() {
  // this function is invoked by the listener
  const msgList = await browser.mailTabs.getSelectedMessages();
  if(msgList.messages) {
     await browser.runtime.sendMessage({
        caller: 'readSelected',
        messages: msgList.messages
     });
  }
}

background.js

browser.runtime.onMessage.addListener((req, sender, res) => {
  // messages is an Array of MessageHeader objects
  const { caller, accounts, all, messages } = req;
  // ... code for handling other cases
  console.log('Reading selected');
  console.log(messages);
  const ids = [];
  for(const msg of messages) {
      ids.push(msg.id);
  }
  // maps all ids to promises that resolves to MessagePart objects
  Promise.all(ids.map(id => browser.messages.getFull(id)))
    .then(messages => {
        console.log(messages);
    }).catch(e => console.error(e));
});

In the console for background.js, I see that each MessagePart object has a parts array which in turn is an array of MessagePart objects. I can see the name of the attachment (in my case, the selected message has a DOCX file as attachment). Question is, how do I get the file? I need the binary file data because I need to convert it to Base64 string before I can upload to the remote server. I looked at the following SO posts: post1 and post2 but I am not sure how that works since, both posts suggest using nsIFile interface which, requires a URI. There are no such URI for the parts provided.

If more information is needed please ask me in comment and I will update the question (the rest of the code is mostly handling calls for the other options as discussed in (1) above). Some guidelines and help will be highly appreciated. Thanks.


Solution

  • I don't believe this is possible as of this writing. Well, you still have messages.getRaw() that returns you the full source of the message in a promise, including the attachments, but you would have to parse the message again, which is not trivial to do.

    I would suggest to follow, maybe comment on, the relevant Thunderbird issues. I found this one and maybe that one that seem related to your problem.

    Note: The other questions you linked refer to older types of add-ons, not based on WebExtensions API. Although this is not recommended for modern add-ons (because the legacy components may break at any upgrade), it may be possible to access the legacy APIs through so-called experiments, but I have too little experience with those to tell you if they would help you do what you want.