Skip to content

Instantly share code, notes, and snippets.

@carstingaxion
Last active March 4, 2023 06:45
Show Gist options
  • Save carstingaxion/0c1604be6943ac9c22f84a3c4b46baaf to your computer and use it in GitHub Desktop.
Save carstingaxion/0c1604be6943ac9c22f84a3c4b46baaf to your computer and use it in GitHub Desktop.
Thunderbird [try to] Signature Update Plugin

Run 1

How should the code for a working plugin for the current version of thunderbird look, that allows a user to set an external URL, from which the referenced default signature gets updated once a day. The URL points to a html page, which should be downloaded and safed. Automatically set the downloaded file as the source for the signature, which gets added to every email by default. The code should follow all relevant coding-standards and best-practices for thunderbird plugins.

// Define the signature object.
var signature = {
url: "", // External URL where the signature is hosted.
html: "", // HTML content of the signature.
filename: "signature.html", // File name to save the signature.
timestamp: 0, // Last updated timestamp.
updateInterval: 86400 // Update interval in seconds.
};
// Function to download the signature from the external URL.
function downloadSignature() {
var req = new XMLHttpRequest();
req.open("GET", signature.url, true);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
signature.html = req.responseText;
saveSignature();
}
};
req.send();
}
// Function to save the signature to disk.
function saveSignature() {
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var signatureFile = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsILocalFile);
signatureFile.append(signature.filename);
var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
outputStream.init(signatureFile, 0x02 | 0x08 | 0x20, 0664, 0);
var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
.createInstance(Components.interfaces.nsIConverterOutputStream);
converter.init(outputStream, "UTF-8", 0, 0);
converter.writeString(signature.html);
converter.close();
signature.timestamp = Date.now() / 1000;
}
// Function to load the signature from disk.
function loadSignature() {
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var signatureFile = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsILocalFile);
signatureFile.append(signature.filename);
if (signatureFile.exists()) {
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
inputStream.init(signatureFile, 0x01, 0444, 0);
var converter = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
converter.init(inputStream, "UTF-8", 0, 0);
var data = "";
var str = {};
while (converter.readString(4096, str)) {
data += str.value;
}
signature.html = data;
signature.timestamp = signatureFile.lastModifiedTime / 1000;
}
}
// Function to update the signature if necessary.
function updateSignature() {
if (Date.now() / 1000 - signature.timestamp > signature.updateInterval) {
downloadSignature();
}
}
// Function to set the signature in outgoing emails.
function setSignature(aIdentity, aComposer) {
updateSignature();
var htmlEditor = aComposer.editor.QueryInterface(Components.interfaces.nsIHTMLEditor);
var htmlNode = htmlEditor.getRootElement();
htmlNode.innerHTML = signature.html;
}
// Register the plugin.
/**
This code adds a new element to the Account Settings dialog with a text field for the external source URL. The value of this field is stored in the signature.url variable and can be edited by the user. The onLoad function sets the initial value of the text field to the current value of signature.url, and the onSave function saves the new value to disk by calling saveSignature(). The validate function is called whenever the user attempts to save the new value and checks that the URL is valid.
Note that you'll need to update the id field of the preferences object to a unique value that doesn't conflict with any existing elements in the Account Settings dialog. Also, you may need to update the validate function to enforce any additional requirements for the external source URL.
*/
// Function to initialize the plugin.
function startup(data, reason) {
// Load the signature from disk.
loadSignature();
// Register the setSignature function as a listener for the compose-send-message event.
var composeSendMsg = Components.classes["@mozilla.org/messengercompose/composesendmessage;1"]
.getService(Components.interfaces.nsIMsgSend);
composeSendMsg.onBeforeSendMsg.addListener(setSignature, false);
// Add a UI element to the Account Settings dialog for the external source URL.
var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"]
.getService(Components.interfaces.nsIMsgAccountManager);
var accountManagerWindow = accountManager.QueryInterface(Components.interfaces.nsIMsgAccountManagerWindow);
accountManagerWindow.registerContentHandler({
id: "signature-external-url",
name: "External Signature URL",
preferences: [{
type: "text",
id: "230227-tsup-url", // "url"
label: "URL:",
validate: function(value) {
if (value.trim() == "") {
return "The URL cannot be blank.";
} else if (!value.startsWith("http://") && !value.startsWith("https://")) {
return "The URL must start with http:// or https://.";
} else {
return "";
}
}
}],
onLoad: function(account) {
this.preferences[0].value = signature.url;
},
onSave: function(account) {
signature.url = this.preferences[0].value.trim();
saveSignature();
}
});
}

Run 2

Please do not rewrite everything, just suggest some working code for the startup() function and how to integrate one element for the external source URL into the existing UI of thunderbird, while still complying to all mentioned standards.

// Define the signature object.
var signature = {
url: "", // External URL where the signature is hosted.
html: "", // HTML content of the signature.
filename: "signature.html", // File name to save the signature.
timestamp: 0, // Last updated timestamp.
updateInterval: 86400 // Update interval in seconds.
};
// Function to download the signature from the external URL.
function downloadSignature() {
var req = new XMLHttpRequest();
req.open("GET", signature.url, true);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
signature.html = req.responseText;
saveSignature();
}
};
req.send();
}
// Function to save the signature to disk.
function saveSignature() {
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var signatureFile = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsILocalFile);
signatureFile.append(signature.filename);
var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
outputStream.init(signatureFile, 0x02 | 0x08 | 0x20, 0664, 0);
var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
.createInstance(Components.interfaces.nsIConverterOutputStream);
converter.init(outputStream, "UTF-8", 0, 0);
converter.writeString(signature.html);
converter.close();
signature.timestamp = Date.now() / 1000;
}
// Function to load the signature from disk.
function loadSignature() {
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var signatureFile = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsILocalFile);
signatureFile.append(signature.filename);
if (signatureFile.exists()) {
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
inputStream.init(signatureFile, 0x01, 0444, 0);
var converter = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
converter.init(inputStream, "UTF-8", 0, 0);
var data = "";
var str = {};
while (converter.readString(4096, str)) {
data += str.value;
}
signature.html = data;
signature.timestamp = signatureFile.lastModifiedTime / 1000;
}
}
// Function to update the signature if necessary.
function updateSignature() {
if (Date.now() / 1000 - signature.timestamp > signature.updateInterval) {
downloadSignature();
}
}
// Function to set the signature in outgoing emails.
function setSignature(aIdentity, aComposer) {
updateSignature();
var htmlEditor = aComposer.editor.QueryInterface(Components.interfaces.nsIHTMLEditor);
var htmlNode = htmlEditor.getRootElement();
htmlNode.innerHTML = signature.html;
}
// Register the plugin.
function startup() {
// Load
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment