Send route not being found, - node.js

I am trying to use nodemailer to send an email from the contact page. I have built the site with a MERN stack. All the other routes work perfectly fine. I can setup a new user, write a post and login an existing user. The only part where the routes break is when the mail is sent on the contact page.
Below is the middleware:
const app = express();
// Connect Database
connectDB();
// Init Middleware
app.use(express.json());
// Define Routes
app.use('/api/users', require('./routes/api/users'));
app.use('/api/auth', require('./routes/api/auth'));
app.use('/api/profile', require('./routes/api/profile'));
app.use('/api/posts', require('./routes/api/posts'));
app.use('/api/send', require('./routes/api/send'));
Below is the send route:
var express = require('express');
var config = require('config');
var router = express.Router();
var nodemailer = require('nodemailer');
var cors = require('cors');
// #route POST api/send
// #desc Send email on contact page
// #access Public
router.post('/send',(req, res ) => {
var name = req.body.name
var email = req.body.email
var subject = req.body.subject
var message = req.body.message
var content = `
name: ${name} \n
email: ${email} \n
subject: ${subject} \n
message: ${message} `
var mail = {
from: name,
to: receiver, // receiver email,
subject: subject,
text: content
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
status: 'fail'
})
} else {
res.json({
status: 'success'
})
}
})
});
module.exports = router;
I get a 404 error when I submit the form on contact page. Below is the contact page:
const ContactForm = () => {
const [state, setState] = useState({
name: '',
email: '',
subject: '',
message: ''
});
const [result, setResult] = useState(null);
const sendEmail = event => {
event.preventDefault();
axios
.post('/send', { ...state })
.then(response => {
setResult(response.data);
setState({
name: '',
email: '',
subject: '',
message: ''
});
})
.catch(() => {
setResult({
success: false,
message: 'Something went wrong. Try again later'
});
});
};
const onInputChange = event => {
const { name, value } = event.target;
setState({
...state,
[name]: value
});
};
This is my handler:
const nodemailer = require ('nodemailer');
nodemailer.createTransport({
host: "smtp.gmail.com", //replace with your email provider
port: 587,
auth: {
user: process.env.email,
pass: process.env.password
}
});
// verify connection configuration
transporter.verify(function(error, success) {
if (error) {
console.log("error at mail send");
} else {
console.log("Server is ready to take the messages");
}
});
module.exports = transporter
To debug I have tried to change the POST route to
(req, res, next)
(req, res, send)

It seems like you missing transpoter object.
You need to create it with nodemailer.createTranspot
const transpoter = nodemailer.createTranspot({
service: 'gmail',
auth: {
user: 'sender#gmail.com',
pass: 'password'
}
})
then try it.

This has been solved by:
Moving the transporter to the send route
The route that the server is using was api/send/send on the POST route it should be /

Related

POST 405 (Not Allowed) after deploying on heroku

this is my first time using React and Node.js to create a web app that has a contact form using nodemailer and axios. Everything seems to be working on localhost, however, after I deployed it on heroku, I got a "POST https://myapp.herokuapp.com/ 405 (Not Allowed)" when I try to send an email using the form
my index.js
const path = require('path');
const express = require('express');
const rateLimit = require("express-rate-limit");
const transporter = require('./config');
const dotenv = require('dotenv');
dotenv.config();
const app = express();
const buildPath = path.join(__dirname, '..', 'build');
const PORT = process.env.PORT || 3030;
app.use(express.json());
app.use(express.static(buildPath));
const limiter = rateLimit({
windowMs: 30 * 1000, // 30 seconds
max: 1 // limit each IP to 1 requests per windowMs
});
// apply to all requests
app.use(limiter);
app.post('/send', (req, res) => {
try {
const mailOptions = {
from: req.body.email,
to: process.env.email,
subject: req.body.subject,
html:
`<p>New Contact Request</p>
<h2>Contact Details</h2>
<ul>
<li>Name: ${req.body.name}</li>
<li>Email: ${req.body.email}</li>
<li>Subject: ${req.body.subject}</li>
<li>Message: ${req.body.message}</li>
</ul>
`
};
transporter.sendMail(mailOptions, function (err, info) {
if (err) {
res.status(500).send({
success: false,
message: 'Something went wrong. Please try again'
});
}
else {
res.send({
success: true,
message: 'Thanks for contacting me. I will get back to you soon'
});
}
});
}
catch (error) {
res.status(500).send({
success: false,
message: "Something went wrong. Please try again"
});
}
});
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, '../build/index.html'), function (err) {
if (err) {
res.status(500).send(err)
}
})
})
app.listen(PORT, () => {
console.log(`Server Started at PORT ${PORT}`);
});
my emailConfig.js
const nodemailer = require('nodemailer');
const dotenv = require('dotenv');
dotenv.config();
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.email,
pass: process.env.password
}
});
module.exports = transporter
my contact.js
import React, { useState } from 'react';
import './Contact.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Form, Button } from 'react-bootstrap';
import axios from 'axios';
const Contact = () => {
const [state, setState] = useState({
name: '',
email: '',
subject: '',
message: ''
});
const [result, setResult] = useState(null);
const sendEmail = event => {
event.preventDefault();
axios
.post('/send', { ...state })
.then(response => {
setResult(response.data);
setState({ name: '', email: '', subject: '', message: '' });
})
.catch(() => {
setResult({ success: false, message: 'Something went wrong. Please try again'});
});
};
const onInputChange = event => {
const { name, value } = event.target;
setState({
...state,
[name]: value
});
};
return (
//some html code
);
};
export default Contact;
I've tried adding a Procfile (my index.js is inside a folder called server)
web: node server/index.js
after adding the Procfile and redeployed, I can't even access the website anymore, but instead, an error saying "GET https://my app.herokuapp.com/ 503 (Service Unavailable)"
First of all I'm facing few technical moments.
From my experience I can say show it should be:
Your node.js application should be hosted directly on http and https default ports 80, 443, or behind proxy ex Nginx (You can choose any other). There are some restrictions by browsers when using different ports.
Look inside axios config, when you're posting to send it goes to your app url, but there is no port defined.
Another, more native option is to use react fetch.
It's just how I see software design, so try to deploy your application as api and call it via postman and then from local copy of your frontend.

