Email api using react node nodemailer express is not working - javascript

I am trying to create an contact page using ReactJs NodeJs express and nodemail. I am not getting any error. But it's not working. The post request is not working so i guess there's something wrong with the axios function but it could be anywhere else too so.Is the error in the backend part or the frontend part How do i fix it?
Post Log saying
Proxy error: Could not proxy request /api/forma from localhost:3000 to localhost:3001 (ECONNRESET)
Client side
import React,{useState} from 'react'
import axios from 'axios';
const Form = () => {
const [name,setName] = useState("");
const [email,setEmail] = useState("");
const [message,setMessage] = useState("");
const [sent,setSent] = useState(false);
const formSubmit=(e)=> {
e.preventDefault();
let data = {
name:name,
email:email,
message:message
}
axios.post('/api/forma',data)
.then(res => {
setSent(true);
},resetForm())
.catch(() => {
console.log("message not sent");
})
}
const resetForm = () => {
setName("");
setEmail("");
setMessage("");
setTimeout(()=> {
setSent(false);
},3000)
}
return (
<div className="container">
<form onSubmit={formSubmit}>
<div className="single">
<label>Name</label>
<input type="text" name="name" className="name" placeholder="Enter your name"
value={name}
onChange={e => setName(e.target.value)}
/>
</div>
<div className="single">
<label>Email</label>
<input type="text" name="email" className="email" placeholder="Enter your email"
value={email}
onChange={e => setEmail(e.target.value)}/>
</div>
<div className="textarea">
<label>Message</label>
<textarea name="message" id="" cols ="30" rows="5" placeholder="Enter your message here"
value={message}
onChange={e => setMessage(e.target.value)}></textarea>
</div>
<div className={sent?'msg msgAppear':'msg'}>
Message has been sent
</div>
<div>
<button type="submit">submit</button>
</div>
</form>
</div>
)
}
export default Form
Server side
const express = require('express');
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer')
const cors = require('cors')
const app = express();
app.use(bodyParser.json);
app.use(bodyParser.urlencoded({extended:true}));
app.use(cors());
app.get('/',()=>{
resizeBy.send("Welcome")
});
app.post('/api/forma',(req,res) => {
let data = req.body
let smtptransport = nodemailer.createTransport({
service:'Gmail',
port:465,
auth:{
user:'yourEmail#gmail.com',
pass: "secreate"
}
});
let mailOptions = {
from:data.email,
to:'yourEmail#gmail.com',
subject:`Message from ${data.name}`,
html:`
<h3>Informations<h3>
<ul>
<li>Name: ${data.name}</li>
<li>Name: ${data.email}</li>
</ul>
<h3>Message<h3>
<p>${data.message}</p>
`
}
smtptransport.sendMail(mailOptions,(error,response) => {
if(error){
res.send(error)
}
else{
res.send('Success')
}
})
smtptransport.close();
})
const PORT = process.env.PORT || 3001;
app.listen(PORT,() => {
console.log(`Server starting at port ${PORT}`);
})

One way to solve this using gmail is creating a transporter.
Here is the working code:
mail.service.js
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: '<myuser>#gmail.com',
pass: '<mypassword>'
},
logger: false, // log to console
debug: false // include SMTP traffic in the logs
});
exports.sendEmail = function(req, res) {
const mailOptions = {
from: '<myuser>#gmail.com',
subject: 'My custom title ',
text: 'Mensagem de: ' + req.body.nome + ', email: [' + req.body.email + '] ' + req.body.mensagem,
to: req.body.email
}
transporter.sendMail(mailOptions).then((trans) => {
res.status(200);
res.json(trans);
res.end();
}).catch((error) => {
res.status(500);
res.json(error);
res.end();
});
}
Here is my router for sendemail action:
const router = require('express').Router();
const emailService = require('../services/mail.service.js');
router.post('/sendmail', emailService.sendEmail);
module.exports = router;
If you are in some situation of 403 errors you might need to do this configurations steps provided by nodemailer (this configuration is in gmail account) .

Related

Send Data from React JS Form to Back Express

