Why am I getting a Nodemailer Cannot /POST error? - reactjs

I wrote a code for a contact us form on nodemailer and I am getting a cannot /post error. What could be the problem? I set up a mailtrap account but listed my email as my regular email. I am not used to using react or node.js so I am having a hard time understanding this. Here is my code:
for contact_us.js:
import React from "react";
import "./contactus.css"
import axios from 'axios';
export default class ContactUs extends React.Component {
state = {
name: '',
subject: '',
email: '',
message: ''
}
constructor(props) {
super(props);
this.onEmailChange= this.onEmailChange.bind(this);
this.onMsgChange= this.onMsgChange.bind(this);
this.onNameChange= this.onNameChange.bind(this);
this.onSubjectChange= this.onSubjectChange.bind(this);
this.submitEmail= this.submitEmail.bind(this);
}
render() {
return (
<div className="section">
<div className="container">
<div className="row">
<div className="col-md-12">
<div className="section-title">
<h2 className="title">Contact Us</h2>
<p>Let us know what you think! </p><hr/>
<form id="contact-form"
method="POST">
<div className="form-group">
<div className="row">
<div className="col-md-6">
<input placeholder = "Name" id="name" type="text"
className="form-control" required value={this.state.name}
//onChange={this.onNameChange.bind(this)}/>
onChange= {this.onNameChange}/>
</div>
<div className="col-md-6">
<input placeholder = "Email" id="email" type="email"
className="form-control" aria-describedby="emailHelp"
required value={this.state.email}
//onChange=
//{this.onEmailChange.bind(this)}
onChange= {this.onEmailChange}
/>
</div>
</div>
</div>
<div className="form-group">
<input placeholder = "Subject" id="subject" type="text"
className="form-control" required value={this.state.subject}
//onChange={this.onSubjectChange.bind(this)}
onChange= {this.onSubjectChange}/>
</div>
<div className="form-group">
<textarea placeholder = "Message" id="message"
className="form-control" rows="1"
required value={this.state.message}
//onChange= {this.onMsgChange.bind(this)}
onChange={this.onMsgChange}/>
</div>
<button className= "button" type="submit" id="button" onSubmit={this.submitEmail} >Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
onNameChange(event) {
this.setState({name: event.target.value})
}
onEmailChange(event) {
this.setState({email: event.target.value})
}
onSubjectChange(event) {
this.setState({subject: event.target.value})
}
onMsgChange(event) {
this.setState({message: event.target.value})
}
submitEmail(e){
console.log('submitting');
e.preventDefault();
axios({
method: "POST",
url:"localhost:3000/contact_us",
data: this.state
}).then((response)=>{
if (response.data.status === 'success'){
alert("Message Sent.");
this.resetForm()
}else if(response.data.status === 'fail'){
alert("Message failed to send.")
}
})
}
resetForm(){
this.setState({name: '', email: '',subject:'', message: ''})
}
}
for index.js:
var express = require('express');
var router = express.Router();
var nodemailer = require('nodemailer');
require('dotenv').config();
var cors = require('cors');
const creds = require('./config');
var app= express();
const port= 4000;
app.use((request, response, next) => {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "Content-Type");
next();
});
const transporter = nodemailer.createTransport({
host: 'smtp.mailtrap.io',
port: 2525,
auth: {
user: '',
pass: ''
}
});
transporter.verify(function(error, success) {
if (error) {
console.log(error);
} else {
console.log("Server is ready to take our messages");
}
});
app.post('/contact_us', (req, res, next) => {
var name = req.body.name
var email = req.body.email
var subject = req.body.subject
var message = req.body.message
var mail = {
from: name,
to: '',//my regular email I used to sign up to mailtrap
subject: subject,
text: message
}
transporter.sendMail(mail, (err, data) => {
if (err) {
console.log('failed');
res.json({
status: 'fail'
})
} else {
console.log('successful');
res.json({
status: 'success'
})
}
})
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

First spot:
Add HTTP to the URL "http://localhost:3000/contact_us" and change the port to 4000 since the API is working under such port. Check if this is enough to get it working

Related

Sending email using react and nodemailer

Been trying to make a contact form which uses nodemailer. I used Postman to check if my backend is working, and it is. I even get an email in my outlook. However, I am stuck at the front end bit. I just can't seem to get the actual contact form to send an email on submit. My code is below.
Backend
app.use(express.json());
app.use(bodyParser.json());
app.use(cors());
app.use(express.urlencoded({ extended: false }));
const transporter = nodemailer.createTransport({
service: "hotmail",
auth: {
user: ,
pass: ,
}
});
transporter.verify(function (error, success) {
if (error) {
console.log(error);
} else {
console.log("Server is ready to take our messages");
}
});
app.post('/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 mail = {
from: name,
to: ,
subject: subject,
text: message
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
status: 'fail'
})
} else {
res.json({
status: 'success'
})
}
})
})
Frontend
import axios from "axios";
import React from 'react';
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
subject: '',
message: ''
}
}
onNameChange(event) {
this.setState({ name: event.target.value })
}
onEmailChange(event) {
this.setState({ email: event.target.value })
}
onSubjectChange(event) {
this.setState({ subject: event.target.value })
}
onMsgChange(event) {
this.setState({ message: event.target.value })
}
submitEmail(e) {
e.preventDefault();
axios({
method: "POST",
url: "/send",
data: this.state
}).then((response) => {
if (response.data.status === 'success') {
alert("Message Sent.");
this.resetForm()
} else if (response.data.status === 'fail') {
alert("Message failed to send.")
}
})
}
resetForm() {
this.setState({ name: '', email: '', subject: '', message: '' })
}
render() {
return (
<div className="section">
<div className="container">
<div className="row">
<div className="col-md-12">
<div className="section-title">
<h2 className="title">Contact Us</h2>
<p>Let us know what you think! In order to provide better service,
please do not hesitate to give us your feedback. Thank you.</p><hr />
<form id="contact-form" onSubmit={this.submitEmail.bind(this)}
method="POST">
<div className="form-group">
<div className="row">
<div className="col-md-6">
<input placeholder="Name" id="name" type="text"
className="form-control" required value={this.state.name}
onChange={this.onNameChange.bind(this)} />
</div>
<div className="col-md-6">
<input placeholder="Email" id="email" type="email"
className="form-control" aria-describedby="emailHelp"
required value={this.state.email} onChange=
{this.onEmailChange.bind(this)} />
</div>
</div>
</div>
<div className="form-group">
<input placeholder="Subject" id="subject" type="text"
className="form-control" required value={this.state.subject}
onChange={this.onSubjectChange.bind(this)} />
</div>
<div className="form-group">
<textarea placeholder="Message" id="message"
className="form-control" rows="1"
required value={this.state.message}
onChange={this.onMsgChange.bind(this)} />
</div>
<button type="submit" className="primary-btn submit">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default ContactForm;

Why does my Nodemailer POST request work in postman but not from my react front-end?

I am using the Nodemailer package and a SendinBlue smtp email server to create a website contact form. When I send a request using postman the email sends and everything works as it should, however, when I try an Axios post request from my react front-end (in both production and live environments) I get the following:
POST http:///send 404 (Not Found)
My Server.js file:
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3001;
const nodemailer = require('nodemailer')
require('dotenv').config();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, 'build')));
}
// Catch all route to redirect unmanaged routes back to the react app.
// THIS OPTION IS NOT SEO OPTIMIZED
// THIS ROUTE SENDS ALL SAVED LINKS TO THE ROOT
app.get('/*', function (req, res) {
res.redirect('/')
});
// CONNECTION NOT YET TESTED
// Nodemailer config to handle contact form submit.
let transporter = nodemailer.createTransport({
host: "smtp-relay.sendinblue.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// Post route for contact form submission
app.post('/send', (req, res) => {
console.log(req.body)
var { name, email, message } = req.body;
let mailOptions = {
from: `"${name}" <${email}>`, //'"Fred Foo 👻" <foo#example.com>', sender address
to: `${process.env.EMAIL}`, // list of receivers
subject: "Atlas Pet Contact Form",
text: `${message}`, // plain text body
}
transporter.sendMail(mailOptions, function (err, data) {
if (err) {
console.log('Error: ', err)
} else {
console.log('Email Sent')
}
});
res.json('Email Sent');
});
app.listen(PORT, () => { console.log(`API Server now listening on PORT ${PORT}!`) })
React contact component:
import React, { useState } from "react";
import axios from "axios";
import "../../pages/style.css";
function ContactForm() {
const [formData, setFormData] = useState({
name: "",
email: "",
message: ""
});
function sendEmail(e) {
e.preventDefault();
axios.post("/send", formData)
.then(res => {
console.log(res)
console.log(res.data)
})
.catch(err => {
console.log(err)
})
};
function handleNameChange(e) {
setFormData({ ...formData, name: e.target.value })
};
function handleEmailChange(e) {
setFormData({ ...formData, email: e.target.value })
};
function handleMessageChange(e) {
setFormData({ ...formData, message: e.target.value })
};
return (
<div className="jumbotron form-spacing">
<form className="form">
<h1 className="display-4 main-txt"><strong>Drop a Line</strong></h1>
<br/>
<div className="hr"></div>
<br/>
<p className="lead main-txt">Questions, Comments, Concerns? Let us know!</p>
{/* Name input */}
<label htmlFor="name">Name</label>
<input
className="inputs"
type="text"
id="name"
name="name"
onChange={handleNameChange}
></input>
<br />
{/* Email input */}
<label htmlFor="email">Email</label>
<input
className="inputs"
type="email"
id="email"
name="email"
onChange={handleEmailChange}
></input>
<br />
{/* Message input */}
<label htmlFor="message">Message</label>
<textarea
className="inputs"
rows="6"
id="message"
name="message"
onChange={handleMessageChange}
></textarea>
{/* Submit button */}
<button
className="submit-btn btn btn-light btn-submit"
type="submit"
value="Send Message"
onClick={sendEmail}
>Send Message</button>
</form>
<div className="row-overlay"></div>
</div>
)
}
export default ContactForm;

React form submit triggers two times

I have React login form. The problem is form submit is called two times. I dont understand it. Can somebody tell me please why? Thanks a lot.
import React from "react"
import LoginErrors from "./LoginErrors"
import LoginSuccess from "./LoginSuccess"
import axios from 'axios'
import { withRouter } from "react-router-dom";
class Login extends React.Component
{
constructor(props)
{
super(props)
this.state = {
name: '',
password: '',
errors: [],
success: []
}
}
changeName = e =>
{
this.setState({name: e.target.value});
}
changePassword = e =>
{
this.setState({password: e.target.value});
}
sendData(e)
{
e.preventDefault();
this.setState({'errors': [], 'success': []});
let formData = new FormData();
formData.set('name', this.state.name);
formData.set('password', this.state.password);
axios({
method: 'POST',
url: 'http://localhost:8000/login',
data: formData,
headers: {
'Content-Type': 'text/html',
'X-Requested-With': 'XMLHttpRequest',
}
})
.then(response => {
// ? returns undefined if variable is undefined
if( response.data?.errors?.length )
{
this.setState({errors: response.data.errors})
}
if( response.data?.success?.length )
{
let data = response.data
this.props.setAccessToken(data.token)
this.props.setUserName(data.user.name)
this.props.history.push('/')
}
})
.catch(response => {
this.setState({errors: ['Login fails. Try it again later please.']})
});
}
render() {
return (
<div className="row justify-content-md-center">
<div className="col-sm-12 col-md-6">
<div id="loginForm">
<h2 className="">Login</h2>
<LoginSuccess success={this.state.success} />
<LoginErrors errors={this.state.errors} sendParentMessage={this.handleErrorsChildMessage} />
<form onSubmit={e => {this.sendData(e)}}>
<div className="form-group">
<label htmlFor="name">Name</label>
<input ref={this.email} name="name" className="form-control" type="text" onChange={this.changeName} />
</div>
<div className="form-group">
<label htmlFor="password">Heslo</label>
<input ref={this.password} name="password" className="form-control" type="password" onChange={this.changePassword} />
</div>
<div className="form-group">
<button name="sbmt" className="btn btn-primary" type="submit">Odoslať</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
So the problem is in axios preflyght request which is related to the CORS policy. But How to stop it?

Redirection to dashboard after login in react

I have a login page, and I want to redirect users to dashboard after the details are filled.
I have tried using history.push and redirect components but I couldn't redirect.
Login Page
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default Login;
I want to redirect to other page once the form is submitted with the email and password.
I've been trying this for days but I couldn't find a solution.
import { withRouter } from 'react-router';
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
this.props.history.push("/dashboard");
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default withRouter(Login);
have some complain about your code.
first: for form validation and handling you dont need to use state,
there is a library called Formik which will help you a lot with
this.
second: if you are using redux to check user is logged in or
not you need to create a private route for routes which cannot be
accessible for public like here dashboard component.
third: to use history you need to wrap your
component inside withRouter HOC which will pass route props to your
component so you can use history or if your are using functional component you can use useHistory() hook.

Passing data from front end to route in backend React

I am currently new to using React and express, I wish to send data which i have received from a form. The data i would like to send back is the UserInfo or email which is in the state. However I am extremely unsure how I am supposed to go about this request.
class ForgotPassword extends Component {
constructor() {
super()
this.state = {
email:'',
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
componentDidMount = () =>{
// this.fetchUserInfo();
}
handleChange = (e) => {
this.setState ({
[e.target.id]: e.target.value
})
console.log(this.state);
}
handleSubmit = async (e) => {
e.preventDefault();
const userInfo = {
email : this.state.email
};
fetch("/forgotpassword", {
method: "POST",
body: JSON.stringify(userInfo),
headers: { "Content-Type": "application/json" }
})
.then(response => {
return response.json();
})
.then(jsonData => {
console.log(jsonData);
})
.catch(err => {
console.log("Error with data fetch " + err);
});
};
This is my form...
<div className='row'>
<div className='col'></div>
<div className='col card form'>
<h1 id="title">Reset Password</h1>
<h5 id="passinstruc">Please enter your email to reset your password</h5>
<form id="forgotpass" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email </label>
<input onChange={this.handleChange} type="email" className="form-control" id="email" aria-describedby="emailHelp" placeholder="Enter email" value={this.state.email} />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<button id="loginbtn" type="submit" className="btn btn-primary btn-lg btn-block" >Submit</button>
<br/>
<div className='division'>
<Link to="/register" className='btn btn-primary btn-lg btn-block' id="registerbtn" > Create your account here</Link>
</div>
</form>
</div>
In my backend I am getting a POST /forgotpassword 404 message but I dont know why. Help would be much appreciated.
This is my backend route where I will be sending the information
var express = require('express');
var router = express.Router();
var connection = require ('../connection');
var email = require ('./sendEmail');
router.post('/forgotpassword', function(req, res, next) {
console.log(req.email);
var userEmail = req.email;
var text = "Follow the instructions below to reset your password"
email.sendEmailWithTemplate(userEmail,'PetS.o.S Password Reset', text);
});
For sending data you will need the domain name or ip address of your server.
Once you obtained that, you can use jQuery.get - https://api.jquery.com/jQuery.get/
or jQuery.post -
https://api.jquery.com/jQuery.post/
Or if you are not using jQuery, use XMLHttpRequest -
https://www.w3schools.com/xml/xml_http.asp
Instead of sending data in body send it in response.
https://www.freecodecamp.org/news/create-a-react-frontend-a-node-express-backend-and-connect-them-together-c5798926047c/
fetch('/api/getList')
.then(res => res.json())
.then(list => this.setState({ list }))
https://dev.to/nburgess/creating-a-react-app-with-react-router-and-an-express-backend-33l3

Resources