ReferenceError: transporter is not defined

i am new in react js am getting an error when i am trying to run my node js server
the error is mentioned in my title box please try to fix it as soon as possible.
index.js
this is my index.js file where i wrote my all backend code
let express = require('express');
let app = express();
const path = require('path');
let nodemailer = require('nodemailer');
// Static folder
app.use('/public', express.static(path.join(__dirname, 'public')));
nodemailer.createTransport({
service: 'gmail',
auth: {
user: "harsalpatil512#gmail.com",
pass: "*********"
}
});
// verifying the connection configuration
transporter.verify(function(error, success) {
if (error) {
console.log(error);
} else {
console.log("Server is ready to take our messages!");
}
});
router.post('/access', (req, res, next) => {
var name = req.body.name
var email = req.body.email
var message = req.body.message
var content = ` name: ${name} \n email: ${email} \n message: ${message} `
var mail = {
from: "harsalpatil512#gmail.com",
to: "ashishnirvikar5670#gmail.com",
message: "Welcome to Gmail",
text: "Thanks for contacting us"
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
status: 'fail'
})
} else {
res.json({
status: 'success'
})
}
})
})
const PORT = process.env.PORT || 8080
app.listen(PORT, () => console.info(`server has started on ${PORT}`))
you need to make a little change:
// need to declare transporter first
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: "harsalpatil512#gmail.com",
pass: "*********"
}
});

ERR EMPTY RESPONSE