I created a react, express app and then created a simple form in React app that accepts name and age and on submit the form data is supposed to go to backend express app and console log there but I can not access the form input data in my backend express.On submit I get this {"message":"Hello World"} logged in my console of react page.
//express app.js
const express = require('express');
const cors = require('cors');
const app = express()
app.use(cors())
app.use(express.urlencoded())
app.use(express.json())
app.use("/",(req,res)=>{
res.json({ message: "Hello World" });
})
app.post('/', (req, res) => {
const { fullname, age } = req.body;
console.log(fullname, age);
res.send('Form submitted successfully');
});
app.listen(5000,()=>{console.log("http://localhost:5000");})
My login react app:
import React from "react";
export default function App(){
function submitHandler(e){
e.preventDefault();
const fullname = e.target.elements.fullname.value;
const age = e.target.elements.age.value;
fetch('http://localhost:5000/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ fullname, age })
})
.then(response => response.text())
.then(data => {
console.log(data);
});
}
return (
<div className="App">
<form onSubmit={submitHandler}>
<input type="text" name="fullname" id="" placeholder="Name:" />
<input type="number" name="age" id="" placeholder="age" />
<input type="submit" value="Submit" />
</form>
</div>
);
}
Help me get the form input data in express app so that I can later store it in mongodb
You must replace app.use with app.get
app.get("/",(req,res)=>{
res.json({ message: "Hello World" });
})
see documentation of app.use

curl works from within the private network, but Axios requests not working on browser

