Send a PDF File with nodemailer via a html form - html

I have a form in which has an upload file input. I want the user to be able to upload their file and send it via the form. At the moment the PDF file shows attached in the email but doesn't contain any data and won't open etc.
This is what I currently have within the nodemailer options:
let mailOptions = {
from: '"Macwear Clothing" <shop#macwearclothing.com>', // sender address
to: req.body.email, // list of receivers
subject: 'Order Review', // Subject line
text: 'Order Acception', // plain text body
html: output, // html body
attachments: [{'filename': 'needlesheet.pdf', 'content': req.body.needle, 'contentType': 'application/pdf'
}]
};
Client Side index.ejs file
<div class="fileUpload up<%= item.number %>" id="m<%= item.number %>">
<div class="fileUploadContent">
<h2>Customer:
<%= item.email %>
</h2>
<div class="uploadFile">
<input id="needle" type="file" name="needle" value="Upload File >">
</div>
<form method="POST" action="send" name="sendNeedleSheet" enctype="multipart/form-data">
<div class="optionalMessage">
<span>Optional Message:</span>
<textarea class="customTextArea" name="message"></textarea>
<input id="email" name="email" type="hidden" value="<%= item.email %>">
</div>
<div class="modalOptions">
<div class="mButton ok">
<button class="customButton" type="submit">Send</button>
</div>
<div class="mButton cancel">
<span>Cancel</span>
</div>
</div>
</form>
</div>
</div>
app.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const chalk = require('chalk');
const nodemailer = require('nodemailer');
const multer = require('multer');
const app = express();
//View Engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
// Set Static Path
app.use(express.static(path.join(__dirname, '/public')));
// Call JSON
//requestLoop();
// var shopifyAPI = require('shopify-node-api');
// var Shopify = new shopifyAPI({
// shop: 'macwear-clothing-embroidery.myshopify.com', // MYSHOP.myshopify.com
// shopify_api_key: '', // Your API key
// access_token: '' // Your API password
// });
var orderData = null;
// Shopify.get('/admin/orders.json', function(err, data, res, headers){
// app.locals.jsonOrderData = data;
// });
// Shopify.get('/admin/orders/count.json', function(err, data, headers) {
// app.locals.jsonOrderCount = data;
// });
var requestLoop = setInterval(function () {
var request = require("request");
var options_orders = {
method: 'GET',
url: 'https://macwear-clothing-embroidery.myshopify.com/admin/orders.json',
headers: {
'Postman-Token': '',
'Cache-Control': 'no-cache',
Authorization: ''
}
};
var options_order_count = {
method: 'GET',
url: 'https://macwear-clothing-embroidery.myshopify.com/admin/orders/count.json',
headers: {
'Postman-Token': '',
'Cache-Control': 'no-cache',
Authorization: ''
}
};
request(options_orders, function (error, response, body) {
if (error) throw new Error(error);
jsonOrderData = JSON.parse(body);
//console.log(body);
});
request(options_order_count, function (error, response, body) {
if (error) throw new Error(error);
jsonOrderCount = JSON.parse(body);
//console.log(body);
});
}, 60000);
app.get('/shopifycall_order_count', function (req, res) {
res.send(jsonOrderCount);
//res.render('dynamic_content');
});
app.get('/shopifycall_orders', function (req, res) {
res.render('dynamic_content');
});
// Multer File Processing
app.post('/send', (req, res) => {
const output = `
<p>Please View & Accpet or Reject the PDF</p>
`;
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: '',
pass: ''
},
tls:{
rejectUnauthorized:false
}
});
// setup email data with unicode symbols
let mailOptions = {
from: '"Macwear Clothing" <shop#macwearclothing.com>', // sender address
to: req.body.email, // list of receivers
subject: 'Order Review', // Subject line
text: 'Order Acception', // plain text body
html: output, // html body
attachments: [{'filename': 'needlesheet.pdf', 'content': req.body.needle, 'contentType': 'application/pdf'
}]
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
// Preview only available when sending through an Ethereal account
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321#example.com>
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});
console.log(req.body.needle);
});
app.get('/', (req, res) => {
res.render('index');
});
app.listen(3000, () => {
console.log('Starting MOS.......');
console.log(chalk.green('Loaded on port 3000'));
console.log('Fetching API.......');
console.log('Initial API Request will take 60 Seconds');
});

