How to fix nodemailer "object object" error in node.js website? - javascript

I am creating a node.js website for a business and would like to be able to notify through email, everytime someone applies. I am using nodemailer and mailgun to send an email every time the job application form is submitted. The emails are being sent, however, it does not contain the key value pairs of the applicant object I've created. Any help would be greatly appreciated!
Here is an image of the email I receive when submitting and application
Here is the nodemailer code I'm running
const nodemailer = require('nodemailer');
const mailgun = require('nodemailer-mailgun-transport');
const debug = require('debug')('app:mail');
const auth = {
auth: {
api_key: '**************',
domain: '***************'
}
};
const transporter = nodemailer.createTransport(mailgun(auth));
function sendOrderEmail(applicant) {
let html = '<ul>';
Object.entries(applicant).forEach(([key, value]) => {
html += `<li>${key}: ${value}</li>`;
});
html += '</ul>';
const mailOptions = {
from: '*************',
to: '*********, *************',
subject: '*****************',
html
};
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
debug(`Error: ${err}`);
} else {
debug(`Info: ${info}`);
}
});
}
module.exports = sendOrderEmail;
Here is my post route where I create the applicant object
app.post('/employment', function(req, res){
var firstName = req.body.firstName;
var middleInitial = req.body.middleInitial;
var lastName = req.body.lastName;
var address = req.body.address;
var city = req.body.city;
var state = req.body.state;
var zipCode = req.body.zipCode;
var phoneNumber = req.body.phoneNumber;
var doYouRecieveText = req.body.doYouRecieveText;
var newApplicant = {
firstName: firstName,
middleInitial: middleInitial,
lastName: lastName,
address: address,
city: city,
state: state,
zipCode: zipCode,
phoneNumber: phoneNumber,
doYouRecieveText: doYouRecieveText
};
Applicant.create(newApplicant, function(err, newlyCreated){
if(err) {
console.log(err);
} else {
console.log(newlyCreated);
sendOrderEmail(newlyCreated);
res.redirect('/');
}
});
});

It looks like the value you are attempting to insert in your html is an Object but the html is expecting a value of type String.
Try stringifying your value before inserting it in your html.
html += `<li>${key}: ${ typeof value === 'string' ? value : JSON.stringify(value)}</li>`;

I was passing through the newlyCreated parameter to the sendOrderEmail function when I should have been passing through the newApplicant variable
Applicant.create(newApplicant, function(err, newlyCreated){
if(err) {
console.log(err);
} else {
console.log(newlyCreated);
sendOrderEmail(newApplicant);
res.redirect('/');
}
});

Related

accessing the same instance of an eventEmitter across files (node.js / express / event listeners / pub-sub architecture)

I'm creating a user via the following post route
.post(async (request, response) => {
const { email, password, firstName, lastName, phoneNumber } = request.body;
console.log(String(email));
console.log(String(password));
const emailError = validateEmail(String(email));
const phoneError = validatePhoneNumber(String(phoneNumber));
if (emailError) {
return response.status(400).send(emailError);
}
if (phoneError) {
return response.status(400).send(phoneError);
}
try {
const result = await createUser(email, password, firstName, lastName, phoneNumber);
console.log("User created!");
response.send(`${firstName} ${lastName} has been added to the database! A confirmation email has been sent to ${email}`);
} catch (error) {
console.log(error);
return response.status(500).send('An error occurred while adding the user to the database');
}
})
the createUser function is in this userService.js publisher
const EventEmitter = require('events');
const userEmitter = new EventEmitter();
const createUser = async (email, password, firstName, lastName, phoneNumber) => {
userEmitter.emit('userCreated', { email, password, firstName, lastName, phoneNumber });
console.log("Emitting userCreated event...");
emmiterCheck();
};
function emmiterCheck() {
if (userEmitter.listenerCount('userCreated') > 0) {
console.log("User creation event emitting!");
} else {
console.log("User creation event not fired");
}
};
module.exports = {
createUser,
userEmitter,
};
the subscriber/listener is here in userDBService.js
const connection = require('../database/connection');
const {createUser} = require('../publishers/userService');
const uuid = require('uuid');
const User = require('../models/User');
createUser.userEmitter.on('userCreated', async (user) => {
console.log("User creation event fired!");
try {
const newUser = await User.create({
id: uuid.v4(),
email: user.email,
password: user.password,
firstName: user.firstName,
lastName: user.lastName,
phoneNumber: user.phoneNumber
});
console.log(`User with ID ${newUser.id} created`);
} catch (err) {
console.log(err);
}
});
when I hit the post route, its saying "Emitting userCreated event...
User creation event not fired
User created!" but it seems like the publisher-subscriber are not on the same instance? I'm not sure if this is the problem, but please advise. Thank you!
I wrote that emmiterCheck function to see if the listeners we're linked, and they're not. I tried creating a specific createUserEmmiter but that still didn't work.