I have a Red Hat Enterpise Linux 9 server hosted at a data center, which has an Apache web server and a MySQL installation. MySQL listens on 3306, and Apache on 80 (defaults).
I'm new to React and Express, and I'm testing a client-server app. I built the client side with create-react-app, and this is the code for App.js
App.js
import "./App.css";
import { useState } from "react";
import Axios from "axios";
function App() {
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const [country, setCountry] = useState("");
const [position, setPosition] = useState("");
const [wage, setWage] = useState(0);
const [newWage, setNewWage] = useState(0);
const [employeeList, setEmployeeList] = useState([]);
const addEmployee = () => {
Axios.post("http://1.2.3.4:3001/create", {
name: name,
age: age,
country: country,
position: position,
wage: wage,
}).then(() => {
setEmployeeList([
...employeeList,
{
name: name,
age: age,
country: country,
position: position,
wage: wage,
},
]);
});
};
const getEmployees = () => {
Axios.get("http://1.2.3.4:3001/employees").then((response) => {
setEmployeeList(response.data);
console.log("retrieving the list");
console.log(employeeList);
});
};
getEmployees();
const updateEmployeeWage = (id) => {
Axios.put("http://1.2.3.4:3001/update", { wage: newWage, id: id }).then(
(response) => {
setEmployeeList(
employeeList.map((val) => {
return val.id == id
? {
id: val.id,
name: val.name,
country: val.country,
age: val.age,
position: val.position,
wage: newWage,
}
: val;
})
);
}
);
};
const deleteEmployee = (id) => {
Axios.delete(`http://1.2.3.4:3001/delete/${id}`).then((response) => {
setEmployeeList(
employeeList.filter((val) => {
return val.id != id;
})
);
});
};
return (
<div className="App">
<div className="information">
<label>Name:</label>
<input
type="text"
onChange={(event) => {
setName(event.target.value);
}}
/>
<label>Age:</label>
<input
type="number"
onChange={(event) => {
setAge(event.target.value);
}}
/>
<label>Country:</label>
<input
type="text"
onChange={(event) => {
setCountry(event.target.value);
}}
/>
<label>Position:</label>
<input
type="text"
onChange={(event) => {
setPosition(event.target.value);
}}
/>
<label>Wage (year):</label>
<input
type="number"
onChange={(event) => {
setWage(event.target.value);
}}
/>
<button onClick={addEmployee}>Add Employee</button>
</div>
<div className="employees">
<button onClick={getEmployees}>Show Employees</button>
{employeeList.map((val, key) => {
return (
<div className="employee">
<div>
<h3>Name: {val.name}</h3>
<h3>Age: {val.age}</h3>
<h3>Country: {val.country}</h3>
<h3>Position: {val.position}</h3>
<h3>Wage: {val.wage}</h3>
</div>
<div>
<input
type="text"
placeholder="2000..."
onChange={(event) => {
setNewWage(event.target.value);
}}
/>
<button
onClick={() => {
updateEmployeeWage(val.id);
}}
>
{" "}
Update
</button>
<button
onClick={() => {
deleteEmployee(val.id);
}}
>
Delete
</button>
</div>
</div>
);
})}
</div>
</div>
);
}
export default App;
The server is supposed to run on port 3001 of the same machine. The code for the server's index.js is below.
index.js for server
const express = require("express");
const app = express();
const mysql = require("mysql");
const cors = require("cors");
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(cors());
app.use(express.json());
const db = mysql.createConnection({
user: "apphost",
host: "0.0.0.0",
password: "password",
database: "employeeSystem",
insecureAuth: 'true'
});
app.get('/home', (req, res) => {
res.send("HELLO THERE\n");
});
app.post("/create", (req, res) => {
const name = req.body.name;
const age = req.body.age;
const country = req.body.country;
const position = req.body.position;
const wage = req.body.wage;
db.query(
"INSERT INTO employees (name, age, country, position, wage) VALUES (?,?,?,?,?)",
[name, age, country, position, wage],
(err, result) => {
if (err) {
console.log(err);
} else {
res.send("Values Inserted");
}
}
);
});
app.get("/employees", (req, res) => {
db.query("SELECT * FROM employees", (err, result) => {
if (err) {
console.log('server index.js problem')
console.log(err);
} else {
res.send(result);
}
});
});
app.put("/update", (req, res) => {
const id = req.body.id;
const wage = req.body.wage;
db.query(
"UPDATE employees SET wage = ? WHERE id = ?",
[wage, id],
(err, result) => {
if (err) {
console.log(err);
} else {
res.send(result);
}
}
);
});
app.delete("/delete/:id", (req, res) => {
const id = req.params.id;
db.query("DELETE FROM employees WHERE id = ?", id, (err, result) => {
if (err) {
console.log(err);
} else {
res.send(result);
}
});
});
app.listen(3001, () => {
console.log("Server running on port 3001.");
});
After running the server with node index.js, when I run curl http://1.2.3.4:3001/employees from a machine on the same physical network, I get a JSON output of the data in the MySQL database as expected. From my Windows CMD, a browser on my Windows machine, or from my phone, the request times out.
Keep in mind that I'm SSH-ing to the linux VM, while on a VPN provided by the data center.
This is the error I get on chrome:
Uncaught (in promise) M {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
Not sure what the issue is. Tried a lot of solutions from all over the internet, but nothing seems to work.
If any more information is needed, feel free to ask. I'll do anything to get this issue fixed and understand what I'm doing wrong.
Thanks in advance!

Using ReactJS, Nodemailer, and Cors and I keep getting Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

I've tried just about everything and just can't figure it out. I know the backend is working fine because I got an email but I cannot figure out why it is not working in the frontend. I am new to this so it may be something simple, I appreciate any and all help! Here is my server.js
const express = require("express");
const nodemailer = require("nodemailer")
const app = express()
require("dotenv").config();
const cors = require('cors');
//middleware
app.use(express.json());
app.use(cors());
let transporter = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: process.env.EMAIL,
pass: process.env.WORD,
clientId: process.env.OAUTH_CLIENTID,
clientSecret: process.env.OAUTH_CLIENT_SECRET,
refreshToken: process.env.OAUTH_REFRESH_TOKEN,
},
});
transporter.verify((err, success) => {
err
? console.log(err)
: console.log(`=== Server is ready to take messages: ${success} ===`)
})
app.post("/loya-granite", function (req, res) {
let mailOptions = {
from: `${req.body.mailState.email}`,
to: process.env.EMAIL,
subject: `Message from: ${req.body.mailState.email}`,
text: `${req.body.mailState.message}`,
};
transporter.sendMail(mailOptions, function (err, data) {
if (err) {
res.json({
status: "Fail",
})
} else {
console.log("Email Sent!");
res.json({ status: "Email Sent!" });
}
});
});
const port = process.env.PORT || 3001;
app.listen(port, () => {
console.log(`Server is running on port: ${port}`)
})
and here is my contact.js
import React, { useState } from 'react'
import './Contact.css'
function Contact(props) {
const [mailState, setMailState] = useState({
name: "",
email: "",
phone: "",
message: "",
});
function handleStateChange(e) {
setMailState((prevState) => ({
...prevState,
[e.target.name]: e.target.value,
}));
}
const submitEmail = async (e) => {
// console.log('Email being submitted')
e.preventDefault();
// console.log('prevent default worked')
console.log({ mailState });
await fetch("http://localhost:3000/", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ mailState }),
})
.then((res) => res.json())
.then(async (res) => {
const resData = await res;
console.log(resData);
if (resData.status === "success") {
alert("Message Sent!");
} else if (resData.status === "fail") {
alert("Message failed to send")
}
})
.then(() => {
setMailState({
email: "",
name: "",
phone: "",
message: "",
});
});
};
return (
<div className='contactContain'>
{/* creating contact form */}
<form id='form' className='form' onSubmit={submitEmail}>
<h3 className='formTitle'>Let's talk about your project</h3>
<input placeholder='Name' id='name' name="name" onChange={handleStateChange} value={mailState.name} />
<input placeholder='Email' id='email' name="email" onChange={handleStateChange} value={mailState.email} />
<input placeholder='Phone Number' id='phone' name="phone" onChange={handleStateChange} value={mailState.phone} />
<textarea placeholder='Message' id='message' name="message" onChange={handleStateChange} value={mailState.message} />
<button id='submit' type='submit'>Send</button>
</form>
<section className='contactInfo'>
<h3>Contact Info</h3>
<p>Phone: (661) 466-3286</p>
<p>Email: dieguito.loyagranite19#gmail.com</p>
</section>
<section className='loyaHours'>
<h3>Hours of Operation</h3>
<p>Monday-Friday: 9am- 5pm</p>
<p>Saturday: Closed</p>
<p>Sunday: Closed</p>
</section>
</div>
)
}
export default Contact
``