I simply used Multer to handle the uploading of the file. All that was required was to set the multer upload directory.
var upload = multer({dest: './public/uploads/'});
And then within the /send route add in upload.single('needle') and remove the arrow function:
app.post('/send', upload.single('needle'), function (req, res, next) {
});
Then within the attachments in mailOptions:
attachments: [
{
filename: req.file.originalname,
path: req.file.path
}
]
Lastly it is important to set the enctype on the HTML form to multipart/form-data otherwise the file upload via multer will not work.

you using path for both your attachment and static path so the document will not display its extension
try:
app.use(express.static('public'))

Related

404 NOT FOUND react and node js

I'm trying to do a post with a form on react, but when i submit for the name, the browser console always show "404 not found localhost:3000/store-data"
Sometimes it works, but in the database the value "name" is "NULL"
i dont know where is the error. so i need some help.
My db:
CREATE TABLE users(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200)
)ENGINE=INNODB;
My Form.js code:
import React from 'react'
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = { name: '' };
}
handleChange = (event) => {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit = (event) => {
alert('A form was submitted: ' + this.state);
fetch('/store-data', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
// We convert the React state to JSON and send it as the POST body
body: JSON.stringify(this.state)
}).then(function(response) {
console.log(response)
return response.json();
});
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} name="name" onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
export default MyForm;
And my server.js code:
const express = require("express");
const bodyParser = require('body-parser');
const cors = require("cors");
const mysql = require('mysql');
const app = express();
app.use(cors());
// parse application/json
app.use(bodyParser.json());
//create database connection
const conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'conex'
});
//connect to database
conn.connect((err) => {
if (err) throw err;
console.log('Mysql Connected...');
});
//add new user
app.post('/store-data', (req, res) => {
let data = { name: req.body.name };
let sql = "INSERT INTO users SET ?";
let query = conn.query(sql, data, (err, results) => {
if (err) throw err;
res.send(JSON.stringify({ "status": 200, "error": null, "response": results }));
});
});
app.listen(3000, () => {
console.log("Server running successfully on 3000");
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, HEAD');
next();
});
I'm trying to do simple form.

how to upload multiple images from multiple fields from HTML form to node js into two folders then to MongoDB?

I have done the first part correctly (upload the images to their folders), but I can't
upload the images to the DB
form.html
the form to upload the images while the user sign up for a new account
<div>
<label for="image">Upload Image</label>
<input type="file" id="image1" name="image1" value="" >
</div><div>
<label for="image">Upload Image</label>
<input type="file" id="image2" name="image2" value="" >
</div>
multer.js
to save the images in the folders
const path = require('path');
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
if (file.fieldname === 'image1') {
cb(null, './logic/uploads');
}
else if (file.fieldname === 'image2') {
cb(null, './logic/uploadp');
}
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
console.log('New image saved!')
}
});
module.exports = multer({ storage: storage });
route
const express = require('express');
const router = express.Router();
const multer = require('../logic/multer')
const { userSignup, userLogin } = require('../logic/Membership_Application');
router.post('/Register',
multer.fields([
{ name: 'image1', maxCount: 1 },
{ name: 'image2', maxCount: 1 },
]),
userSignup
);
router.post('/login', userLogin);
module.exports = router;
logic (data insertion)
const UsersSchema = await new jcs({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
password: hashedPassword,
nationality: req.body.nationality,
//here is the error(it was working with multer.singel but not with multer,fields)
img: {
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
contentType: 'image/png'
},
img2: {
data: fs.readFileSync(path.join(__dirname + '/uploadp/' + req.file.filename)),
contentType: 'image/png'
}
}).save();
model(Database schema)
const db = require('mongoose');
//Database Creation
const UsersSchema = new db.Schema
({
name: { type: String },
email: { type: String },
phone: { type: String },
password: { type: String },
nationality: { type: String },
img:
{
data: Buffer,
contentType: String,
},
img2:
{
data: Buffer,
contentType: String,
},
})
var Users = db.model("Users", UsersSchema);
module.exports = Users;
app.js
const express = require('express');
const app = express();
require('dotenv/config');
const MembershipApplicationRouter = require('./route/Membership_Application');
const AdminRouter = require('./route/admin')
var bodyParser = require('body-parser');
const cors = require('cors');
const db = require('mongoose');
db.connect('mongodb-link',
{
useNewUrlParser: true,
useUnifiedTopology: true
});
const connection = db.connection;
connection.on('connected', () => { console.log("conected with cloud") });
connection.on('error', () => { console.log("error with database") });
app.use('/admin', AdminRouter);
app.use([
bodyParser.urlencoded({ extended: true }),
express.json(),
express.urlencoded({ extended: true })]);
app.use(cors());
app.use('/membershipApplication', MembershipApplicationRouter);
var port = process.env.PORT || 8080;
app.listen(port, () => {
console.log("Server Up and running");
})
module.exports = app;
I have this error msg
New image saved!
New image saved!
C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
^
TypeError: Cannot read properties of undefined (reading 'filename')
at userSignup (C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79:84)
[nodemon] app crashed - waiting for file changes before starting...
The best practice is to store the file’s location in your server to mongoDB.
So that whenever you to access the file you fetch it’s location then return it back!!

