cannot set headers after they are sent to the client Nodejs? - node.js

im trying to make a create methode to create an user with sending email after creat account ,
when i test this method
cannot set headers after they are sent to the client Nodejs
My Method:
export function registerUser(req, res, next) {
// log the request body
console.log(JSON.stringify(req.body))
const { name, email, password, phone, role, level } = req.body
userModel.create(
{
name: name,
email: email,
password: password,
createdAd: Date.now(),
phone: phone,
photo: `${req.protocol}://${req.get('host')}/images/${
req.file.filename
}`,
level: 1,
role: role,
status: 0,
},
(err, result) => {
if (err){ next(err) ;}
else {
sendMail(req, res)
res.status(201).json({
message: 'User added successfully!',
})
}
}
)
}
Email Method
export function sendMail(req, res) {
var mailOptions = {
from: 'neublua.game10#gmail.com',
to: req.body.email,
subject: 'Sending Email using Node.js',
text: 'That was easy!',
}
transporter.sendMail(mailOptions, function (error, info) {
if (error)
res.status(500).json({
message: 'Error sending email',
})
else console.log('Email sent: ' + info.response)
})
}
i put res and req to can access to the email
how can i solve it

This error shows up when you send the response two times.
What express does is that it will only send the first response back to the client, while any responses after that won't be sent. That's basically how the HTTP protocol works, you send a request, you get one response back.
1 request = 1 response
So, the problem actually comes from here
You're saying:
sendMail()
and after that you're saying:
res.status(201).json({
message: 'User added successfully!',
})
where the sendMail is actually sending a response, because an error is happening when it tries to send the email look:
the following screenshot is inside your sending email middleware:
So, you shouldn't send a response twice, either send it here, or there.
What exactly are you trying to achieve? If it's an unimportant email you're trying to send such as the "welcome" email, then keep checking for an error if emails are failing to sent but remove the response from there, the client doesn't need to know that the "welcome" email had a problem while being sent.
If this is an important email, such as an email verification email, then, remove the response sending lines from the user creation middleware, and only send the response (Success or fail) inside the email middleware.

Related

403 Forbidden in Node.js while sending email using sendgrid

