sending an email with sendgrid and nodeJS - node.js

I would like to send an email to myself(outlook adress) using sendgrid.
I have added a sender authentification for my email adress ( the same i use in send grid message: to and from parameters)
Inside an express node server, i process the mail transport. see the code below.
app.post('/api/email', (req, res, next) => {
console.log(req.body);
sendGrid.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: 'The email i have register as sender authentification',
from: 'The email i have register as sender authentification',
subject: 'information request with same from and to',
text: 'Hello i am ' + req.body.name + req.body.informationDetails
};
sendGrid.send(msg)
.then(result => {
res.status(200)
res.json({
success: true
});
})
.catch(err => {
console.log('error: ', err);
res.status(401).json({
success: false
});
})
});
The sendgrid activity page shows me that the mails have been delivered to the adress i have register but i am unable to receive the email inside my mailbox.
i am little lost on how to solve that
Moreover, in the frontend, i am using axios to connect the backend to send the request parameters, but the res value cant be displayed.
Axios.post('/api/email', this.state)
.then(res => {
console.log("check before if success");
console.log(res);
if(res.data.success) {
this.setState({
name: "",
phoneNumber: "",
informationDetails: "",
disabled: false
});
} else {
console.log("no success");
console.log(res);
this.setState({
disabled: false
});
}
})
.catch(err => {
this.setState({
disabled: false
});
})
Does someone have an idea?