nodemailer-express-handlebars | Error: ENOENT: no such file or directory for template !! node.js

I am trying to send a template form node js using nodemailer and express-handlebars but I'm getting the error no such file I have no idea what I'm missing
I'm attaching my index.js down
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const hb = require('nodemailer-express-handlebars')
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
const path = require('path');
// These id's and secrets should come from .env file.
const CLIENT_ID = 'the id';
const CLEINT_SECRET = 'the secret';
const REDIRECT_URI = 'uri';
const REFRESH_TOKEN = 'the token';
const oAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLEINT_SECRET,
REDIRECT_URI
);
oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
app.post("/api", async (req,res) => {
try{
const accessToken = await oAuth2Client.getAccessToken();
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: 'your [enter image description here][1]emial',
clientId: CLIENT_ID,
clientSecret: CLEINT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken,
},
})
const handlebarOptions = {
viewEngine: {
extName: ".handlebars",
partialsDir: path.resolve(__dirname, "emialTemplate"),
defaultLayout: false,
},
viewPath: path.resolve(__dirname, "emialTemplate"),
extName: ".handlebars",
};
transport.use(
"compile",
hb(handlebarOptions)
);
// the data which we going to send
const mailOptions = {
from: req.body.name + '<ummed.gagrana#gmail.com>',
to: 'ummed.gagrana#gmail.com',
subject: req.body.subject,
text: "From:" + req.body.email + "\n Message:" + req.body.message,
// html: '<h2>From:</h2>'+'<h4>'+req.body.email+"</h4> <br>"+"<h2>Message:</h2>"+'<h4>'+req.body.message+"</h4>",
template: 'comeBack'
};
//sending mail
const result = await transport.sendMail(mailOptions);
// checking the result after sending mail
console.log(result)
res.send({hey:"well done you just paased some data"})
} catch (error) {
console.log(error)
}
})
app.listen(3000, () => {
console.log("server up and running on port 3000")
})
This the code I am not sure what I'm missing I'm a beginner in nodejs so please help
I am attaching my work directory path for help
[]
You got a typo. emialTemplate --> emailTemplate
const handlebarOptions = {
viewEngine: {
extName: ".handlebars",
partialsDir: path.resolve(__dirname, "emailTemplate"),
defaultLayout: false,
},
viewPath: path.resolve(__dirname, "emailTemplate"),
extName: ".handlebars",
};
After that, I would return the following code line to tell the server that the code has been processed as it should have.
return res.send({hey:"well done you just paased some data"})

Using multer with nodejs

