Keyconfig JS edit a specific message in Draft ad new message

User Help for Mozilla Thunderbird
Post Reply
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Keyconfig JS edit a specific message in Draft ad new message

Post by matcar »

Hi all, first time for me in this forum.

I use Thunderbird as a full organizer for my job. I have a specific message named "memo" in folder Draft and I'd like to open it as a new message every time I press a specific key on my keyboard. I installed the Dorando Keyconfig plugin and it allows me to perform some operations with useful shortcuts.

So I'm searching a way to use the JS command

Code: Select all

goDoCommand('cmd_editAsNew')
for a specific message, in order to open it automatically for editing without the need to manually select it before.

Thanks for help
Mat
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

Try something like:

Code: Select all

// show msgUri of selected message
var msgHdr = gFolderDisplay.selectedMessage;
var msgUri = msgHdr.folder.getUriForMsg(msgHdr);
alert(msgUri);

Code: Select all

// select folder and message using msgUri, then edit as new
var msgUri = "imap-message://username%40gmail.com@imap.googlemail.com/INBOX#123";
var msgHdr = messenger.msgHdrFromURI(msgUri);
gFolderTreeView.selectFolder(msgHdr.folder);
gFolderDisplay.selectMessage(msgHdr);
goDoCommand("cmd_editAsNew");
Similar thread: http://forums.mozillazine.org/viewtopic ... p=14810679

Keyconfig thread: http://forums.mozillazine.org/viewtopic ... 48&t=72994
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by matcar »

Hi morat, thank you so much for your reply, you solution works very well, I noticed, however, that when I save a message in drafts, thunderbird changes the final number of the URI identifier for that message, so I should change manually every time the number. Does exist a way to identifiy a message in draft with its "Subject"?

Thank you
Regards
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

You are using the edit message as new command.

The original message should have the same uri id and message id. Right?

The new message should have a new uri id and a new message id.

Can you use the message id to select the original message?

Code: Select all

// show folderUri of selected folder
var folder = GetFirstSelectedMsgFolder();
var folderUri = folder.URI;
alert(folderUri);

Code: Select all

// show messageId of selected message
var msgHdr = gFolderDisplay.selectedMessage;
var messageId = msgHdr.messageId;
alert(messageId);

Code: Select all

// select folder using folderUri and select message using messageId
var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
var folder = MailUtils.getFolderForURI(folderUri);
gFolderTreeView.selectFolder(folder);
var messageId = "123456789@example.org";
var msgHdr = folder.msgDatabase.getMsgHdrForMessageID(messageId);
gFolderDisplay.selectMessage(msgHdr);
It is more trouble to use the subject to select the original message.

Code: Select all

// show subject of selected message
var msgHdr = gFolderDisplay.selectedMessage;
var subject = msgHdr.mime2DecodedSubject;
alert(subject);

Code: Select all

// select folder using folderUri and select message using subject
var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
var folder = MailUtils.getFolderForURI(folderUri);
gFolderTreeView.selectFolder(folder);
var subject = "Thank you for contacting Acme Corporation";
var enumerator = folder.messages;
while (enumerator.hasMoreElements()) {
  var msgHdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
  if (msgHdr.mime2DecodedSubject == subject) {
    gFolderDisplay.selectMessage(msgHdr);
    break;
  }
}
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by matcar »

Hi morat, wow it works perfectly! Thank you also for the other code about Subject, no problem I use the ID one.

I take this opportunity to ask you something else (last thing): is it possible (by modifying a little your code) to allow user to open a draft message (in the way you shown me) regardless of the main window currently opened in Thunderbird? I mean, your code works very well if the current displayed window in Thunderbird is the messages main window (where I can select messages in my email account), but if I open Calendar window/tab and I try to programmatically open my draft message for edit, the code selects the right message in Drafts but it can't open it for edit. Can you give me some tips?

Thank you
Regards
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

Try something like:

Code: Select all

// select folder using folderUri and select message using messageId
// regardless of currently focused window
// regardless of currently selected tab
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
  win.focus();
  win.document.getElementById("tabmail").tabContainer.selectedIndex = 0;
  var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
  var folder = win.MailUtils.getFolderForURI(folderUri);
  win.gFolderTreeView.selectFolder(folder);
  var messageId = "123456789@example.org";
  var msgHdr = folder.msgDatabase.getMsgHdrForMessageID(messageId);
  win.gFolderDisplay.selectMessage(msgHdr);
}

Code: Select all

// select folder using folderUri and select message using subject
// regardless of currently focused window
// regardless of currently selected tab
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
  win.focus();
  win.document.getElementById("tabmail").tabContainer.selectedIndex = 0;
  var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
  var folder = win.MailUtils.getFolderForURI(folderUri);
  win.gFolderTreeView.selectFolder(folder);
  var subject = "Thank you for contacting Acme Corporation";
  var enumerator = folder.messages;
  while (enumerator.hasMoreElements()) {
    var msgHdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
    if (msgHdr.mime2DecodedSubject == subject) {
      win.gFolderDisplay.selectMessage(msgHdr);
      break;
    }
  }
}
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by matcar »

