Sending email using react and nodemailer - reactjs

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;

Related

this.state not populating fields in editProfile.component

Newbie here. Basic question I know. I have made a 'newProfile' component using pretty much the same mechanics as this and it's working! Now I need an editProfile component that updates the Profile form with props from the database using params.id. The URL shows the .id piece is working when I click 'edit' on a profile in a profileList component that is also working. This code is not getting errors, but it is not showing state for each of the fields.
What am I missing?
`
export default class EditProfile extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeFirst = this.onChangeFirst.bind(this);
this.onChangeLast = this.onChangeLast.bind(this);
this.onChangeEmail = this.onChangeEmail.bind(this);
this.onChangePassword = this.onChangePassword.bind(this);
this.onChangeDob = this.onChangeDob.bind(this);
this.onChangeLocation = this.onChangeLocation.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username: '',
first: '',
last: '',
email: '',
password:'',
dob:'',
location:'',
}
}
componentDidMount() {
axios.get('http://localhost:5000/profiles/'+this.props.match.params.id)
.then(response => {
this.setState({
username: response.data.username,
first: response.data.first,
last: response.data.last,
email: response.data.email,
password: response.data.password,
dob: response.data.dob,
location: response.data.location
})
})
.catch(function (error) {
console.log(error);
})
}
componentDidMount() {
axios.get('http://localhost:5000/users/')
.then(response => {
if (response.data.length > 0) {
this.setState({
users: response.data.map(user => user.username),
})
}
})
.catch((error) => {
console.log(error);
})
}
onChangeProfilePic(e) {
this.setState({
profilePic: e.target.value
});
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangeFirst(e) {
this.setState({
first: e.target.value
});
}
onChangeLast(e) {
this.setState({
last: e.target.value
});
}
onChangeEmail(e) {
this.setState({
email: e.target.value
});
}
onChangePassword(e) {
this.setState({
password: e.target.value
});
}
onChangeDob(e) {
this.setState({
dob: e.target.value
});
} onChangeLocation(e) {
this.setState({
location: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
const profile = {
username: this.state.username,
first: this.state.first,
last: this.state.last,
email: this.state.email,
password: this.state.password,
dob: this.state.dob,
location: this.state.location,
}
console.log(profile);
axios.post('http://localhost:5000/profiles/update'+this.props.match.params.id, profile)
.then(res => console.log(res.data));
window.location = '/';
}
render() {
return (
<div>
<h3>Edit Profile
</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username:
</label>
<input
type="text"
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}
/>
</div>
<div className="form-group">
<label>First Name:
</label>
<input
type="text"
className="form-control"
value={this.state.first}
onChange={this.onChangeFirst}
/>
</div>
<div className="form-group">
<label>Last Name:
</label>
<input
type="text"
className="form-control"
value={this.state.last}
onChange={this.onChangeLast}
/>
</div>
<div className="form-group">
<label>Email:
</label>
<input
type="text"
className="form-control"
value={this.state.email}
onChange={this.onChangeEmail}
/>
</div>
<div className="form-group">
<label>Password:
</label>
<input
type="text"
className="form-control"
value={this.state.password}
onChange={this.onChangePassword}
/>
</div>
<div className="form-group">
<input type="submit" value="Save" className="btn btn-primary" />
</div>
</form>
</div>
)}
}
`
Here is the error I'm getting in the console.
react-dom.development.js:86 Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
at input
at div
at form
at div
at CreateProfile (http://localhost:3000/static/js/bundle.js:194:5)
at RenderedRoute (http://localhost:3000/static/js/bundle.js:44214:5)
at Routes (http://localhost:3000/static/js/bundle.js:44678:5)
at div
at Router (http://localhost:3000/static/js/bundle.js:44609:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:42779:5)
at App

Why am I getting a Nodemailer Cannot /POST error?

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

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?

How do I redirect to another page on form submit?

I'm trying to redirect to a certain page once I post my form but it doesn't redirect, it only posts the form data and does not redirect to the stated page
I've tried appending the && operator in order for onSubmit to do both functions but to no avail. I also tried having both "onSubmit" and "onClick" but it's only "onSubmit" that works
//./userspost.js
import React, { Component } from "react";
import { Redirect, Link } from "react-router-dom";
import Form1 from "./form1";
import { createUsers } from "./actions/appactions";
class userspost extends Component {
state = {
redirect: false
};
setRedirect = () => {
this.setState({
redirect: true
});
};
renderRedirect = () => {
if (this.state.redirect) {
return <Redirect to="/users" />;
}
};
handleSubmit(data) {
console.log("form submission data", data);
createUsers(data);
}
render() {
return (
<div>
{this.renderRedirect()}
<Form1 onSubmit={this.handleSubmit && this.setRedirect} />
</div>
);
}
}
export default userspost;
for the posting the form data
//./form1.js
import React from "react";
import { Link } from "react-router-dom";
var createReactClass = require("create-react-class");
const Form1 = createReactClass({
//setting initial state
getInitialState() {
return {
firstName: this.props.firstName,
lastName: this.props.lastName,
userName: this.props.userName,
role: this.props.role
};
},
handleFirstChange(e) {
this.setState({
firstName: e.target.value
});
},
handleLastChange(e) {
this.setState({
lastName: e.target.value
});
},
handleUserChange(e) {
this.setState({
userName: e.target.value
});
},
handleRoleChange(e) {
this.setState({
role: e.target.value
});
},
handleSubmit(e) {
e.preventDefault();
this.props.onSubmit(this.state);
},
render() {
return (
<form
name="categories_post"
className="form-horizontal"
onSubmit={this.handleSubmit}
>
<div id="categories_post">
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="firstName"
>
First Name
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.firstName}
onChange={this.handleFirstChange}
id="firstName"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="lastName"
>
Last Name
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.lastName}
onChange={this.handleLastChange}
id="lastName"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="userName"
>
UserName
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.userName}
onChange={this.handleUserChange}
id="userName"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<label className="col-sm-2 control-label required" htmlFor="role">
Role
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.role}
onChange={this.handleRoleChange}
id="role"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<div className="col-sm-2" />
<div className="col-sm-10">
<button
type="submit"
id="categoriesSubmit"
className="btn-default btn"
>
submit
</button>
</div>
</div>
<div className="form-group">
<div className="col-sm-2" />
<div className="col-sm-10">
<button className="btn btn-danger">
<Link to="/users">Home</Link>
</button>
</div>
</div>
</div>
</form>
);
}
});
export default Form1;
for posting using the fetch API
//./actions/appactions.js
import fetch from "isomorphic-fetch";
export function createCategories(data) {
return fetch("https://localhost:44341/api/categories", {
method: "POST",
mode: "cors",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
}
})
.then(res => {
return res;
})
.catch(err => err);
}
export function createUsers(data) {
return fetch("https://localhost:44341/api/users/create", {
method: "POST",
mode: "cors",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
}
})
.then(res => {
return res;
})
.catch(err => err);
}
export function createBusiness(data) {
return fetch("https://localhost:44341/api/businesslistings/create", {
method: "POST",
mode: "cors",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
}
})
.then(res => {
return res;
})
.catch(err => console.log(err));
}
The issue is that you are rendering the Redirect component along with the rest of your JSX everytime. Rendering only <Redirect to="" /> should solve your problem.
class userspost extends Component {
state = {
redirect: false
};
setRedirect = () => {
this.setState({
redirect: true
});
};
handleSubmit(data) {
console.log("form submission data", data);
createUsers(data);
}
render() {
if( this.state.redirect ){
return <Redirect to="users/" />
}
return (
<div>
{this.renderRedirect()}
<Form1 onSubmit={this.handleSubmit} />
</div>
);
}
}
Also, use only the handleSubmit function in your form onSubmit event. Since adding two functions with && could cause unexpected results. And when everything is ready to redirect, just call your function setRedirect.
There is someone that already answered something similar, so I took a bit of help from there. Check it out:
https://stackoverflow.com/a/43230829/5568741

