Problem with using nodemailer to send email to user on Actions on Google, Dialogflow - actions-on-google

I am using nodemailer to send emails to users, when an intent is triggered.
I am creating a promise for the function to send emails using nodemailer.
When running with node index.js, the emails are sent, but when deploying to firebase and invoking the intent with the simulator on actions on google console, i get a webhook error
MalformedResponse
Failed to parse Dialogflow response into AppResponse because of empty speech response.
Here is my code:
When the user invokes this intent, they should receive an email from me.
let sendMails = () => {
return new Promise((resolve, reject) => {
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'my email',
pass: 'password'
}
});
let mailOptions = {
from: 'my email',
to: 'user's email',
subject: 'something',
text: 'here is the email'
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
throw new Error("Error has come");
} else {
let answer = info.response;
return resolve(answer);
// console.log('Email sent: ' + info.response);
}
});
}).catch(error => {
console.log(error);
throw new Error("Error is coming")
})
}
And here is the intent:
app.intent('nda - yes', conv => {
return sendMails().then((answer)=> {
return conv.ask(`<speak>Done. Email is sent. Check your inbox.</speak>`)
})
})`

Related

Unable to receive mail sent via sendgrid

I'm creating a contact form using Nextjs and SendGrid, according to this header status
202
{
server: 'nginx',
date: 'Thu, 08 Dec 2022 16:29:25 GMT',
'content-length': '0',
connection: 'close',
'x-message-id': 'CaVdpVAURza6JrUF7yIQQA',
'access-control-allow-origin': 'https://sendgrid.api-docs.io',
'access-control-allow-methods': 'POST',
'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-
of, x-sg-elas-acl',
'access-control-max-age': '600',
'x-no-cors-reason':
'https://sendgrid.com/docs/Classroom/Basics/API/cors.html',
'strict-transport-security': 'max-age=600; includeSubDomains'
}
the email is sent but I find nothing in my inbox,
and this error occurs in the terminal
API resolved without sending a response for /api/contact, this may result in stalled requests.
I don't know what mistake I've done but. I invite you to look at my code bellow:
API :
import sgMail from "#sendgrid/mail";
export default function handler(req, res) {
if (req.method !== "POST") {
res.status(405).json({ message: "INVALID_METHOD" });
return;
}
// Variables from the client side
var name = req.body.name;
var email= req.body.email;
var subject= req.body.subject;
var content = req.body.content;
// auto line break message
const message = content
.replace(/\n/g, "<br>")
.replace(/\r/g, "<br>")
.replace(/\t/g, "<br>")
.replace(/<(?!br\s*\/?)[^>]+>/g, "");
// giving the api key API
sgMail.setApiKey(process.env.KEY_SENDGRID);
// Creating message
const sendGridMail = {
to: "arotiana4612#gmail.com",
from: "kaspersky2mahanaima#gmail.com",
subject: subject,
templateId: "d-b48909edf062437e8442f861a4c8be29",
dynamic_template_data: {
name: name,
email: email,
subject: subject,
content: message,
},
};
// SENDING MESSAGE VIA SENDGRID
(async () => {
try {
await sgMail.send(sendGridMail)
.then((response) => {
console.log(response[0].statusCode)
console.log(response[0].headers)
})
.catch((error) => {
console.error(error)
})
} catch (err){
console.error(err);
res.status(500).json({
error:JSON.stringify(err),
message: "ERROR_WITH_SENDGRID",
});
}
})();
}
And this is the method from the client side that from which I get the data:
const onSubmit: SubmitHandler<Inputs> = async (formData) => {
if (!isLoading) {
setIsLoading(true);
const response = await fetch("/api/contact", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
const result = await response.json();
setIsLoading(false);
if (!response.ok) {
console.log("error sending email:",result);
} else {
console.log("ok");
}
return result;
}
};
I want to receive the mail in my inbox. Your help would be very appreciated, I'm strugling

Azure communication services

I am using azure communication services in my react app to send email.
But It is giving CORS error
import { EmailClient } from "#azure/communication-email";
function App() {
const connectionString =
"**************************************************************************************";
const client = new EmailClient(connectionString);
const sender = "1000055393#hexaware.com";
const emailContent = {
subject: "Send email quick start test- JS sample",
plainText:
"Test Email from JS Send Email Sample Application\n\n This email is part of testing of email communication service. \\n Best wishes",
html: "<html><head><title>ACS Email as a Service</title></head><body><h1>ACS Email as a Service - Html body</h1><h2>This email is part of testing of email communication service</h2></body></html>",
};
const toRecipients = {
to: [{ email: "krnsda04#gmail.com", displayName: "Karan S" }],
};
async function main() {
try {
const emailMessage = {
sender: sender,
content: emailContent,
recipients: toRecipients,
};
console.log(sender,"sender");
const sendResult = await client.send(emailMessage);
console.log(sendResult,"result");
if (sendResult && sendResult.messageId) {
// check mail status, wait for 5 seconds, check for 60 seconds.
const messageId = sendResult.messageId;
if (messageId === null) {
console.log("Message Id not found.");
return;
}
console.log("Send email success, MessageId :", messageId);
let counter = 0;
const statusInterval = setInterval(async function () {
counter++;
try {
const response = await client.getSendStatus(messageId);
if (response) {
console.log(
`Email status for {${messageId}} : [${response.status}]`
);
if (response.status.toLowerCase() !== "queued" || counter > 12) {
clearInterval(statusInterval);
}
}
return;
} catch (e) {
console.log("Error in checking send mail status: ", e);
}
}, 5000);
} else {
console.error(
"Something went wrong when trying to send this email: ",
sendResult
);
}
return;
} catch (e) {
console.log(
"################### Exception occoured while sending email #####################",
e
);
}
}
main();
return <h3>hello ${connectionString}</h3>;
}
export default App;
But when running this code, I m getting this error.
Access to XMLHttpRequest at 'https://************************/emails:send?' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
In Azure docs, they have given the code in Node.js.
Since Iam using that code in react and accessing from front end, is it showing CORS error?
How to solve this issue?
As you can see in the SDKs and REST APIs docs, ACS Email library is meant to be used in a trusted service environment. This is because there is no reasonable way to protect your connection string in the browser.
In your case, building a Node.js backend and letting your React app talk to it would be a good and preferred solution.

What does it mean if a post with status 200 is left waiting?

I am doing a POST to an enpoint to authenticate users. The endopoint is "/user/login". I make a post and receive status code 200 but the Postman, and also my client, are waiting for the RES object that does not arrive.
This is a screenshot of the API call through Postman:
This is controler in server side:
router.post(
'/user/login',
passport.authenticate('local'),
UserCtrl.getLogin,
)
getLogin = (req, res, next) => {
console.log("req: ", req.body)
console.log('logged in', req.user);
var userInfo = {
username: req.user.username
};
res.json(userInfo)
}
The console prints the lines in the controller, and the user is effectively authenticated, for example:
req: { username: 'fedex', password: 'fedex' }
logged in {
_id: new ObjectId("62a8b00f468c563699d7dfc2"),
username: 'fedex',
password: '$2a$10$cdbh0oCBNpHxxwebsvArLOAFwetVAh5LTnQwk1Lg9kjWkjAWhfxym',
__v: 0
}
probably the problem is in the invocation of the local passport strategy, but I only do the standard:
const strategy = new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, (err, user) => {
if (err) {
return done(err)
}
if (!user) {
return done(null, false, { message: 'Incorrect username' })
}
if (!user.checkPassword(password)) {
return done(null, false, { message: 'Incorrect password' })
}
return done(null, user)
})
}
)
EDITED: If I remove the middleware where the passport.authenticate('local') is invoked, and incorporate the authentication functionality directly in the controller, it works. But what is wrong with calling passport in the route?
BEFORE (does not work):
router.post(
'/user/login',
passport.authenticate('local'),
UserCtrl.getLogin
)
AFTER (adding passport authentication inside the controller, it work)
router.post(
'/user/login',
UserCtrl.getLogin
)

NodeMailer queuing outgoing email, but email never sends

I'm trying to send an email from my own domain without using an external SMTP server. I'm using NodeMailer's SMTP connection:
let options = {
secure: true,
port: consts.portOut,//465
host: consts.host, //mydomain.com
transactionLog: true,
debug: true,
requireTLS: true,
authMethod: 'PLAIN',
};
let connection = new SMTPConnection(options);
connection.connect(function() {
let auth = {
user: 'abc',
pass: 'def'
};
connection.login(auth, function(err) {
if (err) {
console.log("Authentication failed!", err);
}
console.log("Authentication to SMTP server successful.");
let envelope = {
from: 'fee#mydomain.com',
to: 'myemail#gmail.com'
};
let message = 'message hello world';
connection.send(envelope, message, function(err, info) {
if (err) {
console.log("err:::", err);
} else {
console.log('info?', info);
//connection.quit();
}
});
connection.quit();
});
});
connection.on("error", function(err) {
console.log(err);
});
My server code using NodeMailer's SMTP Server:
const options = {
secure: true,
size: 25000000, //25MB
authMethods: ['PLAIN'],
key: hskey,
cert: hscert,
ca: [hschain],
onAuth(auth, session, callback) {
if(auth.username !== 'abc' || auth.password !== 'def') {
return callback(new Error('Invalid username or password'));
}
callback(null, {user: 123}); // where 123 is the user id or similar property
},
onConnect(session, callback) {
console.log("the address is:", session.remoteAddress)
if (session.remoteAddress === consts.ip) {
return callback(); // Accept the address
} else {
return callback(new Error('Only connections from %s allowed', consts.ip));
}
},
onData(stream, session, callback) {
simpleParser(stream, (err, parsed) => {
if(err) {
console.error(err);
} else {
console.log(parsed);
}
});
stream.on('end', function () {
let err;
if(stream.sizeExceeded){
err = new Error('Message exceeds fixed maximum message size');
err.responseCode = 552;
return callback(err);
}
callback(null, 'Message queued as abcdef');
});
}
};
const emailServer = new SMTPServer(options);
emailServer.listen(consts.portOut, function () {
processSMTPConnection(consts, hskey);
});
emailServer.on("error", function (err) {
console.error("Error %s", err.message);
});
So after my client connects to my local SMTP server, the last message I get is 'Message queued as abcdef' and nothing ever sends (nothing ever arrives in my gmail inbox or any other email testing services)...
No incorrect ports are blocked, so I must be missing something(?).
Is this not how to correctly use NodeMailer?
Should I be able to send emails from my local domain using NodeMailer?
Documentation here has a note that states:
This module does not make any email deliveries by itself. smtp-server
allows you to listen on ports 25/24/465/587 etc. using SMTP or LMTP
protocol and that’s it. Your own application is responsible of
accepting and delivering the message to destination.
(emphasis mine)
Your server seems to accept the email (that's why it's showing that the message has been queued) but it doesn't delivers to destination.
To expand a little bit on how to send the message once it arrives to your SMTP server. If the TO address is local, just put the message in their mailbox. But if you want to "remail" the message, you need to contact the TO mail exchange with the message.
Something like:
const toExchange = getMX(parsed.to);
const outMessage = createMessageFromParsed(parsed);
const transporter = createTransport({
port: 25,
host: toExchange,
name: os.hostname(),
});
transporter.sendMail(outMessage);

"Webhooks failing" and "webhooks disabled" error while trying to set up facebook messenger bot

I'm trying to setup a Facebook messenger bot and keep running into the same two errors.
Webhooks failing:
Webhooks disabled:
I'm creating my chatbot with NodeJS, Express, and a server. I am running my webhook on a heroku server. I have had it verified and saved by Facebook.
After that, I ran this code:
curl -ik -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=<token>"
this replied with a success message so I started adding code to reply to the incoming messages but I can't seem to get it connected.
Here is my code:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 3000;
// body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', function (req, res) {
if (req.query['hub.verify_token'] === '<myToken>') {
res.send(req.query['hub.challenge']);
}
res.send('Error, wrong validation token');
})
app.post('/', function (req, res) {
messaging_events = req.body.entry[0].messaging;
for (i = 0; i < messaging_events.length; i++) {
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
}
res.sendStatus(200);
});
// error handler
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(400).send(err.message);
});
app.listen(port, function () {
console.log('Listening on port ' + port);
});
var token = <myToken>;
function sendTextMessage(sender, text) {
messageData = {
text:text
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
}
At this point I should be able to start a chat with my bot and have it reply with an echo but nothing is happening.
Any help is appreciated. Thanks!
You are not listening on the correct endpoint.
Your app.post('/' should be
app.post('/webhook', function(req, res) {
var messagingEvents = req.body.entry[0].messaging;
messagingEvents.forEach(function(event) {
var sender = event.sender.id;