How to use nodemailer with claudia-api-builder - javascript

I am trying to create a simple REST API I can post an email to, to then email myself. I am using nodemailer and had set it up as an express app and it all worked fine confirming my authentication etc. is fine. I wanted to host it online so I have used claudia.js to create a lambda and API gateway setup but this seems to have broken it.
The Code
const nodemailer = require('nodemailer');
const secrets = require('./secret');
const apiBuilder = require('claudia-api-builder');
api = new apiBuilder();
module.exports = api;
var mailOptions;
var logMsg = "none";
api.post('/email', async (req, res) => {
mailOptions = {
from: secrets.email,
to: secrets.email,
subject: 'Email From: ' + req.body.senderEmail + ' | ' + req.body.subject,
text: req.body.content,
};
sendMail(mailOptions);
return logMsg;
})
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: secrets.email,
pass: secrets.pwd
}
});
function sendMail(mailOptions) {
logMsg="Starting Send Function";
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
logMsg = error;
return error;
} else {
logMsg = "Send Complete";
return true;
}
});
logMsg="Function finished";
}
When I debug via postman, by posting a raw JSON
{
"senderEmail": "test2",
"subject": "test",
"content":"test"
}
I receive "Function Finished" Which I dont really see how it is possible as surely the if or else should've fired under transporter.sendMail(..., returning from the function. I also don't receive an email which is my end goal

I had the same problem until I started returning the transporter
return transporter.sendMail(mailOptions)
.then(info => {
console.log('email sent: ', info)
return {'status': 'OK'}
})
.catch(err => {
console.log('email error: ', err)
return {'status': 'ERROR'}
})

Related

Send email using Cloud Functions and Nodemailer

How can I send an email to a person using Cloud Functions and Nodemailer?
On my app there's a contact screen where users can ask questions and send feedback to the app, and when the user presses a button, the Cloud Function gets triggered. However, I don't seem to recieve any emails whatsoever, I even checked the "Spam" folder.
What am I doing wrong?
My code for the Cloud Function looks like this:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
admin.initializeApp(functions.config().firebase);
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'exampleemail#gmail.com',
pass: 'exampleemailpassword'
}
});
exports.sendEmail = functions.https.onRequest((request, response) => {
const { sender, phone, message } = request.query;
const mailOptions = {
from: sender.toLowerCase(),
to: 'exampleemail#gmail.com',
subject: 'New feedback email',
text: `${message} Phone: ${phone}`
};
// eslint-disable-next-line consistent-return
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
response.send(err.toString());
}
response.send('Email sent');
});
});
I see what you are doing wrong, you can't use gmail's SMTP transport service in server environments other than your own computer
Gmail has a limit of 500 recipients a day (a message with one To and
one Cc address counts as two messages since it has two recipients) for
#gmail.com addresses and 2000 for Google Apps customers, larger SMTP
providers usually offer about 200-300 recipients a day for free.
So I would recommend you to use a service like EmailJS to send emails
I was doing it wrong, I had to return a code to the HttpRequest in order to run the function property. Then, it works
exports.sendEmail = functions.https.onRequest((request, response) => {
cors(request, response, () => {
const { sender, phone, message } = request.query;
const mailOptions = {
from: sender.toLowerCase(),
to: 'exampleemail#gmail.com',
subject: 'New feedback email',
text: `${message} \nEmail: ${sender.toLowerCase()}\nPhone: ${phone}`
};
return transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return response.status(500).send({
data: {
status: 500,
message: error.toString()
}
});
}
return response.status(200).send({
data: {
status: 200,
message: 'sent'
}
});
});
});
});

react add data from MongoDB to email