express js server dosn't allow post from deployed app

I have problem with the server when deploy my app with gh-pages. When i try to POST on /contact url it respond 405 Method Not Allowed.
I tried with cors on express but it's same. My client side is with React.
When I run it on localhost everything work normal but in production like server doesn't exist. Should I add something in my react app to connect them or...?
const express = require('express');
const bodyParser = require('body-parser');
const http = require('http');
const path = require('path')
const nodemailer = require('nodemailer');
const cors = require('cors')
const pass = require('./.vscode/settings.json')
const config = require('./config')
var allowedOrigins = ['http://localhost:3000','https://some.github.io'];
const corsOptions = {
origin: function(origin, callback){
if(!origin) return callback(null, true);
if(allowedOrigins.indexOf(origin) === -1){
var msg = 'The CORS policy for this site does not ' +
'allow access from the specified Origin.';
return callback(new Error(msg), false);
}
return callback(null, true);
},
credentials: true,
}
const app = express();
const route = express.Router();
app.use(express.static(path.join(__dirname, 'client' ,'/public')))
app.use(cors(corsOptions))
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'https://some.github.io');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', route)
http.createServer(app).listen(config.port, () => {
console.log(`Listening on port ${config.port}`)
});
app.get('/', (req, res) => {
console.log('server')
res.sendFile(path.join(__dirname, 'client' ,'/public', 'index.html'));
});
const transporter = nodemailer.createTransport({
port: 465,
host: "smtp.gmail.com",
auth: {
user: 'email',
pass: pass,
},
secure: true,
});
route.get('/contact', (req,res) => {
res.status(200).send('Contact page')
})
route.post('/contact', (req, res) => {
const {name, email, message} = req.body
console.log(req.body)
const mailToMe = {
from: 'email', // sender address
to: 'email', // list of receivers
subject: name,
text: message,
html: message + `<br> From: ${email}`,
};
transporter.sendMail(mailToMe, (error, info) => {
if(error) {
return console.log(error)
}
res.redirect('/contact')
res.status(200)
});
})
That is the client side component in react:
const ContactForm = () => {
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [message, setMessage] = useState('')
const [errorName, setErrorName] = useState('')
const [errorEmail, setErrorEmail] = useState('')
const [errorMessage, setErrorMessage] = useState('')
const [isSubmited, setIsSubmited] = useState(false)
useEffect(() => {
if(isSubmited){
setTimeout(() => {
setIsSubmited(false)
}, 7000)
}
})
const handelValidation = () => {
setErrorName('')
setErrorEmail('')
setErrorMessage('')
// Name
if (!name) {
setErrorName("Name field cannot be empty!")
return false
}
if (!name.match(/[A-Z][a-z]+ [A-Z][a-z]+/)) {
setErrorName("Тhe first and second names must begin with a capital letter and continue with lowercase letters!")
return false
}
// Email
if (email === '') {
setErrorEmail("Email field cannot be empty!")
return false
}
if (!email.match(/[A-Za-z0-9.]+#[a-z]+.[a-z]+.?[a-z]+/)) {
setErrorEmail("Email must be valid!")
return false
}
// Message
if (message === '') {
setErrorMessage("Message field cannot be empty!")
return false
}
if(message.length <= 10) {
setErrorMessage("Message should more the 10 characters!")
return false
}
return true
}
const handleSubmit = (e) => {
e.preventDefault()
let result = handelValidation();
console.log(name, email, message)
if (!result) {
return
}
let data = { name: name, email: email, message: message }
axios.post(`/contact`, data).catch(e => console.log(e))
setName('')
setEmail('')
setMessage('')
setIsSubmited(true)
}
return (
<Form onSubmit={handleSubmit}>
<Input
onChange={e => setName(e.target.value)}
label={"What is your name?"}
name={"name"}
icon={"far fa-user"}
placeholder={"Type your first and second name..."}
value={name}
isError={errorName}
/>
{errorName ? <Notification error={errorName} /> : ""}
<Input
onChange={e => setEmail(e.target.value)}
label={"Write your email"}
name={"email"}
icon={"far fa-envelope"}
placeholder={"Type your email..."}
value={email}
isError={errorEmail}
/>
{errorEmail ? <Notification error={errorEmail} /> : ""}
<Input
onChange={e => setMessage(e.target.value)}
label={"What is your message to me?"}
name={"message"}
icon={"far fa-comment-alt"}
placeholder={"Type your message..."}
value={message}
isError={errorMessage}
/>
{errorMessage ? <Notification error={errorMessage} /> : ""}
<SubmitButton title={"Submit form"} />
{isSubmited ? <Div>Thank you for contacting me! You must have received an automatic reply
to the email you entered above.</Div> : ""}
</Form>
)
}
Github Pages does not support any kind of server-side programming.
You need hosting (there are many cloud services that will let you deploy a Node.js web service to them as well as VPSs and dedicated servers you can rent) on which you can run your server-side JavaScript. You can't just drop it onto Github pages and have it do anything.
You need to deploy public server instead of local server. Local servers are accessible for only you, not the others.

How do I send an image attachment via an Email form with Nodemailer?

I am new to coding backend stuff. What I am trying to do is have a customer fill out an email form, upload an attachment with a preview and send said image as an attachment to my email so I can set up the image to use for the site. Everything is being setup in React and Node.js. I can send the email form; I can even send an attachment with the email. The problem is the attachment is empty. I try to open the attachment in a new tab and it hangs and does nothing. If I try to download the attachment, it hangs and then says server error.
I have been scouring the internet, trying so many various things for days trying to get this thing to work. Watching tutorials, looking at other questions and suggestions, going through blog posts and nothing seems to work. I know there is a way to do this, but I have no idea what. I haven't found anything that works. Can please someone enlighten me on what I am doing wrong and how to actually get an image attachment to send? I have left my code here so people can review it. Thank you.
FRONT END
import React, { Component } from "react";
import axios from "axios";
class App extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
message: "",
file: null,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleFileChange = this.handleFileChange.bind(this);
this.handleReset = this.handleReset.bind(this);
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
handleFileChange = (e) => {
const [file] = e.target.files;
if (file) {
this.setState({
file: URL.createObjectURL(e.target.files[0]),
});
console.log(file);
}
};
handleReset = (e) => {
this.setState({
[e.target.name]: "",
[e.target.email]: "",
[e.target.message]: "",
[e.target.file]: null,
});
};
async handleSubmit(e) {
e.preventDefault();
const { name, email, message, file } = this.state;
const form = await axios.post("/api/form", {
name,
email,
message,
file,
});
if (file) {
this.setState({
file: URL.revokeObjectURL(e.target.files[0]),
});
}
}
render() {
return (
<form
onSubmit={this.handleSubmit}
style={{ width: "200px", padding: "20px" }}
>
<label htmlFor="name">Name:</label>
<input type="text" name="name" onChange={this.handleChange} />
<label htmlFor="email">Email:</label>
<input type="email" name="email" onChange={this.handleChange} />
<label htmlFor="message">Message:</label>
<input type="textarea" name="message" onChange={this.handleChange} />
<label htmlFor="file">File:</label>
<input
type="file"
name="file"
accept="image/jpeg, jpg"
onChange={this.handleFileChange}
multiple={false}
/>
<img src={this.state.file} alt="img" />
<input type="submit" />
</form>
);
}
}
export default App;
BACKEND
const express = require("express");
const bodyParser = require("body-parser");
const nodemailer = require("nodemailer");
const app = express();
const cors = require("cors");
const fs = require("fs");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors());
app.post("/api/form", (req, res) => {
nodemailer.createTestAccount((err, account) => {
const htmlEmail = `
<h3>Contact Details</h3>
<ul>
<li>
Name: ${req.body.name}
</li>
<li>
Email: ${req.body.email}
</li>
</ul>
<h3>Message</h3>
<p>${req.body.message}</p>
`;
let transporter = nodemailer.createTransport({
host: "********",
port: ***,
auth: {
user: "********",
pass: "********",
},
});
let mailOptions = {
from: "test#test.com",
to: "testReceive#test.com",
replyTo: "test#test.com",
subject: "Test Message",
text: req.body.message,
html: htmlEmail,
attachments: [
{
filename: "AdvertImage.jpg",
content: req.body.file,
contentType: "image/jpg",
},
],
};
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return console.log(err);
}
console.log("Message sent: %s", info.message);
console.log("Message URL: %s", nodemailer.getTestMessageUrl(info));
});
});
});
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
Thank you!

Categories

Resources