Listening for changes in the address fields - thunderbird

Is there a way for a web extension add-on to listen for address fields changes when message is being edited? I need to listen for "to" address being added or changed.
Tried browser.compose.onComposeStateChanged - it get fired (sporadically) when address editing is started/in progress, but not when the editing is actually done.is

The API is not guaranteed to fire after a user finishes editing the address field.
You could try setTimeout to poll for changes at regular intervals.
let toAddress = "";
browser.compose.onComposeStateChanged.addListener(function (tab) {
browser.compose.getComposedDetails(tab.id).then((details) => {
if (details.to !== toAddress) {
console.log("To field changed: " + details.to);
toAddress = details.to;
}
});
});
You can add this inside the onModify, onRemove, onAdd listeners depending on your needs.

Related

How to stop the user from entering the duplicate record on default save

I have a custom module where there is an email field. Now i want to stop the user if the email is already in the database.
I want to stop the user on save button and show the error. Like when a required field goes empty.
I tried to get some help but was not able to understand it.
Note: I realized after posting this that you are using suitecrm which this answer will not be applicable toward but I will leave it in case anyone using Sugar has this question.
There are a couple of ways to accomplish this so I'll do my best to walk through them in the order I would recommend. This would apply if you are using a version of Sugar post 7.0.0.
1) The first route is to manually create an email address relationship. This approach would use the out of box features which will ensure your system only keeps track of a single email address. If that would work for your needs, you can review this cookbook article and let me know if you have any questions:
https://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_9.2/Cookbook/Adding_the_Email_Field_to_a_Bean/
2) The second approach, where you are using a custom field, is to use field validation. Documentation on field validation can be found here:
https://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_9.2/Cookbook/Adding_Field_Validation_to_the_Record_View/index.html
The code example I would focus on is:
https://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_9.2/Cookbook/Adding_Field_Validation_to_the_Record_View/#Method_1_Extending_the_RecordView_and_CreateView_Controllers
For your example, I would imagine you would do something like this:
Create a language key for your error message:
./custom/Extension/application/Ext/Language/en_us.error_email_exists_message.php
<?php
$app_strings['ERROR_EMAIL_EXISTS_MESSAGE'] = 'This email already exists.';
Create a custom controller for the record creation (you may also want to do this in your record.js):
./custom/modules//clients/base/views/create/create.js
({
extendsFrom: 'RecordView',
initialize: function (options) {
this._super('initialize', [options]);
//reference your language key here
app.error.errorName2Keys['email_exists'] = 'ERROR_EMAIL_EXISTS_MESSAGE';
//add validation tasks
this.model.addValidationTask('check_email', _.bind(this._doValidateEmail, this));
},
_doValidateEmail: function(fields, errors, callback) {
var emailAddress = this.model.get('your_email_field');
//this may take some time so lets give the user an alert message
app.alert.show('email-check', {
level: 'process',
title: 'Checking for existing email address...'
});
//make an api call to a custom (or stock) endpoint of your choosing to see if the email exists
app.api.call('read', app.api.buildURL("your_custom_endpoint/"+emailAddress), {}, {
success: _.bind(function (response) {
//dismiss the alert
app.alert.dismiss('email-check');
//analyze your response here
if (response == '<email exists>') {
errors['your_email_field'] = errors['your_email_field'] || {};
errors['your_email_field'].email_exists = true;
}
callback(null, fields, errors);
}, this),
error: _.bind(function (response) {
//dismiss the alert
app.alert.dismiss('email-check');
//throw an error alert
app.alert.show('email-check-error', {
level: 'error',
messages: "There was an error!",
autoClose: false
});
callback(null, fields, errors);
})
});
},
})
Obviously, this isn't a fully working example but it should get you most of the way there. Hope this helps!

How to intercept incoming email and retrieve message body in thunderbird