I am trying to upload a file from my page to node server.
I can see form data are arriving in the router on server.
But no file is saved in upload folder.
What am I doing wrong?
//router unit
const express = require('express');
const router = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log('chegei')
cb(null, "uploads/")
},
filename: (req, file, cb) => {
console.log('chegei2')
cb(null, Date.now() + "-" + file.ogirinalname)
},
});
module.exports = function (page) {
router.post('/SendMsgBase64', async (req, res) => {
var upload = multer({ storage: storage }).single('userFile');
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.send({ "data": "Error uploading file." });
}
return res.send({ "data": "File is uploaded" });
});
return router
}
//app.js unit
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const WARoutes = require('../routes/WARoutes');
const path = require('path');
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {
res.sendFile('/index.html');
})
app.use('/whats', WARoutes(this.page));
//html
<form id="uploadForm">
<input type="file" name="userFile" />
<input type="button" value="Upload Image" onclick="uploadFile();">
<span id="status"></span>
</form>
<script>
uploadFile = () => {
var formData = new FormData();
debugger
var logoImg = $('input[name="userFile"]').get(0).files[0];
formData.append('logo', logoImg);
var objArr = [];
objArr.push({ "id": "123", "name": "luiz" });
//JSON obj
formData.append('objArr', JSON.stringify(objArr));
$.ajax({
url: "/whats/SendMsgBase64",
type: "POST",
processData: false,
contentType: "application/x-www-form-urlencoded",
data: formData,
complete: function (data) {
alert("success");
}
})
};
</script>
According to multer's github page, if you have not created the uploads directory, it may go something wrong.
If this is the case, creating the directory on your own or passing a string value to destination property is the solution for you.
https://github.com/expressjs/multer
Note: You are responsible for creating the directory when providing destination as a function. When passing a string, multer will make sure that the directory is created for you.

Sending HTML template through mail using node js node mailer

I had written node mailer code from w3schools. I want to send the html template designed (index.html in my case). Below is the code. please help me how can i send html template to the mail using node js.
var nodemailer = require('nodemailer');
var data = require('index.html');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'youremail#gmail.com',
pass: 'yourpassword'
}
});
var mailOptions = {
from: 'youremail#gmail.com',
to: 'myfriend#yahoo.com',
subject: 'Sending Email using Node.js',
html: 'data'
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
This is the right way of passing html in the nodemailer
var nodemailer = require('nodemailer');
var fs = require('fs');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'youremail#gmail.com',
pass: 'yourpassword'
}
});
fs.readFile('index.html', {encoding: 'utf-8'}, function (err, html) {
if (err) {
console.log(err);
} else {
var mailOptions = {
from: 'youremail#gmail.com',
to: 'myfriend#yahoo.com',
subject: 'Sending Email using Node.js',
html: html
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
}
});
Index.html file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Node js Email </title>
<link rel="stylesheet" href="">
</head>
<body>
<div class="container"><br />
<h1>Send Email</h1><br />
<form onsubmit="sentthis()" method="post">
<div class="divi">
<label for="to"></label>To:</label>
<input type="email" class="too" name="to">
</div>
<div class="divi">
<label for="subject">Subject:</label>
<input type="text" class="subjectt" name="subject">
</div>
<div class="divi">
<p>Body:</p>
<textarea cols="" rows="5"class="textarea" name="body"></textarea>
</div>
<div class="divi">
<button type="submit" class="btn">Send</button>
</div>
</form>
</div>
</body>
</html>
server.js file
var express = require('express'),
path = require('path'),
nodeMailer = require('nodemailer'),
bodyParser = require('body-parser');
var app = express();
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(express.static('public'));
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
var port = 3000;
app.get('/', function (req, res) {
res.render('index.html');
});
app.post('/sent',function(req,res){
let transporter = nodeMailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: 'marcus251#gmail.com',
pass: 'yourpassword'
}
});
let mailOptions = {
from: '"Marcus coffee" <marcus251#gmail.com>',
to: "Receiver Name <receiver#email.com>",
subject: req.body.subject,
text: req.body.body,
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: ', info.messageId, info.response);
res.render('index.html');
});
});
app.listen(port, function(){
console.log('Server is running at port: ',port);
});
This will solve your problem.