pretty new to react only been doing it for a couple of weeks and I'm working on a project for personal use to send an email to my email using nodemailer which I have managed to do. the next part I want to do is add data to the email that will come from my MongoDB database like the order number, customer name and status of the job I've searched high and low on youtube and google and not really finding anything on the issue
also, it only runs when I type node server.js and then it automatically sends the email which I don't want I want it to run when submit is clicked when a status is updated in the database.
Here is the code for what I have on server.js
require('dotenv').config();
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
});
let mailOptions = {
from: 'group2021#gmail.com',
to: 'edge#gmail.com',
subject: 'Project Update',
text: 'Hello {{name}} please find this email as an update to you project.'
};
transporter.sendMail(mailOptions, function(err, data) {
if(err) {
console.log('Error Occured!', err);
} else {
console.log('Email Sent!')
}
});
I'm not sure how your application looks like, I assume it's SPA react application.
I suggest you to create simple http server using Expressjs and creating endpoint which you will call from the client (react app) e.g. (the code is not tested is just an example)
const express = require('express');
const app = express();
const port = 3000;
const nodemailer = require('nodemailer');
app.get('/mail/:someID', async (req, res) => {
// someID is identifier to find data in db
// it will come from localhost:PORT/mail/>>someID<<
const { someID } = req.params;
let data;
try {
data = await mongoCol.FindOne({
/* query */
}); // reads data from mongo
} catch (err) {
return res.status(500).json(err);
}
// prepare content
var text =
'Hello {{name}} please find this email as an update to you project.\n' + data;
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
});
let mailOptions = {
from: 'group2021#gmail.com',
to: 'edge#gmail.com',
subject: 'Project Update',
text: text
};
transporter.sendMail(mailOptions, function (err, data) {
if (err) {
console.log('Error Occured!', err);
return res.status(500).json(err);
} else {
console.log('Email Sent!');
return res.sendStatus(200);
}
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
You should add some kind of authorization to not allow other people to send email by your server.
also, it only runs when I type node server.js and then it automatically sends the email which I don't want
This happens because your code is not in function and any time you import or start file (module) it will execute.

Nodemailer transporter seems to break when used a script function

i came here with a nodemailer situation, i'm building a contact form and to avoid php i was trying to use nodemailer on js however i found a problem.
When i use nodemailer on a simples mailer.js and use "node mailer.js" it works:
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'email',
pass: 'password'
}
});
var mailOptions = {
from: 'person',
to: 'email',
subject: 'Teste nodemailer',
text: `Teste`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
but when i try to insert it on the script that validades the form:
async function sendIT(){
var email = document.getElementById('email').value;
var name = document.getElementById('name').value;
var msg= document.getElementById('msg').value;
var error = false;
if(name == ""){
document.getElementById('nameError').classList.add('error');
error = true;
}else{
document.getElementById('nameError').classList.remove('error');
}
if(msg == ""){
document.getElementById('msgError').classList.add('error');
error = true;
}else{
document.getElementById('msgError').classList.remove('error');
}
if (!(/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(email))){
document.getElementById('emailError').classList.add('error');
error = true;
}else{
document.getElementById('emailError').classList.remove('error');
}
if(!error){
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'email',
pass: 'passwor'
}
});
var mailOptions = {
from: 'person',
to: email,
subject: 'Test nodemailer',
text: 'The ' +name+ ' sent the following message:\n\n\n' + msg
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
alert('e-mail failed')
console.log(error);
} else {
alert('E-mail sent');
console.log('Email sent: ' + info.response);
}
});
}
}
And the error seems to be on the 'transporter' because it is when i create the transporter or when i try to use it to send an e-mail that the scripts breaks.
Does anyone know why this happens? Thank you for the time spent reading and responding to this question
Edit.:
The line
var nodemailer = require('nodemailer');
at the top of the script file gives an error on the browser Uncaught ReferenceError: require is not defined, an error that it should not happen since i'm using nodejs.

nodemailer email not sent and no errors logged