NEXT JS req.body undefined

not sure what I'm doing wrong?
I'm getting undefined when trying to upload my form data to my supabase the data is coming to the API undefined but when I pass it to the function it prints what I want to send to the API in my submit handler.
export const Quote = () => {
const [formIsValid, setFormIsValid] = useState(false);
//----------------------------_FORM VALIDATION------------------------------------
const {
value: firstName,
inputBlurChangeHandler: firstNameBlur,
isValid: firstNameValid,
hasError: firstNameInputHasError,
valueChangeHandler: firstNameChangeHandler,
reset: resetFirstName,
} = useInput((value) => value.trim() !== "");
**hooks & useEffect removed to shorten question they are same as above but different names**
console.log(formIsValid, "FORM IS VALID");
const formSubmitHandler = async (event) => {
event.preventDefault();
//UNDEFINEDS
await fetch("api/dbhandler", {
method: "POST",
body: {
firstname: firstName,
secondname: secondName,
street: streetAddress,
phone: phoneNumber,
email: emailAddress,
postal: postalCode,
about: quoteDescription,
},
headers: {
"Content-Type": `text/plain`,
},
});
};
API is coming as undefined in req. body but if I console log in the submit handler values are being passed to the function not sure what I am doing wrong
import { supabase } from "../../utils/supabaseClient";
const supabaseApiHandler = async (req, res) => {
console.log(req.body.firstname);
if (req.method === "POST") {
const firstname = req.body.firstname;
const secondname = req.body.secondname;
const email = req.body.email;
const street = req.body.street;
const postal = req.body.postal;
const phone = req.body.phone;
const about = req.body.about;
const { data, error } = await supabase.from("quotes").insert([
{
firstname,
secondname,
email,
street,
postal,
phone,
about,
},
]);
}
res.status(200).json({ name: "test" });
};
export default supabaseApiHandler;
If you have the body parser disabled in the API route, req.body will be empty.
I accidentally left this code in without using another body parser.
export const config = {
api: {
bodyParser: false,
},
};

Getting single message from Graph

I'm trying to get a single email from an Office 365 Mailbox.
I'm sending the email id to my app via a POST (req.body.id) and then calling this code in order to get some email properties:
router.post('/id', async function(req, res, next) {
console.log("email with ID -> ", req.body.id)
let parms = { title: 'Inbox', active: { inbox: true } };
const accessToken = await authHelper.getAccessToken(req.cookies, res);
const userName = req.cookies.graph_user_name;
if (accessToken && userName) {
parms.user = userName;
// Initialize Graph client
const client = graph.Client.init({
authProvider: (done) => {
done(null, accessToken);
}
});
try {
const result = await client
.api('/me/messages/', req.body.id)
.select('id,subject,from,toRecipients,ccRecipients,body,sentDateTime,receivedDateTime')
.get();
parms.messages = result.value;
console.log("email -> ", result.value);
res.render('message', parms);
} catch (err) {
parms.message = 'Error retrieving messages';
parms.error = { status: `${err.code}: ${err.message}` };
parms.debug = JSON.stringify(err.body, null, 2);
res.render('error', parms);
}
} else {
// Redirect to home
res.redirect('/');
}
});
At the moment, result.value contains all of the messages in the mailbox instead of just the message with provided id.
Could someone tell me where my error is, please?
The api method has a single path parameter. Calling it like .api('/me/messages/', req.body.id) is effectivly sending it a path ("/me/messages/") along with an additional parameter it ignores.
You need to send it a single string so you'll need to append the req.body.id to the path ({path} + {id}):
const result = await client
.api('/me/messages/' + req.body.id)
.select('id,subject,from,toRecipients,ccRecipients,body,sentDateTime,receivedDateTime')
.get();

ReactNative and firebase, Real time database when signUp

I build a react native signUp form with this fields (email, password, name, and phone) and I need to add it to the firebase database when user create his account.
I create the signUp function like this:
onSignUpPress() {
const navigation = this.props.navigation;
this.setState({ error: '', loading: true });
const { email, password } = this.state;
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(() => {
this.setState({ error: '', loading: false });
navigation.navigate("Profile");
})
.catch(() => {
this.setState({ error: 'Authentication failed.', loading: false });
console.log("Error creating user:");
});
}
and it's work
I need to know how can I add the field to a database
I try this :
writeUserData(uid, name, email, phone) {
let userId = firebaseApp.auth().currentUser.uid;
var newUser = {
name: name,
email: email,
phone: phone
}
var newUserKey = firebase.database().ref().child('users').push().key;
var updates = {};
updates['/users/' + newUserKey] = newUser;
updates['/user-users/' + uid + '/' + newPostKey] = postData;
return firebase.database().ref().update(updates);
}
onSignUpPress() {
....
....
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(() => {
....
this.writeUserData(uid, name, email, phone);
navigation.navigate("Profile");
})
....
.....
}
but it's not working correctly any help, please?
Firebase has many functionalities. Out of them two are authentication and real time database.
When you call createUserWithEmailPassword successfully, it automatically creates a UID of the user and stores the meta in Firebase Authentication.
You can now at point of time get this UID of this user when he is authenticated using firebase.auth(). currentUser.uid and then create a firebase reference where you want to save data database.ref().child(path)
Use the .set(object) or .push(object) to save data.
Tip : Create your database architecture properly (see documentation) to be able to fetch the saved data properly.
try this,
writeUserData(uid, name, email, phone) {
const userId = firebase.auth().currentUser.uid;
//You don't have to create key because userId is uniq value.
return firebase.database().ref(`users/${userId}`).update({name, email, phone});
}
onSignUpPress() {
....
....
// createUserWithEmailAndPassword promise resolve return userData!
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(userData => {
....
this.writeUserData(userData.uid, name, email, phone);
navigation.navigate("Profile");
})
....
.....
}
and I don't get it why you try to update,
updates['/user-users/' + uid + '/' + newPostKey] = postData;
even if you don't have postData at this moment!
You just set when user create post data like this
writePostData(uid, postData) {
const postRef = firebase.database().ref(`user-users/${uid}`);
//this way is useful when key handling before push
var push = postRef.push();
var key = push.key;
return postRef.child(key).set(postData);
//or just push
return postRef.push(postData);
}

how to access variables inside app.get

How can I access a variable or set of variables inside app.get and make it accessible to the whole project? I am trying to capture the information sent from the SMS text, organized into the "messageData" variable, then sent to the "MessageSchema," where it is then sent and stored in the Mongo Database. My issue is that I believe none of the variables(message, number, answer) are truly being found. How can I fix that?
app.js
app.get('/smssent', function(req, res, callback) {
var message = req.query.Body;
var number = req.query.From;
var twilioNumber = req.query.To;
var context = null;
var index = 0;
var contextIndex = 0;
contexts.forEach(function(value)
{
console.log(value.from);
if (value.from == number)
{
context = value.context;
contextIndex = index;
}
index = index + 1;
});
console.log('Recieved message from ' + number + ' saying \'' + message + '\'');
var conversation = new ConversationV1({
username: '',
password: '',
version_date: ConversationV1.VERSION_DATE_2016_09_20
});
//console.log(JSON.stringify(context));
//console.log(contexts.length);
conversation.message({
input: { text: message },
workspace_id: '',
context: context
}, function(err, response) {
if (err) {
console.error(err);
} else {
var answer = response.output.text[0];
if (context == null) {
contexts.push({'from': number, 'context': response.context});
} else {
contexts[contextIndex].context = response.context;
}
var intent = response.intents[0].intent;
console.log(intent);
if (intent == "done") {
//contexts.splice(contexts.indexOf({'from': number, 'context': response.context}),1);
contexts.splice(contextIndex,1);
// Call REST API here (order pizza, etc.)
}
var client = require('twilio')(
'',
''
);
client.messages.create({
from: twilioNumber,
to: number,
body: response.output.text[0]
}, function(err, message) {
if(err) {
console.error(err.message);
}
});
}
});
res.send('');
});
(ABOVE)This is what retrieves the SMS text, and conducts Twilio, Node, and IBM Bluemix.
index.js
router.post('/app', function(req, res, next) {
if (req.body.number &&
req.body.message &&
req.body.answer
) {
// create object with form input
var messageData = {
number: req.body.number,
message: req.body.message,
answer: req.body.answer
};
// use schema's `create` method to insert document into Mongo
Message.create(messageData, function (error, message) {
if (error) {
return next(error);
} else {
return res.redirect('/');
}
});
} else {
var err = new Error('All fields required.');
err.status = 400;
return next(err);
}
});
(ABOVE)This is the code to organize and prepare everything for the "MessageSchema."
message.js
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var MessageSchema = new mongoose.Schema({
number: {
type: String,
required: true,
trim: true
},
message: {
type: String,
required: true,
trim: true
},
answer: {
type: String,
required: true,
trim: true
}
});
var Message = mongoose.model('Message', MessageSchema);
module.exports = Message;
Finally, this is what sends all the info to the DB.
If anyone finds anything or has any tips to improve this code, please let me know, I am open for all the input you can give me!
THANKS!
var messageData = {
number: req.body.number,
message: req.body.message,
answer: req.body.answer
};
This is OK. However, keep in mind that these variables are sent through POST body, not queries like the other one.
queries: ?param = ...
body: (like POST form; hidden from the URL)
If you unsure whether you are passing them alright, you can test that easily by console.info(...) on a certain point; and using Postman to easily test POST behavior.

Categories

Resources