In my Thunderbird add-on I want to listen to new incoming emails and process the message body.
So I have written a mailListener and added it to an instance of nsIMsgFolderNotificationService.
The listener works fine and notifies when a mail comes. I get the nsIMsgDBHdr object which was fetched, but I cannot stream the message for the particular folder in the msgAdded function of my mailListener. it hangs, and I cannot even see the message body in the Thunderbird's message pane.
I think the nsISyncStreamListener used to stream the message from the folder waits for OnDataAvailable event which is not yet triggered inside the mailListener's msgAdded function.
Any inputs on how to fetch message body when a new email comes? Below is the code for my mailListener
var newMailListener = {
msgAdded: function(aMsgHdr) {
if( !aMsgHdr.isRead ){
let folder = aMsgHdr.folder;
if(aMsgHdr.recipients == "myemail+special#gmail.com"){
let messenger = Components.classes["#mozilla.org/messenger;1"]
.createInstance(Components.interfaces.nsIMessenger);
let listener = Components.classes["#mozilla.org/network/sync-stream-listener;1"]
.createInstance(Components.interfaces.nsISyncStreamListener);
let uri = aMsgHdr.folder.getUriForMsg(aMsgHdr);
messenger.messageServiceFromURI(uri).streamMessage(uri, listener, null, null, false, "");
let messageBody = aMsgHdr.folder.getMsgTextFromStream(listener.inputStream,
aMsgHdr.Charset,
65536,
32768,
false,
true,
{ });
alert("the message body : " + messageBody);
}
}
}
};
I had a similar problem. The solution I found (not easily) is to use MsgHdrToMimeMessage from mimemsg.js as Gloda is not available yet. This uses the callback function:
var newMailListener = {
msgAdded: function(aMsgHdr) {
if( !aMsgHdr.isRead ){
MsgHdrToMimeMessage(aMsgHdr, null, function (aMsgHdr, aMimeMessage) {
// do something with aMimeMessage:
alert("the message body : " + aMimeMessage.coerceBodyToPlaintext());
//alert(aMimeMessage.allUserAttachments.length);
//alert(aMimeMessage.size);
}, true);
}
}
};
And do not forget to include the necessary module:
Components.utils.import("resource:///modules/gloda/mimemsg.js");
More folow up reading can be found e. g. here.

Updating MongoDB in Meteor Router Filter Methods

I am currently trying to log user page views in meteor app by storing the userId, Meteor.Router.page() and timestamp when a user clicks on other pages.
//userlog.js
Meteor.methods({
createLog: function(page){
var timeStamp = Meteor.user().lastActionTimestamp;
//Set variable to store validation if user is logging in
var hasLoggedIn = false;
//Checks if lastActionTimestamp of user is more than an hour ago
if(moment(new Date().getTime()).diff(moment(timeStamp), 'hours') >= 1){
hasLoggedIn = true;
}
console.log("this ran");
var log = {
submitted: new Date().getTime(),
userId: Meteor.userId(),
page: page,
login: hasLoggedIn
}
var logId = Userlogs.insert(log);
Meteor.users.update(Meteor.userId(), {$set: {lastActionTimestamp: log.submitted}});
return logId;
}
});
//router.js This method runs on a filter on every page
'checkLoginStatus': function(page) {
if(Meteor.userId()){
//Logs the page that the user has switched to
Meteor.call('createLog', page);
return page;
}else if(Meteor.loggingIn()) {
return 'loading';
}else {
return 'loginPage';
}
}
However this does not work and it ends up with a recursive creation of userlogs. I believe that this is due to the fact that i did a Collection.find in a router filter method. Does anyone have a work around for this issue?
When you're updating Meteor.users and setting lastActionTimestamp, Meteor.user will be updated and send the invalidation signal to all reactive contexts which depend on it. If Meteor.user is used in a filter, then that filter and all consecutive ones, including checkLoginStatus will rerun, causing a loop.
Best practices that I've found:
Avoid using reactive data sources as much as possible within filters.
Use Meteor.userId() where possible instead of Meteor.user()._id because the former will not trigger an invalidation when an attribute of the user object changes.
Order your filters so that they run with the most frequently updated reactive data source first. For example, if you have a trackPage filter that requires a user, let it run after another filter called requireUser so that you are certain you have a user before you track. Otherwise if you'd track first, check user second then when Meteor.logginIn changes from false to true, you'd track the page again.
This is the main reason we switched to meteor-mini-pages instead of Meteor-Router because it handles reactive data sources much easier. A filter can redirect, and it can stop() the router from running, etc.
Lastly, cmather and others are working on a new router which is a merger of mini-pages and Meteor.Router. It will be called Iron Router and I recommend using it once it's out!