I am designing a contact page in which UI is rendered using React. I have a form which is supposed to send email on submit. Here is the UI code for handling submit:
handleSubmit = (event) => {
event.preventDefault();
this.setState({
disabled: true
});
Axios.post('http://localhost:3040/api/email', this.state)
.then( res => {
if(res.data.success){
this.setState({
disabled: false,
emailSent: true
});
} else{
this.setState({
disabled: false,
emailSent: false
});
}
})
.catch(err => {
this.setState({
disabled: false,
emailSent: false
});
});
}
The api to send email is written in Node.js. Used #sendgrid//mail to trigger send. On debugging I can see that the form values are reaching the api but on send it throws 403 Forbidden error. Here is the api code:
app.post('/api/email', (req, res, next) => {
sendGrid.setApiKey('<Generated key in sendgrid>');
const msg = {
to: 'some#email.com',
from: req.body.email,
subject: 'Website Contact Page',
text: req.body.message
}
sendGrid.send(msg).then(result => {
res.status(200).json({
success: true
});
})
.catch(err => {
console.log('error: ', err);
res.status(401).json({
success: false
});
});
});
The following is the error trace I am getting in the VSCode console while debugging:
stack:"Error: Forbidden
at axios.then.catch.error (c:\react\portfolio-api\node_modules\#sendgrid\client\src\classes\client.js:105:29)
at process._tickCallback (internal/process/next_tick.js:68:7)"
proto:Error {constructor: , toString: , toJSON: }
Not sure why its giving me Forbidden error. Please let me know if I need to add more info here. Thanks in advance :)
EDIT:-
Followed the doc here at sendgrid to create an API key and used the same in sendGrid.setApiKey().
To be able to send email from sendgrid, you need to setup Single Sender Verification or Domain Verification.
Please check the docs to verify sender.
To ensure our customers maintain the best possible sender reputations
and to uphold legitimate sending behavior, we require customers to
verify their Sender Identities. A Sender Identity represents your
“From” email address—the address your recipients will see as the
sender of your emails.
You can verify one or more Sender Identities using either Domain
Authentication or Single Sender Verification.
In your api application console log, the error message must be like this:
(to see the real error message in the reactjs side, you need to use err.response.data.
The from address does not match a verified Sender Identity. Mail
cannot be sent until this error is resolved.

Trying to Send Email Using Alexa and AWS SES. Email will send however Alexa will return and Error

I am writing an Alexa Skill where one of the functions is to request to send an email to a user using AWS SES.
When the utterance is said to send the email, the email will send however Alexa will always reply 'There was a problem with the requested skill's response'.
I have tested to make sure the 'getEmail' intent itself is working and it is.
I have also tried moving the function within the intent but this has the same results.
This is the function to send the email using SES which seems to be working:
function sendEmail (event, context, callback){
var params = {
Destination: {
ToAddresses: ["xyz#gmail.com"]
},
Message: {
Body: {
Text: { Data: "Hi. Here is your email"
}
},
Subject: { Data: "Here is an email"
}
},
Source: "abc#gmail.com"
};
ses.sendEmail(params, function (err, data) {
callback(null, {err: err, data: data});
if (err) {
console.log(err);
context.fail(err);
} else {
console.log(data);
context.succeed(event);
}
});
}
Here is the intent which call the sendEmail() function.
'getEmail': function () {
sendEmail();
var bodyTemplate1 = new Alexa.templateBuilders.BodyTemplate1Builder();
var template1 = bodyTemplate1.setTitle("email").setTextContent(makeRichText("email")).setBackgroundImage(makeImage(image)).build();
this.response.speak("Your email has been sent").renderTemplate(template1).shouldEndSession(true);
this.emit(':responseReady');
},
When I run this I would like for the email to send to the the device and Alexa to just say "Your Email has been sent". At the moment it is just the email that is sending and the device saying "There was a problem with the requested skill's response"
Here is the error message from AWS Cloud
Looking at logs, your callback(null, {err: err, data: data}); is the issue here. From the code that you posted, callback doesn't exist (will be undefined). It doesn't look like you need that there so you can remove it.
AWS SDK - SES.sendEmail
The "callback" is just your function that's passed as the second argument.

nodemailer not sending and returning error

I'm trying to setup a simple contact form using nodemailer. All i'm trying to do is send an email to my email from the contact form. My email is "myemail#mac.com"
When I do my axios post I get an error in the data object saying: 550 5.7.0 From address is not one of your addresses. but yet the status:200 and statusText:"OK"
When I use the same from email as the icloud email "myemail#mac.com" then it works ? I dont see anything where it says you have to use the same from address as the service address ?
Axios post:
const request = axios.post('http://localhost:3002/send', {'name':John Doe,'email':meme#gmail.com'});
request.then((result)=>{
console.log("request = ", result);
});
Error message from console.log("request = ", result);
error:{
code:"EMESSAGE",
command:"DATA",
response:"550 5.7.0 From address is not one of your addresses.",
responseCode:550
}
nodemailer is my node.js
const transporter = nodemailer.createTransport({
service: "iCloud",
auth: {
user: "myemail#mac.com",
pass: "myemailpassword"
}
})
app.use('/send', function(req, res){
var message = {
from: req.body.email,
to: 'myemail#mac.com',
subject: 'Message From Portfolio Contact Form',
//text: 'Plaintext version of the message',
html: '<p>'+req.body.description+'</p>'
};
transporter.sendMail(message, function(error, info){
if(error){
res.json({error: error});
}else{
res.json({success: info.response});
};
});
})
You configure nodemailer transport with iCloud Service and you are trying to send a mail with a gmail adresse.
from: req.body.email, // meme#gmail.com
to: 'myemail#mac.com'
Which logically produces the error:
response:"550 5.7.0 From address is not one of your addresses."
You probably want to do the inverse.

Sending emails to a mailing list with Mailgun

I am creating a personal app for email marketing/news letter/campaign, for this am using the Mailgun API with node.js and a simple HTML form to send emails.
As of now, sending emails is working fine when I give the "to"-address directly in my front part. But when I try to send to a mailing list, I encounter some issues.
I'm trying to send emails to a list which is already created in my Mailgun account.
My below post method is to send mails.
app.post('/', function(req, res) {
var api_key = 'key-here';
var domain = 'mydomin.in';
var Mailgun = require('mailgun-js');
var mailgun = new Mailgun({ apiKey: api_key, domain: domain });
var data = {
from: req.body.myname + "<" + req.body.email + ">",
to: req.body.to,
subject: req.body.subject,
text: req.body.plaintext,
'o:tag': req.body.tag
};
console.log(req.body);
mailgun.messages().send(data, function(error, body) {
console.log(body);
var list = mailgun.lists(req.body.to);
list.members().list(function (err, members) {
// `members` is the list of members
console.log(members);
});
if (error) {
// email not sent
res.render('index', { title: 'No Email', msg: 'Error. Something went wrong.', err: true })
} else {
// Yay!! Email sent
res.render('index', { title: 'Sent Email', msg: 'Yay! Message successfully sent.', err: false })
}
});
});
In the code I mention my mailing list. What happens is when I hit send, it shows success as in the following image:
Finally, here are some logs from the mailgun dashboard
Please point out what I did wrong and share your suggestions how to send emails to the list. My approach may be totally wrong, so any guidance will be appreciated.
NOTE: from my console.it shows "thank you,the messages are in queue". but am not receiving any mails yet. Many many thanks for any help.
Official docs
https://help.mailgun.com/hc/en-us/articles/217531258:
If you're on the Free plan without credit card information present or using your sandbox domain for testing, you're restricted to sending just to Authorized Recipients.

send me email notification when user signs up for text messages via my twilio-powered application

I built a basic node.js application where users can sign-up for a weekly email.
Right now, when users sign-up on my website they get a verification email to confirm their number.
What I'd like to do now, is get the application to also send me an email that a user has signed up for the application, once they confirm their number.
Is there a simple way / tutorial on how to set this up?
Do I create a custom webhook for this? here's my .js file below:
var client = require('twilio')(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
module.exports.sendMessage = function(phone, msg, callback) {
// console.log(client)
console.log(phone);
console.log(msg);
client.sms.messages.create({
to: phone,
from: '+1XXXXXXXXXX',
body: msg
}, function(error, message) {
// The HTTP request to Twilio will run asynchronously. This callback
// function will be called when a response is received from Twilio
// The "error" variable will contain error information, if any.
// If the request was successful, this value will be "falsy"
if (!error) {
// The second argument to the callback will contain the information
// sent back by Twilio for the request. In this case, it is the
// information about the text messsage you just sent:
console.log('Success! The SID for this SMS message is:');
console.log(message.sid);
console.log('Message sent on:');
console.log(message.dateCreated);
} else {
console.log('Oops! There was an error.');
}
callback(error);
});
};
You could use Nodemailer to have it send you a notification.
https://github.com/nodemailer/nodemailer
var nodemailer = require('nodemailer');
// setup e-mail data with unicode symbols
var mailOptions = {
from: 'yourappsemail#gmail.com', // sender address
to: 'yourpersonalemail#gmail.com', // list of receivers
subject: 'Alert you have a new subscriber', // Subject line
text: phone+' - has signed up' // plaintext body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});

Resources