How can I pass data using <Redirect> in react router v4?

The situation is that I use axios gain data from back-end and I want to redirect from current page to another page as well as passing some data.
How can I pass data when I use <Redirect> to redirect?
I am using code like below, and I can't get 'profile' at the destination page. No matter, this.props or this.state
I understand that using react-router-redux is a better choice.
import React, { Component } from 'react'
import axios from 'axios'
import { Redirect } from 'react-router'
export default class Login extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
emailError: 'Please fill in email',
password: '',
passwordError: 'Please fill in password',
redirect: false,
profile: ''
}
this.handleEmail = (e) => {
var email = e.target.value
var emailError = ''
if (email === null)
emailError = 'Please fill in email'
this.setState({
email: email,
emailError: emailError
})
}
this.handlePassword = (e) => {
var password = e.target.value
var passwordError = ''
if (password === null)
passwordError = 'Please fill in password'
this.setState({
password: password,
passwordError: passwordError
})
}
this.handleSubmit = (e) => {
e.preventDefault()
if (this.state.emailError)
alert(this.state.emailError)
else if (this.state.passwordError)
alert(this.state.passwordError)
else {
axios.post('/user/login', {
email: this.state.email,
password: this.state.password
}).then(response => {
if (response.data !== 'fail') {
this.setState({
redirect: true,
profile: response.data
})
}
})
}
}
}
render() {
const { redirect, profile } = this.state
if (redirect)
return (<Redirect to={{
pathname: '/user/profile',
state: { referrer: this.state.profile }
}} />)
return (
<div className="content user">
<div className="container">
<div className="row">
<div className="col-xs-12">
<h1>Log In Your Tutor Profile</h1>
<form role="form" noValidate>
<div className="row">
<div className="col-xs-12">
<label htmlFor="email">Email</label>
<div className="form-group">
<input id="email" type="text" className="form-control" value={this.state.email} onChange={this.handleEmail} name="email" required/>
</div>
</div>
</div>
<div className="row">
<div className="col-xs-12">
<label htmlFor="password">Password</label>
<div className="form-group">
<input id="password" type="password" className="form-control" value={this.state.password} onChange={this.handlePassword} name="password" required/>
</div>
</div>
</div>
<div className="row">
<div className="col-xs-12">
<div className="form-group">
<button className="btn btn-primary submit" onClick={this.handleSubmit}>LOG IN YOUR PROFILE</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
)
}
}
The way you are passing your state to the Redirect is correct, the only place the problem should be is how you are accessing it. State can be accessed like this.props.location.state. However if you directly route to the path then state won't we available so you need to add a check
Access your state like
this.props.location.state && this.props.location.state.referrer

Resources