I'm trying to add a contact form in my website using nodemailer.
With plain-text, the email was sent (with the cmd node server.js), but since I have added a form in my html and tried to send the "req.bodies" using a route, it doesn't work anymore and I have the following error : Error: Missing credentials for "PLAIN".
Here are my codes :
Index.js
var express = require("express");
var router = express.Router();
const nodemailer = require("nodemailer");
/* GET home page. */
router.get("/", function (req, res, next) {
res.render("index", { title: "Express" });
});
router.post("/send-email", async function (req, res, next) {
"use strict";
var email = req.body.email;
var name = req.body.name;
var message = req.body.message;
var transporter = nodemailer.createTransport({
// host: "smtp.gmail.com",
service: "gmail",
// secure : false,
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD,
},
});
console.log("message :", req.body.message, "email :", req.body.email);
// send mail with defined transport object
var mailOptions = {
from: email,
to: process.env.EMAIL,
subject: "Nouveau mail contact de " + name, // Subject line
text: name + "0102030405" + message,
};
transporter.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
} else {
res.redirect("/");
}
});
});
module.exports = router;
Server.js
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const port = 3000;
require("dotenv").config();
app.use(bodyParser.json());
const nodemailer = require("nodemailer");
app.listen(port, () => {
console.log(`Server running on ${port}`);
});
app.use("/index", require("./routes/index"));
// let transport = nodemailer.createTransport({
// service: "gmail",
// auth: {
// user: process.env.EMAIL,
// pass: process.env.PASSWORD,
// },
// });
// let mailOptions = {
// from: '"Fred Foo đź‘»" <process.env.EMAIL>', // sender address
// to: "process.env.EMAIL", // list of receivers
// subject: "Hello âś”", // Subject line
// text: "Hello world?", // plain text body
// html: "<b>Hello world?</b>", // html body
// };
// transport.sendMail(mailOptions, function (err, data) {
// if (err) {
// console.log("Error Occurs");
// } else {
// console.log("Email sent !!");
// }
// });
html
<form action="/send-email" method="POST">
Your Name:
<input type="text" name="name">
Email Address:
<input type="email" name="email" placeholder="Email">
Message:
<textarea name="message"></textarea>
<input type="submit" value="Submit">
</form>
Body-Parser doesn't seem to work because it is strikeout.
“less secure” apps is enabled on my gmail account
Thank you very much for your help !
EDIT : I think it's because it doesn't recognize my process.env because when I directly write them, it works.
I put my file .env in the same directory but it still does not recognize them.
Related
So i have the main nodejs server file (myserver.js)
const express = require("express");
const app = express();
const nodemailer = require("nodemailer");
const port = 80;
const vectorExpress = require("./node_modules/#smidyo/vectorexpress-nodejs/index");
const fs = require("fs");
var cors = require("cors");
app.use(cors());
app.use(express.json())
var randomnum = require('./randomnum.js');
var number = randomnum.number;
app.post('/mail', (req, res)=>{
console.log(req.body)
let transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: '',
pass: ''
}
});
const mailOptions = {
from: req.body.email,
to: 'naizeylines.info#gmail.com',
subject: `Order from ${req.body.name}`,
text:
`${req.body.name}
${req.body.street}
${req.body.postcode} ${req.body.town}
${req.body.country}
Quantity: ${req.body.quantity}
Additional information:
${req.body.message}
Shipping address:
${req.body.name2}
${req.body.street2}
${req.body.postcode2} ${req.body.town2}
${req.body.country2}
${req.body.phone2}
Email: ${req.body.email}
Phone number: ${req.body.phone}
File number: ${number}
`,
attachments: [{ // utf-8 string as an attachment
path: `${number}.svg`,
},
{
path: `${number}.dxf`,
},
]
}
transporter.sendMail(mailOptions, (error, info)=>{
if(error){
console.log(error);
res.send('error');
}else{
console.log('Email sent:' + info.response);
res.send('success');
}
})
})
var bodyParser = require("body-parser");
and a seperate script file (randomnum.js)
function randomnumber() {
return Math.floor(100000 + Math.random() * 900000);
}
var number = randomnumber();
exports.number = number;
console.log(number);
i would like to have it so that everytime nodemailer sends an email the main script would run the randomnum.js so that i would get a new random number generated. been trying for a few days now but i think im in over my head with my limited knowledge.
Based on code you provided, I see one obvious issue. You are defining randomnum out of the POST request. Also If i were you I'd generate random number inside of the myserver.js file.
Try this bit of code:
app.post('/mail', (req, res)=>{
var number = Math.floor(100000 + Math.random() * 900000)
let transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: '',
pass: ''
}
}); REST OF YOUR POST REQUEST LOGIC.....
Put Nodemailer code in separate file and export in main.js file and use with pass your data from main.js file
Hope this code will help to you
const nodemailer = require("nodemailer");
import * as dotenv from "dotenv";
dotenv.config({});
export class SendEmail {
public static send(data) {
const transport = nodemailer.createTransport({
name: process.env.SMTP_HOST,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER_NAME,
pass: process.env.SMTP_PASSWORD,
},
pool: true, // use pooled connection
rateLimit: true, // enable to make sure we are limiting
maxConnections: 1, // set limit to 1 connection only
maxMessages: 3, // send 3 emails per second
});
var mailOptions = {
from: process.env.FROM,
html: data.html,
replyTo: process.env.REPLY_TO,
to: data.to,
subject: data.subject,
text: data.text,
};
transport.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log("Message sent: %s", info.messageId);
return;
});
}
}
I have a contact form on my website that I created with Node.js. When I run the site as a local host (localhost:5000), everything works fine. I fill out the contact form and when I hit send, I get a thank you alert and the email goes through.
However, once I connected my site to a domain and had it live, it no longer works - I get the "invalid login" message. I wrote an "if statement" in JS to return this "invalid login" error if the request does not go through, which is what I keep getting.
Could it be that I am not connecting to the correct server?
I'm guessing the xhr variable I use in my code is not valid once I begin using an actual hosting service. If so, how can I fix that?
Here is my code.
form.addEventListener('submit', (e)=>{
e.preventDefault();
console.log('submit clicked')
let formData = {
email: email.value,
level: password.value,
amount: amount.value,
service: service.value,
details: details.value,
email: email.value
}
let xhr = new XMLHttpRequest();
xhr.open('POST', '/');
xhr.setRequestHeader('content-type', 'application/json');
xhr.onload = function() {
console.log(xhr.responseText);
if (xhr.responseText == 'success'){
alert('Thank you! An Ogma representative will contact you shortly.');
email.value = '';
password.value = '';
amount.value = '';
service.value = '';
details.value = '';
email.value = '';
}else{
alert('Invalid login')
}
}
xhr.send(JSON.stringify(formData));
})
Edit: Here is my code with nodemailer. It is my Server.js file.
const express = require('express');
const app = express();
const nodemailer = require("nodemailer");
const PORT = process.env.PORT || 5000;
//Middleware
app.use(express.static('public'));
app.use(express.json())
app.get('/', (req, res)=>{
res.sendFile(__dirname + '/public/Request.html')
})
app.post('/', (req, res)=>{
console.log(req.body);
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: '//kept hidden',
pass: //kept hidden
}
})
const mailOptions = {
from: req.body.email,
to: '//kept hidden',
subject: 'New message from Ogma',
text: [req.body.email, req.body.password, req.body.amount, `req.body.service, req.body.details].join('\n\n')`
}
transporter.sendMail(mailOptions, (error, info) =>{
if(error){
console.log(error);
res.send('error');
} else {
console.log('Email sent: ' + info.response);
res.send('success')
}
})
})
app.listen(PORT, ()=>{
console.log('Server running on port ${PORT}')
})
My code is working but res.redirect() is not redirecting me to other pages, I am using pug as template engine. this is my first time using pug. (adding this extra text to question because It looks like your post is mostly code; please add some more details. error is not letting me post lol. )
const express = require("express");
const mongoose = require("mongoose");
const User = require("./model/user");
const bcrypt = require("bcrypt");
const login = require("./routes/login");
const register = require("./routes/register");
const dashboard = require("./routes/dashboard");
const home = require("./routes/home");
const crypto = require("crypto");
const dotenv = require("dotenv").config();
// Connecting Database
mongoose
.connect(process.env.DB, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => {
console.log("Database Connected!");
});
const app = express();
// Setting view engine to pug
app.set("view engine", "pug");
// parsing json
app.use(express.json());
// Routes
app.use("/login", login);
app.use("/register", register);
app.use("/dashboard", dashboard);
app.use("/", home);
// creating a new user
app.post("/register", async (req, res) => {
const { username, email, password } = req.body;
const hashedPass = await bcrypt.hash(password, 10);
User.create({
username: username,
email: email,
password: hashedPass,
emailToken: crypto.randomBytes(64).toString("hex"),
});
});
// logging in the user
app.post("/login", async (req, res) => {
const { email, password } = req.body;
const findUser = await User.findOne({ email: email });
console.log(findUser);
if (findUser) {
const match = await bcrypt.compare(password, findUser.password);
if (match) {
console.log("User logged in");
// This is not working
res.redirect("/dashboard");
} else {
console.log("Invalid Password !");
}
} else {
console.log("User not registered !");
}
});
app.listen(process.env.PORT, () => {
console.log("Server to chal gya ji...");
});
This is my pug file for login.
doctype html
html
head
body
form(id="form")
h1 Login
label Email
input(id="email" type="text")
br
br
label Password
input(id="password" type="password")
br
br
input(type="submit" id="btn" value="Login")
br
br
a(href="/register") Register
script
include login.js
And this is login.js from where I am sending a post request using fetch.
const form = document.querySelector("#form");
form.addEventListener("submit", registerUser);
async function registerUser(e) {
e.preventDefault();
const email = document.querySelector("#email").value;
const password = document.querySelector("#password").value;
const output = await fetch("/login", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({
email,
password,
}),
});
}
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.
I need your help. I want to make User registration form and use Nodejs, Express.js, MongoDB(mongoose) and give me very simple example how to make user registration form with: Name, Email, Password and Mobile Number :) I've made mongoose schema and give values like that Name: req.body.name but it won't work :/ In my oppinion I made something bad.
this is my code and if you think it's not correct, please correct it. (sorry for my bad english). this is server.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/addressbookdb');
var express = require('express');
var app = express();
var db = mongoose.connection;
app.use(express.static(__dirname + '/../client'));
app.post("/",function(req,res){
res.end("Registration Succesfully Completed!");
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
console.log("connected.")
});
// Schema
var RegSchema = mongoose.Schema({
Name: String,
Email: String,
Pass: String,
Num: Number,
reg_time : {
type : Date, default: Date.now
}
}, { collection: 'AddressCol' });
// Model
var UserReg = mongoose.model('UserReg', RegSchema);
// Add in collection
var UserAdd = new UserReg({
Name: req.body.name,
Email: req.body.email,
Pass: req.body.pass,
Num: req.body.num,
});
// Save
UserAdd.save(function (err, fluffy) {
if (err) return console.error(err);
});
});
app.listen(8000, function() {
console.log("Server is running!");
});
and this is my HTML page:
<div class="form-group">
<input type="text" class="form-control" id="name" placeholder="name><br>
<input type="email" class="form-control" id="email" placeholder="Email"><br>
<input type="password" class="form-control" id="pass" placeholder="Password"><br>
<input type="number" class="form-control" id="num" placeholder="Number"><br>
<button type="submit" class="btn btn-primary" id="reg-form-btn">Registration!</button>
</div>
<script>
$(document).ready(function() {
$("#reg-form-btn").click(function() {
var name = $("#name").val();
var email = $("#email").val();
var pass = $("#pass").val();
var num = $("#num").val();
$.post("/", {
Name: name,
Email: email,
Pass: pass,
Num: num
});
});
});
</script>
Maybe you should consider Passport or another module.
But you can do something like this:
app.post('/signup', function (req, res, next) {
var user = {
Name: req.body.name,
Email: req.body.email,
Pass: req.body.pass,
Num: req.body.num
};
var UserReg = mongoose.model('UserReg', RegSchema);
UserReg.create(user, function(err, newUser) {
if(err) return next(err);
req.session.user = email;
return res.send('Logged In!');
});
});
app.post('/login', function (req, res, next) {
var email = req.body.email;
var pass = req.body.pass;
User.findOne({Email: email, Pass: pass}, function(err, user) {
if(err) return next(err);
if(!user) return res.send('Not logged in!');
req.session.user = email;
return res.send('Logged In!);
});
});
app.get('/logout', function (req, res) {
req.session.user = null;
});
Then you should have a middleware to handle authentication
function isLoggedIn (req, res, next) {
if (!(req.session && req.session.user)) {
return res.send('Not logged in!');
}
next();
}
And use it on the private routes
app.get("/api", isLoggedIn, function (req, res) {
//Something private
})
Here is a nice tutorial how to make what you want using very useful module passport. Also you will have a quick look at Jade template engine which can be useful in your further learning of creating express apps.
check this tutorial...you can ignore Angular and mongojs if you want:
http://www.phloxblog.in/single-page-application-angular-js-node-js-mongodb-mongojs-module/#.Vc20OXW1Gkq
You are missing body-parser. Try this in your server code:
const bodyParser = require('body-parser');
app.use(bodyParser);
Please refer the question How to access the request body when POSTing using Node.js and Express?