emit user-specific events for long poll

What's the best way to implement long-polling for user-specific events? I have a "home feed" for each user that I want dynamically updated with new information immediately as it comes in.
Right now I'm making an AJAX call from the client to /register?id=2, for example, to listen for updates. The server itself sends a GET request to /emit?id=2&eventid=3 when some other event(eventid=3) related to user(id=2) occurs. The Node.js server has code similar to below:
var event_emitter = new events.EventEmitter();
http.createServer(function(req,res) {
var uriParse = url.parse(req.url,true);
var pathname = uriParse.pathname;
if (pathname=="/register") {
var userid = uriParse.query.id;
var thisRes = res;
event_emitter.addListener('event'+userid,function(eventid){
if (thisRes) {
console.log(thisRes);
thisRes.writeHead(200, { "Content-Type": "text/plain" });
thisRes.end(eventid);
thisRes = null;
}
});
} else if (pathname=="/emit") {
var userid = uriParse.query.id;
var eventid = uriParse.query.eventid;
event_emitter.emit('event'+userid,eventid);
res.writeHead(200, { "Content-Type": "text/plain" });
res.end('success');
}
}).listen(3000,"0.0.0.0");
So the client's AJAX call doesn't load until the event occurs, at which point the server returns a response with the eventid. The client uses this eventid to make a different AJAX call (unrelated, since I'm using Django for the main application but Node.js for event-driven super-powers).
I'm just bothered by creating so many listeners for "event2" "event454" etc as more users connect. Is this scalable with something like Node.js? How else can I emit user-specific events?
Thanks in advance!
You can remove the listener after emitting the events using removeAllListeners.

KRL - How do you get the value of a watched field?

I am watching a field on a page with a change.
watch("#searchbox","change");
How do you get the new value of the field in the rule that fires after it changes?
I have a rule like this
rule get_update is active {
select when web change "#searchbox"
....
}
I cannot find out how to get the new value. I cannot use watch it with a submit.
Thanks
I am going to guess what I think you are trying to do:
You have an input on a page and when a user types in the input, you want to be able to raise an event and get the new value from the input that the user was typing into so you can react to what ever it is that they typed in.
Based on the assumptions I have made:
The watch action is not what you really want to use because it only raises an event on the action that it is watching and doesn't send any other data along with the event. You will want to write some of your own custom JavaScript to
watch for the user typing
get the new value from the input
raise web event with the new value as a parameter
Here is some sample code taken from http://kynetxappaday.wordpress.com/2010/12/16/day-8-raise-web-events-from-javascript/ that illustrates raising a web event with a parameter in JavaScript
ruleset a60x488 {
meta {
name "raising-custom-web-events"
description <<
raising-custom-web-events
>>
author "Mike Grace"
logging on
}
rule run_on_a_pageview {
select when pageview ".*"
{
notify("Hello","I ran on a pageview") with sticky = true;
emit <|
app = KOBJ.get_application("a60x488");
app.raise_event("custom_event_just_for_me", {"answer":42});
|>;
}
}
rule respond_to_custom_event_raised_from_emitted_js {
select when web custom_event_just_for_me
pre {
answer = event:param("answer");
}
{
notify("What is the answer?",answer) with sticky = true;
}
}
}