i don't know whether you have solved it or not. but i have a working example following your problem. i won't be explaining it to you because of not being sure of executing it futher.
nodejs:
app.post("/contact", (req,res,next) => {
const name = req.body.name;
const email = req.body.email;
const subject=req.body.subject;
const message = req.body.message;
const msg = {
to: "it's ur desired email", //receiver's email
from: email, // Change to your verified sender
subject: subject,
text: "testing from local",
html: `<p>Name: ${name}</p> sends a message from <p>Email: ${email}</p>: <br/><p>Message: ${message}</p>`,
};
sgMail
.send(msg)
.then((result) => {
res.json({success: true});
})
.catch((error) => {
console.error(error);
res.status(500).json("Error")
});
App.js from frontend:
axios.post('http://localhost:5000/contact', this.state)
.then(res => {
if(res.data.success) {
this.setState({
disabled: false,
emailSent: true
});
} else {
this.setState({
disabled: false,
emailSent: false
});
}
})
.catch(err => {
console.log(err);
this.setState({
disabled: false,
emailSent: false
});
})
}
i have added the subject area because i needed it for my project and it looks cool for me.
let me know if it works

Related

Reactjs: post data to localhost always pending

I am working on ReactJs and NodeJS and I am creating a signup page. I post data to server but it is always pending.
Which part did I do wrong? It would be nice if someone can help.
Front end:
const handleSubmit = (event) => {
// prevent page refresh
event.preventDefault();
const newUserData = {
name: name,
email: email,
password: password,
};
axios
.post("/signup", newUserData)
.then((res) => {
console.log(res.data);
})
.catch((error) => {
console.log(error);
});
setEmail("");
setName("");
setPassword("")
console.log("form submitted ✅");
};
Backend:
router.post("/signup", (req, res) => {
const { name, email, password } = req.body;
if (!email || !password || !name) {
res.status(422).send({ error: "Please add all the fields" });
}
console.log(req.body);
User.findOne({ email: email })
.then((savedUser) => {
if (savedUser) {
res.status(422).send({ error: "Email already been used" });
}
bcrypt.hash(password, 12).then((hashedpassword) => {
const user = new User({
name,
email,
password: hashedpassword,
});
user
.save()
.then((user) => {
res.json({ message: "Sign Up Successfully" });
})
.catch((err) => {
console.log(err);
});
});
})
.catch((err) => {
console.log(err);
});
});
in package.json i set proxy as
"proxy": "http://localhost:5000",
I guess you are using MongoDB as well, in that case keep in your mind that the findOne is async, so you need to use await before. And for to save data you need to use the .create() method from MongoDB, e.g.
router.post("/signup", async (req, res) => {
const { name, email, password } = req.body;
if (!email || !password || !name) {
res.status(422).send({ error: "Please add all the fields" });
}
console.log(req.body);
await User.findOne({ email: email })
.then((savedUser) => {
if (savedUser) {
// you need to add return to stop the code
return res.status(422).send({ error: "Email already been used" });
}
// or you can add else because the code keep running
bcrypt.hash(password, 12).then((hashedpassword) => {
const user = await User.create({
name,
email,
password: hashedpassword,
});
user
.save()
.then((user) => {
res.json({ message: "Sign Up Successfully" });
})
.catch((err) => {
console.log(err);
});
});
})
.catch((err) => {
console.log(err);
});
});
I think it is better to use something like throw new Error('Email already been used') instead of return for your res.status(422).send({ error: "Email already been used" }); because if you have return the server doesn't give back an error, but a normal answer, but of course it is ok if you want that.
I want you to be sure that before you submit, the values name, email, password, are updated. Please try:
const handleSubmit = async (event) => {
// prevent page refresh
event.preventDefault();
console.log(`The value for the name: ${name}`);
console.log(`The value for the email: ${email}`);
console.log(`The value for the password: ${password}`);
try {
const response = await axios.post("http://localhost:5000/signup", {
name,
email,
password,
});
console.log(response.data);
setEmail("");
setName("");
setPassword("");
console.log("form submitted ✅");
} catch (error) {
console.log(error);
}
};

mailgun.messages is not a function

I am trying to get my e-commerce web app to send emails on purchasing but when I try to pay for things I get the mailgun.messages is not a function I've reverted changes and re coded it twice but this is a different error I'm not sure how to resolve this. Is there another way to use mailgun's api? Here is the code below:
orderRoutes.js:
orderRouter.put(
"/:id/pay",
isAuth,
expressAsyncHandler(async (req, res) => {
const order = await Order.findById(req.params.id).populate(
"user",
"email firstName"
);
if (order) {
order.isPaid = true;
order.paidAt = Date.now();
order.paymentResult = {
id: req.body.id,
status: req.body.status,
update_time: req.body.update_time,
email_address: req.body.email_address,
};
const updateOrder = await order.save();
mailgun.messages().send(
{
from: "Sales <sales#cocoTiCosmetics.com>",
to: `${order.user.firstName} <${order.user.email}>`,
subject: `New Order ${order._id}`,
html: payOrderEmailTemplate(order),
},
(error, body) => {
if (error) {
console.log(error);
} else {
console.log(body);
}
}
);
res.send({ message: "Order Paid", order: updateOrder });
} else {
res.status(404).send({ message: "Order Not Found" });
}
})
);
utils.js
export const mailgun = () =>
mg({
apiKey: process.env.MAILGUN_API_KEY,
domain: process.env.MAILGUN_DOMAIN,
});

How to send authentication email with sendgrid

I have these lines of code, but having difficulty sending mail using SendGrid. I need a working guide to what can be done.
const sgMail = require('#sendgrid/mail')
sgMail.setApiKey(process.env.MAIL_KEY)
const { name, email, password } = req.body;
console.log(name, email, password)
const errors = validationResult(req);
if (!errors.isEmpty()) {
const firstError = errors.array().map(error => error.msg)[0];
return res.status(422).json({
errors: firstError
});
} else {
User.findOne({
email
}).exec((err, user) => {
if (user) {
return res.status(400).json({
errors: 'Email is taken'
});
}
});
const token = jwt.sign(
{
name,
email,
password
},
process.env.JWT_ACCOUNT_ACTIVATION,
{
expiresIn: '5m'
}
);
const emailData = {
from: process.env.EMAIL_FROM,
to: email,
subject: 'Account activation link',
html: `
<h1>Please use the following to activate your account</h1>
<p>${process.env.CLIENT_URL}/users/activate/${token}</p>
<hr />
<p>This email may containe sensetive information</p>
<p>${process.env.CLIENT_URL}</p>
`
};
sgMail.send(emailData)
.then(sent => {
return res.json({
message: `Email has been sent to ${email}`
});
})
.catch(err => {
console.log(err)
return res.status(400).json({
success: false,
errors: errorHandler(err)
});
});
The above code is the code I have, but I get the error described in the image which is the catch to the .then of the sgMail.send. I get a forbidden error in the console. I don't know where that is really coming from

how to send email confirmation in nodejs and SendGrid?

I have a NodeJs and ReactJs project, where a user can register and after the user is registered they will get an email to confirm their account.
so now when I register the email is working well. but it works with an email that I set in like this.
function sendMail() {
const msg = {
to: "someoneemail#gmail.com",
from: "myemail#gmail.com",
subject: "a subject",
text: "some text herer",
html: "<strong>and easy to do anywhere, even with Node.js</strong>",
};
sgMail
.send(msg)
.then(() => {
console.log("Email sent");
})
.catch((error) => {
console.error(error);
});
}
module.exports = { sendMail };
I need to remove this to: "someoneemail#gmail.com" a*
nd instead set the user email, the user who to register on this
system
and instead of text: i have to send the token.
so here is the registration part:
router.post("/register", async (req, res) => {
const { fullName, emailAddress, password } = req.body;
const user = await Users.findOne({
where: {
[Op.and]: [{ fullName: fullName }, { emailAddress: emailAddress }],
},
});
if (user) {
res.status(400).send({
error: `some message.`,
});
} else {
bcrypt
.hash(password, 10)
.then((hash) => {
return {
fullName: fullName,
emailAddress: emailAddress,
password: hash,
isVerified: false,
};
})
.then((user) => {
const token = TokenGenerator.generate();
const creator = Verifications.belongsTo(Users, { as: "user" });
return Verifications.create(
{
token,
user: user,
},
{
include: [creator],
}
);
})
.then((verification) => {
console.log("verification", verification);
sendMail();
})
.then(() => res.json("User, Successmessage "));
}
});
but the codes are not in the same file.
Just add the parameters you need to the sendMail function:
function sendMail(user, token) {
const msg = {
to: user.emailAddress,
from: "myemail#gmail.com",
subject: "Sending with SendGrid is Fun",
text: token,
html: `<strong>${token}</strong>`,
};
sgMail
.send(msg)
.then(() => {
console.log("Email sent");
})
.catch((error) => {
console.error(error);
});
}
Also inject the needed parameters in the promises:
.then(async (user) => {
const token = TokenGenerator.generate();
const creator = Verifications.belongsTo(Users, { as: "user" });
await Verifications.create(
{
token,
user: user,
},
{
include: [creator],
}
);
return {user, token};
})
.then(({user, token}) => {
sendMail(user, token);
})
.then(() => res.json("User, Successmessage "));

React JS: Rendering Blank page instead of rendering the component in route

In React JS App there is forgot password functionality, on entering email end users get password reset link if the user's email exists in DB. When user clicks the link inside email it gets redirect and load blank screen. I can't figure out the problem, I had checked all routes and looks like perfect.
This is ResetPassword Component where user can enter set his new password.
const ResetPassword = (props) => {
const userId = props.match.params.id
const [password,setPassword] = useState({
password: '', confirmPassword: ''
})
const baseUrl = process.env.REACT_APP_baseUrl
const changePassUrl = `${baseUrl}/user/reset/${userId}`
const history = useHistory()
const resetPassword = async e => {
e.preventDefault()
const options = {
method: 'PATCH',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(password)
}
await fetch(changePassUrl, options)
.then(response => response.json())
.then(user => {
console.log('Success:', user);
if(user.status===true){
toast.success('Password changed Successfully. Login with New Password',{position: 'top-center', autoClose: 8000})
history.push('/login')
}
else if(user.status === false){
toast.error('Please try again!',{position: 'top-center', autoClose: 8000})
}
})
.catch((error) => {
console.error('Error:', error);
});
}
App.js route of above component.
<Route exact path='/reset/:id' component={ResetPassword}/>
Node API that sends the reset link via NodeMailer.
module.exports.resetUserPassword = (req, res) => {
User.findOne({email: req.body.email},
(err, users) => {
if (err) {
res.status(500).json({
status: false,
message: 'some error occured in Finding User.',
error: err,
});
}
if (users) {
const url = process.env.Url
var transporter = nodemailer.createTransport({
host: process.env.mailHost,
port: 587,
auth: {
user: process.env.mailUser,
pass: process.env.mailPass
}
});
var mailOptions = {
from: process.env.mailUser,
to: users.email,
subject: 'Password Reset Link',
html: `
<div style='color: #000'>
<h2>Hello ${users.fullName},</h2>
<h3>A request has been received to change the password for your Jobs#MyCityMyStore Account.</h3>
<h3>Click here to reset your password</h3>
<p>If you did not initiate this request, Please contact us immediately at </p><a href='#'>support#support.com</a><br/>
<p>Thank you.</p>
<p>support#support Team</p>
</div>`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
res.status(200).json({ status: true, email: users.email });
}else{
res.status(200).json({status: false, data: 'User not found '+users})
}
}
);
};

Resources