Hi morat, thank you very much, everything works very well! I found that instead of "goDoCommand("cmd_editAsNew");" the command "goDoCommand("cmd_editDraftMsg");" is better for my goal, in this way Thunderbird overwrites info on the same message, without creating a lot of new messages with same Subject.

Thanks to your replies, Thunderbird programming has become an interesting thing for me and if it's not too much trouble for you (feel free to reply, I'm using you a little too much ;-)) I'd like to ask you other two things (sorry):

1. Where user can find some documentation (official or unofficial) about how to learn to automate something in Thunderbird by using JS language? For example, how can I know the command for "Mark As Unread" in JS? So, where can user find a table of JS commands for common operations in Thunderbird (like Forward, Forward As, etc...)?

2. About your last code for easily opening a draft message for edit (for me it is a memo message that I modify several times in a day), it works perfectly; I ask you if it is possible to modify your script in order to open the draft message but without changing the current displayed window: I mean, if I'm in Calendar window and I'm editing an event by writing something in the "New Event" window, can I open my draft message "memo" with keyboard shortcut without Thunderbird changing the displayed windows (ie opening the draft message in the background)? For now, when I open my draft message, Thunderbird switches from the current window (for example a new event in Calendar) to the draft message window; but mine is an extra non-fundamental request, I'm just curious to know if it's possible with programming.

Many thanks for your time!
Regards
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

1.

Thunderbird commands
http://forums.mozillazine.org/viewtopic ... &t=2750453

2.

The cmd_editDraftMsg command uses the OpenComposeWindow method to open the compose window.

There is no command to open the compose window in the background.

You can re-focus the original window using a one second delay.

Code: Select all

// select folder using folderUri and select message using subject, then edit message
// regardless of currently focused window
// regardless of currently selected tab
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
  // win.focus();
  win.document.getElementById("tabmail").tabContainer.selectedIndex = 0;
  var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
  var folder = win.MailUtils.getFolderForURI(folderUri);
  win.gFolderTreeView.selectFolder(folder);
  var subject = "Thank you for contacting Acme Corporation";
  var enumerator = folder.messages;
  while (enumerator.hasMoreElements()) {
    var msgHdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
    if (msgHdr.mime2DecodedSubject == subject) {
      win.gFolderDisplay.selectMessage(msgHdr);
      win.goDoCommand("cmd_editDraftMsg");
      setTimeout(function () { window.focus(); }, 1000);
      break;
    }
  }
}
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by matcar »

Hi morat, ok thank you so much for links, saved them as bookmark for future needs!

About your last code, unfortunately, due to my very very little knowledge about programming and javascript, I can't understand how setTimeout command works in order to show the previous active window/tab (before the opening for edit of the draft message). I understand that "setTimeout" executes the function "win.focus()" after 1000 ms. But "win.focus" should be the last active window/tab before the execution of the main code that opens the draft message. Am I right?

I try to explain with following pseudocode what I'd like to translate into JS (but no skill to do it):

1) to save in variable "A" (as example) the current opened window/tab name (for example a window/tab "New Event" of the TB Calendar);
2) to execute your code, for easily opening of a specific draft message (very useful for my purposes);
3) to save in variable "B" the name of the draft message window/tab opened by your main code (point 2);
4) to force Thunderbird (with something like "focus" command, like you suggested me in your last code) to switch to window/tab saved in "A" (point 1);
5) to force Thunderbird to switch to window/tab saved in "B", that is the draft message to be edited (point 3).

After point 5), the current active window/tab, ready to be edited/used, should be the target one (the draft message), and due to point 4, the background window/tab (the one I will see when I close the draft message after modification) should be the last one before the draft message opening (in the example the Calendar "New Event" tab). Am I right?

So, what is the TB JS command for save in a variable the name of active window/tab (maybe "getMostRecentWindow()") in order to focus it when need?

Thank you so much!
Regards
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

I changed the code to re-focus the original window and re-select the original tab using a one second delay.

Code: Select all

// select folder using folderUri and select message using subject, then edit message
// regardless of currently focused window
// regardless of currently selected tab
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
  var index = win.document.getElementById("tabmail").tabContainer.selectedIndex;
  // win.focus();
  win.document.getElementById("tabmail").tabContainer.selectedIndex = 0;
  var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
  var folder = win.MailUtils.getFolderForURI(folderUri);
  win.gFolderTreeView.selectFolder(folder);
  var subject = "Thank you for contacting Acme Corporation";
  var enumerator = folder.messages;
  while (enumerator.hasMoreElements()) {
    var msgHdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
    if (msgHdr.mime2DecodedSubject == subject) {
      win.gFolderDisplay.selectMessage(msgHdr);
      win.goDoCommand("cmd_editDraftMsg");
      setTimeout(function () {
        window.focus();
        win.document.getElementById("tabmail").tabContainer.selectedIndex = index;
      }, 1000);
      break;
    }
  }
}
|win| is the most recently opened 3pane window.

