⬆️ ⬇️

Writing Addon to Mozilla Thunderbird

Foreword



Finish Exim a little bit (including forcing it to output the results for SPF and DKIM tests to headers).

I decided that it would be good to display this (and not only this information in the mail client itself). And since I didn’t search for additional modules, I immediately started writing my Addon while studying in parallel, as for me, the very tangled DOM \ XUL \ Javascript model of Thunderbird operation.



Formulation of the problem:



What I wanted to see as a result of the add-on? A slightly modified interface where you can see information on DKIM, SPF checks (pass, none, fail, softfail ......), as well as the “X-Spam-Score” indicator that would be displayed as a progress bar and show “ SPAMNOST ”of a specific type of letter, as determined by our server antispam.



Structure



Detailed information on the initial construction of the structure can be obtained here (English) . Therefore, I will only briefly dwell on the details of the organization:

  1. Create install.rdf - where we record all the official information about the addon: Author, title, version, type (extension, theme, etc.), supported versions of Thunderbird, etc.
  2. Create chrome.manifest. Here we describe what resources we will use.
  3. We create a well-defined folder structure from which we need only the \ chrome folder where we put the JavaScript files with logic and XUL files with the description of the visual elements. Which will be discussed in the next chapter


chrome.manifest in my case has the following form:

content signchk chrome/content/

overlay chrome://messenger/content/msgHdrViewOverlay.xul chrome://signchk/content/signchk.xul



here

1. We describe the path to our interface and script files. which inside will be available on the links chrome: // sigchk / content / ...

2. through the overlay keyword, we say that the visual elements contained in the signchk.xul file will be added to msgHdrViewOverlay.xul.



Work interface



To begin, we will create a XUL file with the following content:

 <?xml version="1.0"?> <overlay id="signchk" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <vbox id="singlemessage"> <hbox> <vbox id="SPFbox"> <label id="spfbox_lbl" value="SPF" /> </vbox> <vbox id="DKIMbox"> <label id="dkimbox_lbl" value="DKIM" /> </vbox> <box id="MsgProgressBox" pack="end"> <stack pack="end"> <progressmeter mode="determined" value="0" id="auth_progress" max="70"/> <hbox align="center" pack="center"> <label value="" id="auth_res_lbl" /> </hbox> </stack> </box> </hbox> </vbox> <script type="application/x-javascript" src="chrome://signchk/content/signchk.js" /> </overlay> 


Here, the most important element is the root vbox id = "singlemessage", since it is this that defines the position where our additional elements will be placed. The id of this element itself can be found through the DOM Inspector (an additional component that allows you to walk through the Thunderbird interface element tree).

After we have found this element, then we simply add the interface elements we need and give out conscious id-names so that later we can easily find and manage them.

In the last line we make a link to the javascript file containing the logic of the work.

( Retreat : If anyone wondered why there is xmlns = " www.mozilla.org/keymaster/gatekeeper/there.is.only.xul " - simply because it should be there. If there is something else standing there example like chrome.manifest: chrome: //messenger/content/msgHdrViewOverlay.xul , then rewriting of useful content may occur and you will get just a blank screen.If someone finds this definition more correctly, and writes here, I will only glad)

Work logic



For a start, we will prepare the ground for work:

 const Cc = Components.classes; const Ci = Components.interfaces; const Cr = Components.results; const Cu = Components.utils; var auth_res_lbl; var auth_progress; var spfbox_lbl; var dkimbox_lbl; window.addEventListener('load', function(e) { startup(); },false); function startup() { document.getElementById('threadTree').addEventListener("select",selChange,false); auth_res_lbl = document.getElementById('auth_res_lbl'); auth_progress = document.getElementById('auth_progress'); spfbox_lbl = document.getElementById('spfbox_lbl'); dkimbox_lbl = document.getElementById('dkimbox_lbl'); } 


Here we make synonyms for specific components, declare variables that will correspond to the visual elements created in the previous step, initialize them, and listen to the event of the threadTree element that corresponds to the list of thunderbird messages.

Next we need to get the current message, read it, select the headers and parse them.

Actually this is what the following code does:

 function selChange(event) { var msgHdr = window.gFolderDisplay.selectedMessage; var messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger); var stream = Cc["@mozilla.org/network/sync-stream-listener;1"].createInstance(Ci.nsISyncStreamListener); var sis = Cc['@mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream); var uri = msgHdr.folder.getUriForMsg(msgHdr); sis.init(stream); messenger.messageServiceFromURI(uri).streamMessage(uri, stream, null, null, false, null); var _message = sis.read(sis.available()); var headers = _message.split(/\r\n\r\n|\r\r|\n\n/, 1)[0]; var mimeHeaders = Cc["@mozilla.org/messenger/mimeheaders;1"].createInstance(Ci.nsIMimeHeaders); mimeHeaders.initialize(headers, headers.length); 


After that we can select any title and do whatever we want with it:

  //spam score var res = mimeHeaders.extractHeader("X-Spam-Score", false); if(res) { auth_res_lbl.setAttribute('value',res.split(" ",1)[0]); auth_progress.setAttribute('value',res.split(" ",1)[0]); } else { auth_res_lbl.setAttribute('value',""); auth_progress.setAttribute('value',0); } //spf status res = mimeHeaders.extractHeader("Recieved-SPF", false); if(res) { spfbox_lbl.setAttribute('value',"SPF: "+res.split(" ",1)[0]); } else { spfbox_lbl.setAttribute('value',"SPF: undefined"); } //dkim status (Authentication-Result) res = mimeHeaders.extractHeader("Authentication-Results", false); if(res) { var tmp = res.split(", ",1)[0].split("=")[1]; dkimbox_lbl.setAttribute('value','DKIM: '+tmp); } else { dkimbox_lbl.setAttribute('value',"DKIM: undefined"); } 


')

As a result, we have this:





PS After the work was completed, there was also a workaround for getting headlines - though not so “sporty” and depending on the settings of the thunderbird itself. Use window.currentHeaderData - an array containing the headers of the current message. BUT the content of this variable depends on the menu item View-> Headers . So, if in this clause the display of all headers is selected then currentHeaderData will contain ALL message headers. BUT by default this mode is disabled and you should not hope that it will be enabled for the user as this will affect the display of headers in the message preview window.



Pps

Most of the information was drawn from:

- https://developer.mozilla.org/en/Building_a_Thunderbird_extension

- https://developer.mozilla.org/en/Extensions/Thunderbird/HowTos

- http://old.nabble.com/Mozilla---Thunderbird-f6673.html , and specifically here

Source: https://habr.com/ru/post/127662/



All Articles