How to read mail text in mail listener 2? - protractor

conf.js
var MailListener = require("mail-listener2");
var mailListener = new MailListener({
username: "*****#office365.com",
password: "******",
host: "outlook.office365.com",
port: 993, // imap port
tls: true,
fetchUnreadOnStart: true,
tlsOptions: {rejectUnauthorized: false},
mailbox: "INBOX",
searchFilter: "UNSEEN",
markSeen: true
});
mailListener.on("server:connected", function () {
console.log("imapConnected");
});
mailListener.on("server:disconnected", function () {
console.log("imapDisconnected");
});
(function () {
var count = 0;
mailListener.on("mail", function (mail, seqno, attributes) {
var mailuid = attributes.uid,
toMailbox = 'Inbox',
i = ++count;
if (i > 1) {
mailListener.stop(); // start listening
return;
}
console.log('email parsed', {
i: i,
subject: mail.subject,
from: mail.from,
text:mail.text,
seqno: seqno,
uid: attributes.uid,
attributes: attributes
});
expect(mail.subject).toEqual("FW: Secure One-Time-Password for Account Login");
var pattern = new RegExp(/Please use (\w+)/g);
var regCode = pattern.exec(mail.text)[1];
console.log(regCode);
console.log('attempting to mark msg read/seen');
mailListener.imap.addFlags(mailuid, '\\Seen', function (err) {
if (err) {
console.log('error marking message read/SEEN');
return;
}
//console.log('moving ' + (seqno || '?') + ' to ' + toMailbox);
//mailListener.imap.move(mailuid, toMailbox, function (err) {
if (err) {
console.log('error moving message');
return;
}
console.log('moved ' + (seqno || '?'), mail.subject);
});
});
});
})
();
mailListener.start(); // start listening
setTimeout(function () {
mailListener.stop(); // start listening
}, 60 * 1000);
I am reading all the details except text and the text is in html table format.
Instead of text i am getting undefined message.If needed i will add html code also.
If i am forwarding the same mail to gmail from office 365 and reading the mail from gmail i am able to get text.
Error:
subject: 'test mail',
from: [ { address: 'otp#gmail.com', name: 'gmail.com' } ],
body: undefined,
seqno: 2,
uid: 18,
attributes:
{ date: 2017-06-14T16:22:06.000Z,
flags: [ '\\Seen' ],
uid: 18,
modseq: '3914',
'x-gm-labels': [],
'x-gm-msgid': '1570197813730673685',
'x-gm-thrid': '1570197813730673685' } }
[21:56:13] E/launcher - Cannot read property '1' of null
[21:56:13] E/launcher - TypeError: Cannot read property '1' of null

I see that this is an old issue, but I am facing the same problem and using the nearly the same function.
I want to get the content of the e-mail with a link and the email is in HTML. So: mail.text doesn't and won't work in this case.
Solution is really simple and it works for me straight forward: mail.html

Related

Variables exporting error in MongoDB error