|index| is the selected tab number in the 3pane window, 0 for the left most tab.

|window| is the active window when the keyboard shortcut is pressed.
matcar wrote:save in a variable the name of active window in order to focus it when need?
Examples...

Code: Select all

// show windowtype for currently focused window
var wintype = document.documentElement.getAttribute("windowtype");
alert(wintype);

Code: Select all

// show windowtype for each opened window
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var enumerator = wm.getEnumerator("");
var out = [];
while (enumerator.hasMoreElements()) {
  var win = enumerator.getNext();
  if (win &&
      win.document &&
      win.document.documentElement.hasAttribute("windowtype")) {
    var wintype = win.document.documentElement.getAttribute("windowtype");
    out.push(wintype);
  }
}
alert(out.join("\n"));

Code: Select all

// minimize 3pane window using windowtype
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var wintype = "mail:3pane";
var win = wm.getMostRecentWindow(wintype);
win.minimize();
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by matcar »

Hi morat, thanks for all explanation, but really I'm noticing JS for Thunderbird is not so easy... :?

However the last code I use (= your last code without command "setTimeout" and with "windows.focus" commented) is the following:

Code: Select all

// select folder using folderUri and select message using subject
// regardless of currently focused window
// regardless of currently selected tab
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
    var index = win.document.getElementById("tabmail").tabContainer.selectedIndex;
    win.document.getElementById("tabmail").tabContainer.selectedIndex = 0;
    var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
    var folder = win.MailUtils.getFolderForURI(folderUri);
    win.gFolderTreeView.selectFolder(folder);
    var subject = "Thank you for contacting Acme Corporation";
    var enumerator = folder.messages;
    while (enumerator.hasMoreElements()) {
        var msgHdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
        if (msgHdr.mime2DecodedSubject == subject) {
            win.gFolderDisplay.selectMessage(msgHdr);
            goDoCommand("cmd_editDraftMsg");
            win.document.getElementById("tabmail").tabContainer.selectedIndex = index;
            break;
        }
    }
}
and it works perfectly: the code, regardless of the current displayed tab, opens the draft message without altering the current tab opened. I'm excited!

But there is a small detail that still interests me: even if the current tab is not modified, the very first tab (index=0, that is the tab where user can select different email client sub-tabs like Inbox, Drafts, Trash, etc...) switches always to Drafts tab. I'd like to know if there is a way to save in a var the name of the last tab in index=0 (for example Inbox) before executing the code, in order to return from Draft to that tab.

As always feel free to answer, your code is perfect =D> !

Thank you
Regards
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

I rewrote the code without the cmd_editDraftMsg command or selectFolder method or the selectedIndex property.

Code: Select all

// edit draft message using messageId
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
  var type = Components.interfaces.nsIMsgCompType.Draft;
  var format = Components.interfaces.nsIMsgCompFormat.Default;
  var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
  var folder = win.MailUtils.getFolderForURI(folderUri);
  var messageId = "123456789@gmail.com";
  var msgHdr = folder.msgDatabase.getMsgHdrForMessageID(messageId);
  var msgUri = msgHdr.folder.getUriForMsg(msgHdr);
  var msgArr = [msgUri];
  win.ComposeMessage(type, format, folder, msgArr);
  setTimeout(function () {
    window.focus();
  }, 1000);
}

Code: Select all

// edit draft message using subject
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("mail:3pane");
if (win) {
  var folderUri = "imap://username%40gmail.com@imap.googlemail.com/[Gmail]/Drafts";
  var folder = win.MailUtils.getFolderForURI(folderUri);
  var subject = "Thank you for contacting Acme Corporation";
  var enumerator = folder.messages;
  while (enumerator.hasMoreElements()) {
    var msgHdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr);
    if (msgHdr.mime2DecodedSubject == subject) {
      var type = Components.interfaces.nsIMsgCompType.Draft;
      var format = Components.interfaces.nsIMsgCompFormat.Default;
      var msgUri = msgHdr.folder.getUriForMsg(msgHdr);
      var msgArr = [msgUri];
      win.ComposeMessage(type, format, folder, msgArr);
      setTimeout(function () {
        window.focus();
      }, 1000);
      break;
    }
  }
}
The above examples do not change the selected folder or the selected tab.
matcar
Posts: 7
Joined: July 5th, 2019, 2:10 am

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by matcar »

Hi morat, wonderful, really! The last code is the best one, it doesn't change the current folder in Tab with index=0.

It surprises me a little to know that to open (for editing) a message in drafts, user needs such a complex code (at least for me); this makes me understand that for any other keyboard shortcut, the programming will not be easy, but never mind.

Thank you very much morat for your time and patience, have happy days.
Regards
morat
Posts: 6404
Joined: February 3rd, 2009, 6:29 pm

Re: Keyconfig JS edit a specific message in Draft ad new mes

Post by morat »

You're welcome.
Post Reply