I am trying to add a contact form that will send to a dedicated gmail account. I have got the contact form working independently but when I try and add it to my working project it does not work and the error I get is:
Cannot POST /api/send
The project is a MERN stack. Below is the mailer.js middleware:
import nodemailer from 'nodemailer'
import config from '../config'
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
auth: {
user: process.env.username,
pass: process.env.password,
}
});
const send = ({ email, name, text }) => {
const from = name && email ? `${name} <${email}>` : `${name || email}`
const message = {
from,
to: 'react.nodemailer#gmail.com',
subject: `New message from ${from} at creating-contact-forms-with-nodemailer-and-react`,
text,
replyTo: from
};
return new Promise((resolve, reject) => {
transporter.sendMail(message, (error, info) =>
error ? reject(error) : resolve(info)
)
})
}
export default send
The server.js on the backend is:
const express = require('express');
const connectDB = require('./config/db');
const path = require('path');
// // ********************
// // CONTACT FORM
// // ********************
const cors = require ("cors")
const nodemailer = require("nodemailer")
// // ********************
// // CONTACT FORM
// // ********************
const app = express();
// // Connect Database
connectDB();
// Init Middleware
app.use(express.json());
// // ********************
// // CONTACT FORM
// // ********************
app.use(cors());
app.post('/contact', (req, res) => {
const { email = '', name = '', message = '' } = req.body
mailer({ email, name, text: message }).then(() => {
console.log(`Sent the message "${message}" from <${name}> ${email}.`);
res.redirect('/#success');
}).catch((error) => {
console.log(`Failed to send the message "${message}" from <${name}> ${email} with the error ${error && error.message}`);
res.redirect('/#error');
})
})
// // ********************
// // CONTACT FORM
// // ********************
// Define Routes
app.use('/api/users', require('./routes/api/users'));
app.use('/api/auth', require('./routes/api/auth'));
app.use('/api/profile', require('./routes/api/profile'));
app.use('/api/posts', require('./routes/api/posts'));
app.use('/api/send', require('./routes/api/send'));
// Serve static assets in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
The contact form is:
import React, { Component } from "react";
import axios from "axios";
class ContactForm extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
message: "",
status: "Submit"
};
}
handleSubmit(event) {
event.preventDefault();
this.setState({ status: "Sending" });
axios({
method: "POST",
url: "api/send",
data: this.state,
}).then((response) => {
if (response.data.status === "sent") {
alert("Message Sent");
this.setState({ name: "", email: "", message: "", status: "Submit" });
} else if (response.data.status === "failed") {
alert("Message Failed");
}
});
}
handleChange(event) {
const field = event.target.id;
if (field === "name") {
this.setState({ name: event.target.value });
} else if (field === "email") {
this.setState({ email: event.target.value });
} else if (field === "message") {
this.setState({ message: event.target.value });
}
}
This is the api POST route.
var express = require('express');
var config = require('config');
var router = express.Router();
var cors = require('cors');
// #route POST api/send
// #desc Send email on contact page
// #access Public
router.post('/api/send',(req, res, next ) => {
var name = req.body.name
var email = req.body.email
var subject = req.body.subject
var message = req.body.message
var content = `
name: ${name} \n
email: ${email} \n
subject: ${subject} \n
message: ${message} `
var post = {
from: name,
subject: subject,
text: content
}
});
module.exports = router;
I have been trying to debug this for a week or so. I am currently trying to find out why the POST route is not working.
The error codes I have got are 500 internal server error and 404 not found. The url it will be going to is http://localhost:5000/api/send
Change
router.post('/api/send',(req, res, next )
to
router.post('/',(req, res, next )
In your express app your already have.
app.use('/api/send', require('./routes/api/send'));
Thus, for all "/api/send" we will look in the file './routes/api/send'.
The way you defined it you will have to query it like http://localhost:5000/api/send/api/send.
You will have
router.post('/',(req, res, next ) => {
var name = req.body.name
var email = req.body.email
var subject = req.body.subject
var message = req.body.message
var content = `
name: ${name} \n
email: ${email} \n
subject: ${subject} \n
message: ${message} `
var post = {
from: name,
subject: subject,
text: content
}
});
module.exports = router;
Also how about moving routes to its own file. i.e in server have
app.use(require('./routes/api'));
And in ./routes/api/index.js have the definitions there. i.e
const express = require('express');
const router = express.Router();
router.use('/api/send', require('./send'));
module.exports = router;
You can directly register the route on the express app like below,
app.post('/api/send',function(){
//..send code
//nodemailer.send("blabla")
});
instead of registering routes both on app and router.

Nodejs Email attachment issue browse file through Postman form-data

Hi,
I am Facing issues with the Email attachment,
Please tell me how can i send file that i browse from form-data in postman.
how to refer the path of that file?
//const Joi = require('joi');
const express = require('express'); //This returns a function
const app = express();
app.use(express.json());
var nodemailer = require('nodemailer');
var send = require('gmail-send');
var fileupload = require('express-fileupload');
app.use(fileupload());
var config = require('./config.json')
const Joi = require('joi');
This is the Post method for validating the email data.
//POST
app.post('/api/sendemail', (req, res) => {
//No need to validate using JOI, Email validation is done using sendMail()
const schema = {
to: Joi.string().min(3).required(),
subject: Joi.string().min(1).required(),
text: Joi.string()
};
const result = Joi.validate(req.body, schema);
if (result.error) {
res.status(400).send(result.error);
return;
}
Transporter variable contains the sending info.
let transporter = nodemailer.createTransport({
service: 'gmail',
host: 'smtp.gmail.com',
port: 465,
ssl: 'true',
auth: {
user: config.sender,
pass: config.password
},
});
In this Mail Info Look at Attachments,how to right the path?
let Mailinfo = {
from: config.sender,
to: req.body.to,
subject: req.body.subject,
text: req.body.text,
attachments: [
{ filename: req.files }
]
}
transporter.sendMail(Mailinfo, (error, info) => {
if (error) {
res.send(error);
} else {
console.log(req.files);
res.send('Email sent successfully' + info.response);
}
});
});
Here is the POrt connection
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}....`));
You can use sendgrid api with :
npm install #sendgrid/mail
const sgMail = require('#sendgrid/mail')
sgMail.setApiKey(yourapikey)
let msg = {
to: email,
from: your email,
subject: your subject,
text: your text,
html: your html file,
}
await sgMail.end(msg)

nodemailer not sending email on server?

So i have created a form with a react front end and a node js and nodemailer backend. I am trying to send that data in an email. I can send it to the back end at that is received perfectly fine however, I am getting an issue when sending out the emaiil as the 'mail not sent' error is getting executed from the Transporter.sendMail function and I'm not to sure why.
Would love to get some help. Please see the code below for my server. I have obviously removed my authentication details for security purposes.
console log error:
[0] not sent
const nodemailer = require('nodemailer');
const path = require('path');
const express = require("express");
const app = express();
const port = 5000;
const cors = require("cors");
app.use(cors());
const bodyParser = require("body-parser");
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(
bodyParser.urlencoded({
// to support URL-encoded bodies
extended: true
})
);
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'email',
pass: 'password',
}
});
app.get("/home", (req, res) => {
console.log("Hello from .get /home", req.body.generalDetails, req.body.firstName, req.body.mName );
})
app.post("/home", (req, res) => {
var mailOptions = {
from: 'email',
to: 'email',
subject: 'Hello',
text: req.body.generalDetails,
}
transporter.sendMail(mailOptions, function(err, res) {
if (err) {
console.log('Mail not sent');
} else {
console.log('Mail sent');
}
});
let data = [{
//page one data
generalDetails: req.body.generalDetails,
fName: req.body.fName,
mName: req.body.mName,
lName: req.body.lName,
email: req.body.email,
}];
res.json(data);
}
);
app.listen(port, () => `Server running on port ${port}`);
I'd like to modify some snippets in your code as below:
const smtpTransport = nodemailer.createTransport({
service: "Gmail", // <======
auth: {
user: YOUR_GMAIL_ADDRESS,
pass: YOUR_GMAIL_PASSWORD
}
});
...
let mailOptions = {
from: FROM_ADDRESS,
to: TARGET_MAIL_ADDRESS,
subject: 'Hello',
text: req.body.generalDetails,
html: req.body.generalDetails, // <======
};
smtpTransport.sendMail(mailOptions, function (err) {
if (err) {
// failed
} else {
// sent
}
});
...
PS: why don't you share the error log if it still goes on?

Resources