Question
I have provided my code below for reference. I'm using MongoDB and discord.js v12. So basically, I have made a !info command which shows some general info of the user.
What this code does is, it checks through the member's roles, and regarding which role they have, it calculates their total claim time (for giveaways etc.). The problem here, is with the donator role. I can't figure out why I can't use the donates variable outside the db.findOne block. Here, data.content.length shows the total donates of the users, which means donates * 5 is +5 claim time for each donate.
My Code
const moment = require('moment');
module.exports = {
name: 'info',
async execute(client, message, args, Discord){
const member = message.mentions.members.first() || message.guild.members.cache.get(args[0]) || message.member;
const db = require('../models/d-schema');
db.findOne({ guildid: message.guild.id, user: member.user.id }, async(err, data)=>{
if(err) throw err;
if(data){
const donates = parseInt(data.content.length);
}
})
var DefaultTime = 10;
var support = 0;
var donate = 0;
var boost = 0;
const userRoles = member.roles.cache.map((r) => r.name);
if (userRoles.includes("୨・supporter")) {
support = 3;
}
if (userRoles.includes("୨・donator")) {
donate = donates * 5;
}
if (userRoles.includes("୨・booster")) {
boost = 10;
}
const TotalTime = DefaultTime + support + donate + boost;
const embed = new Discord.MessageEmbed()
.setThumbnail(member.user.displayAvatarURL( {dynamic: true} ))
.addFields(
{name: member.user.tag, value: member.user, inline: true},
{name: 'Nickname', value: `${member.nickname !== null ? member.nickname : 'None'}`, inline: true},
{name: 'Is Bot', value: member.user.bot, inline: true},
{name: 'Joined', value: `${moment.utc(member.joinedAt).format("MMMM Do YYYY")}`, inline: true},
{name: 'Created', value: `${moment.utc(member.user.createdAt).format("MMMM Do YYYY")}`, inline: true},
{name: 'Claim Time', value: `${TotalTime} seconds`, inline: true},
)
.setFooter(`ID : ${member.user.id}`)
.setTimestamp()
.setColor('00ffcc')
message.channel.send(embed)
}
}
You cannot use the donates variable because you are declaring it inside the db.findOne() block. This is called variables scope. For better understanding you can read this answer.
If you want to use it outside of that block, you have to declare it beforehand, like this:
let donates;
db.findOne({ guildid: message.guild.id, user: member.user.id }, async(err, data)=>{
if(err) throw err;
if(data){
donates = parseInt(data.content.length);
}
})
Now you're able to use that variable outside of the db.findOne() block :)
Edit:
Alternative way:
It would be easier to use the function asynchronously. That way, everything can be scoped in the same block!
Example:
These two methods will give the same results:
const data = await Model.findOne({ ... });
console.log(data);
Model.findOne({ ... }, (err, data) => {
console.log(data);
});
Suggestion from Lioness100

How we do Exception handling in protractor-cucumber and do a email notification

I am using Protractor-Cucumber framework with protractor 5.2.2 and cucumber 3.2. I have a requirement of posting in no.of locations. So I have written a script in a loop for it. But it randomly fails before completing the loop. So when the script ends abnormally, is there like an exception handling section that gets control before exiting.The script can be fail due to any of the reasons like web driver issue,NoSuchElementError,ElementIsNotIntractable,ElementIsNotVisible etc.So whatever be the issue I have to handle that, and if it fails, I have to do an email notification. I have tried try catch, as given below, but it does not work for me.
When(/^I login$/, function () {
try{
element(by.css(".signin")).click();
var count=post_details.length ;
for (var i=0; i<count; i++){
post();
}
}
catch(e){
console.log("failed");
}
});
How we can do this in protractor-cucumber.Thanks in advance
For the exception problem you can try this. ignoreUncaughtException
For the email part create a hooks.js file. Here you can setup the After() function, to check your scenario fails or not. Cucumber Docs.
Example:
After(function (scenario) {
if (scenario.result.status === Status.FAILED)
{
failed = true;
const attach = this.attach;
//creates a screenshot for the report
return browser.takeScreenshot().then(function(png) {
return attach(new Buffer(png, "base64"), "image/png");
});
}
});
Then you can use nodemailer to send messages. Nodemailer
In your AfterAll() function you can handle the send part.
Example:
AfterAll(function(callback){
console.log("AfterAll");
if (failed)
{
var transporter = nodemailer.createTransport(
{
host: 'host.com',
port: xx,
secure: false,
//proxy: 'http://10.10.10.6:1098',
auth: {
user: userMail,
pass: pw
}
});
var mailOptions = {
from: 'xx', // sender address (who sends)
to: xxxxxx#mail.com',
subject: 'your subject', // Subject line
text: 'Your test failed....', // plaintext body
/*attachments: [
{
filename: 'report.html',
path: htmlReport,
}]*/
};
transporter.sendMail(mailOptions, function(error, info)
{
if(error)
{
return console.log(error);
}
console.log('Email sent: ' + info.response);
console.log(info);
});
} else {
//do your stuff
}
setTimeout(callback, 2000);
});