I'm trying to use nodemailer to send email but it's not sending any email and the strange thing is that it's also not logging any error.
Here's the code of my route:
router.post("/form", async (req, res) => {
try {
let { name, email, password } = req.body;
let user = await User.create({
name,
email,
password,
});
if (!user) return res.status(501).send("Something went wrong");
let token = await user.getSignedToken();
try {
user.emailToken = await user.verifyEmail();
} catch (ex) {
console.log(ex);
}
try {
await user.save({ validateBeforeSave: false });
} catch (ex) {
console.log(ex);
}
const options = {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRE * 24 * 60 * 60 * 1000
),
};
var smtpTransport = nodemailer.createTransport({
service: "Gmail",
auth: {
user: "myEmail",
pass: "myPass",
},
});
var mailOptions = {
from: "myEmail",
to: req.body.email,
subject: "Verify Email Token",
text: `go to the below link\nhttp://localhost:3000/verifyEmail/${emailToken}`,
};
smtpTransport.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
} else {
console.log("Email sent: " + info.response);
}
});
res.cookie("token", token, options);
res.send("Check email for activation");
} catch (ex) {
res.send(ex);
}
});
So, it's not sending any email and after it, the res.cookie and the res.send line is also not working. But, the server is not logging any error/exceptions. So, what could be the issue? I used nodemailer in another route (with the same gmail account as this one) and it was working. So, what could be the problem that the code here isn't working?
In the mailoptions object, you are using emailToken and that variable is never defined. Instead, you might wanna use user.emailToken

How to add an event listener to trigger a server side email function?

So, I have an express application serving a static index.html page, and a function in my app.js file that sends an email when the server starts up.
What I'd like to do is send the email only when a user hits a 'submit' button on a form (and the form is successfully sent, so on success-confirmation, preferably).
How do I get my program to "listen" for an onClick / form-successfully-sent event and then run the server side code I have that sends an email?
const http = require('http');
const nodemailer = require('nodemailer');
const express = require('express');
const app = express();
const port = 8080;
app.listen(port, () => console.log(`App listening on port ${port}!`));
app.use(express.static('public'));
app.get('/', (req, res) => res.send('index.html'))
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'USERNAME#GMAIL.COM',
pass: 'PASSWORD'
}
});
const mailOptions = {
from: 'USERNAME#GMAIL.COM',
to: 'USERNAME2#GMAIL.COM',
subject: 'Sending Email using Node.js',
text: 'That was easy!'
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
})
I would like to trigger the transporter.sendMail method/function when a user successfully submits a form.
Thanks!
Add a route on your server that will handle form submissions. There are multiple ways to do this, however, as a simple example, look at the code below:
app.post("/send", function(req, res, next) {
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "test-email#gmail.com",
pass: "test123"
}
});
const mailOptions = {
from: `${req.body.email}`,
to: "test-email#gmail.com",
subject: `${req.body.name}`,
text: `${req.body.message}`,
replyTo: `${req.body.email}`
};
transporter.sendMail(mailOptions, function(err, res) {
if (err) {
console.error("there was an error: ", err);
} else {
console.log("here is the res: ", res);
}
});
});
Then, in your client application, call the function below (or something similar) to send the client-side data to the newly-created endpoint:
function sendEmail(name, email, message) {
const options = {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
name: name,
email: email,
message: message
})
};
return fetch("/send", options)
.then(res => res.json())
.then(res => {
console.log("here is the response: ", res);
})
.catch(err => {
console.error("here is the error: ", err);
});
}
You'll have to set up an API endpoint
app.post('/send-mail', function (req, res) {
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
})
})
And then call that from your form code.
onSubmit() {
fetch('/send-mail', {
method: 'POST'
})
}
Edit: typo.
Put this part inside a function and call it when you handle your form request, create parameters in function as needed for f.ex. mailOptions information
function sendEmail(){
const mailOptions = {
from: 'USERNAME#GMAIL.COM',
to: 'USERNAME2#GMAIL.COM',
subject: 'Sending Email using Node.js',
text: 'That was easy!'
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
})
}
const bodyparser = require("body-parser");
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: `${req.body.username}`,
pass: `${req.body.password}`
}
});
const mailOptions = {
from: `${req.body.email}`,
to: 'USERNAME2#GMAIL.COM',
subject: ``${req.body.subject},
text: `${req.body.message}`
};
app.post("/login", (req, res)=>{
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
})
})
remember to do npm install --save body-parser and also app.use(bodyparser.json())

Categories

Resources