Loopback Verify User with lb-mandrill-connector: Uncaught AssertionError: template name should be defined

I'm trying to send an email with mandrill through loopback user.verify method but I'm stucked in this error:
Uncaught AssertionError: template name should be defined
Googleing around I found this PR on loopback: https://github.com/strongloop/loopback/pull/1517/files
but it seems that has not been merged as it brake TravisCI tests...
From that PR, I tried this workaround in my code:
let options = {
type: 'email',
port: '80',
to: ac.email,
from: app.get('emailFrom'),
subject: 'Thanks for registering.',
verifyHref: verifyHref,
template: null,
user: ac
};
var template = loopback.template(path.resolve(__dirname, '../../server/views/verify.ejs'));
options.html = template(options);
But it seems that loopback set a default template if no specified, any suggestion?
I'm running on loopback#2.18
The solution here is not to do the user.verify but generate the token and then call user.save and proceed with the call to mandrill.
context.req.app.models.User.generateVerificationToken(user, function (err,token) {
if (err) {
return next(err);
}
user.verificationToken = token;
user.save(function (err) {
if (err) {
next(err);
}
else {
var url = 'http://' + config.host + ':' + config.port + '/api/users/confirm?uid=2&redirect=/&token=' + token;
var mandrill_client = new mandrill.Mandrill('XXXX');
Shouldn't it be
let options = {
type: 'email',
port: '80',
to: ac.email,
from: app.get('emailFrom'),
subject: 'Thanks for registering.',
verifyHref: verifyHref,
template: path.resolve(__dirname, '../../server/views/verify.ejs'),
user: ac
};
user.verify(options, function(err, response) {
if (err) {
next(err);
return;
}
console.log('> verification email sent:', response);
// render the response template
context.res.render('response', {
title: 'Signed up successfully',
content: 'Please check your email and click on the verification link before logging in.',
redirectTo: '/',
redirectToLinkText: 'Log in'
});
});
The loopback method user.verify compiles and renders the ejs template (via loopback.template) and sends the email via the Email datasource. Unfortunately you can't supply a different template engine .. it's hardcoded to ejs. I wanted to use nunjucks so had to override loopback.template to return the render method of nunjucks so that when loopback.template is called from user.verify it works as expected.
I just stumbled accross the issue today. Mandrill provides built-in template functionality where you you provide dynamic templates within your mandrill account and specify variables to populate using the mandrill connector. When template is provided template.name must exist or an assert statement will fail.
This is taken straight from the code:
/**
* Send transactional email with options
*
* Basic options:
*
* {
* from: { name: "evenemento", email: "crew#evenemento.co" },
* to: "hello#evenemento.co",
* subject: "Ho ho",
* text: "Plain text message",
* html: "<b>Html messages</b> put here"
* }
*
* Full list of options are available here:
* https://mandrillapp.com/api/docs/messages.nodejs.html#method=send
*
* if option template is set than message will be send as template:
*
* {
* from: { name: "evenemento", email: "crew#evenemento.co" },
* to: "hello#evenemento.co",
* subject: "Ho ho",
* template: {
* name: "signup-confirm",
* content: {
* name: "NewUser Name",
* accountId: "123456"
* }
* }
* }

Getting error sending email in nodejs with emailjs

[error: can't set headers after they are sent.]
createCredentials() is deprecated, use tls.createSecureContext instead
{[Error: bad response on command '-']
code:2
smtp : '550 5.3.4 Requested action not token; To continue sending messages,
please sign in to your account.\n}
I have been trying to send email in nodejs with emailjs and nodemailer but i keep on getting the error above.
transportEmail: email.server.connect({
user: "ghConnectUs#outlook.com",
password:"******",
host: "smtp-mail.outlook.com",
tls: {ciphers: "SSLv3"}
})
note: i have include all modules.
i'm hoping somebody can point me to the right path. i just want to send me using outlook or gmail in node app.
Below is the code for sending email from nodejs app (through Gmail):
Using Nodemailer v1.3.4:
var nodemailer = require("nodemailer");
var transporter = nodemailer.createTransport({
service: "Gmail",
auth: {
user: "email_id_of_gmail_account",
pass: "password_of_gmail_account"
}
});
var mailOptions = {
from: 'sender_email_id', // sender address
to: 'receiver_email_id, some_other_email_if_requierd', // list of receivers
cc: 'cc_email_id'
subject: 'subject text', // Subject line
text: 'body plain text', // plaintext body
html: '<b>body html</b>' // html body
};
var sendEMail = function () {
transporter.sendMail(mailOptions, function(error, info){
if(error){
console.log(error);
}else{
console.log('Message sent: ' + info.response);
}
});
};
sendEmail();
Note: if you are using Nodemailer version 0.7 or lower, then transporter object will created like this:
var transporter = nodemailer.createTransport('SMTP', {
service: "Gmail",
auth: {
user: "email_id_of_gmail_account",
pass: "password_of_gmail_account"
}
});
Using emailJs v0.3.16:
var email = require("/node_modules/emailjs/email.js");
var server = email.server.connect({
user: "emailId_of_gmail_account",
password: "password_of_gmail_account",
host: "smtp.gmail.com",
ssl: true // in case outlook, use "tls: {ciphers: "SSLv3"}"
});
var message = {
text: "body text",
from: "senderName <sender's_email_id>",
to: "receiverName <receiver_email_id>",
subject: "subject text",
attachment: // optional
[
{data: "<html>i <i>hope</i> this works! html </html>", alternative: true},
{path: "path/to/file.zip", type:"application/zip", name:"renamed.zip"}
]
};
var sendEMail = function () {
server.send(message, function (err, message) {
console.log(err || message);
});
};
sendEmail();

How to change http status codes in Strongloop Loopback

I am trying to modify the http status code of create.
POST /api/users
{
"lastname": "wqe",
"firstname": "qwe",
}
Returns 200 instead of 201
I can do something like that for errors:
var err = new Error();
err.statusCode = 406;
return callback(err, info);
But I can't find how to change status code for create.
I found the create method:
MySQL.prototype.create = function (model, data, callback) {
var fields = this.toFields(model, data);
var sql = 'INSERT INTO ' + this.tableEscaped(model);
if (fields) {
sql += ' SET ' + fields;
} else {
sql += ' VALUES ()';
}
this.query(sql, function (err, info) {
callback(err, info && info.insertId);
});
};
In your call to remoteMethod you can add a function to the response directly. This is accomplished with the rest.after option:
function responseStatus(status) {
return function(context, callback) {
var result = context.result;
if(testResult(result)) { // testResult is some method for checking that you have the correct return data
context.res.statusCode = status;
}
return callback();
}
}
MyModel.remoteMethod('create', {
description: 'Create a new object and persist it into the data source',
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
returns: {arg: 'data', type: mname, root: true},
http: {verb: 'post', path: '/'},
rest: {after: responseStatus(201) }
});
Note: It appears that strongloop will force a 204 "No Content" if the context.result value is falsey. To get around this I simply pass back an empty object {} with my desired status code.
You can specify a default success response code for a remote method in the http parameter.
MyModel.remoteMethod(
'create',
{
http: {path: '/', verb: 'post', status: 201},
...
}
);
For loopback verion 2 and 3+: you can also use afterRemote hook to modify the response:
module.exports = function(MyModel) {
MyModel.afterRemote('create', function(
context,
remoteMethodOutput,
next
) {
context.res.statusCode = 201;
next();
});
};
This way, you don't have to modify or touch original method or its signature. You can also customize the output along with the status code from this hook.