Send dynamic zip files using nodemailer [duplicate] - javascript

I have code that send email with nodemailer in nodejs but I want to attach file to an email but I can't find way to do that I search on net but I could't find something useful.Is there any way that I can attach files to with that or any resource that can help me to attach file with nodemailer?
var nodemailer = require('nodemailer');
var events = require('events');
var check =1;
var events = new events.EventEmitter();
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "gmail",
auth: {
user: "example#gmail.com",
pass: "pass"
}
});
function inputmail(){
///////Email
const from = 'example<example#gmail.com>';
const to = 'example#yahoo.com';
const subject = 'example';
const text = 'example email';
const html = '<b>example email</b>';
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html
}
return mailOption;
}
function send(){
smtpTransport.sendMail(inputmail(),function(err,success){
if(err){
events.emit('error', err);
}
if(success){
events.emit('success', success);
}
});
}
///////////////////////////////////
send();
events.on("error", function(err){
console.log("Mail not send");
if(check<10)
send();
check++;
});
events.on("success", function(success){
console.log("Mail send");
});

Include in the var mailOption the key attachments, as follow:
var mailOptions = {
...
attachments: [
{ // utf-8 string as an attachment
filename: 'text1.txt',
content: 'hello world!'
},
{ // binary buffer as an attachment
filename: 'text2.txt',
content: new Buffer('hello world!','utf-8')
},
{ // file on disk as an attachment
filename: 'text3.txt',
path: '/path/to/file.txt' // stream this file
},
{ // filename and content type is derived from path
path: '/path/to/file.txt'
},
{ // stream as an attachment
filename: 'text4.txt',
content: fs.createReadStream('file.txt')
},
{ // define custom content type for the attachment
filename: 'text.bin',
content: 'hello world!',
contentType: 'text/plain'
},
{ // use URL as an attachment
filename: 'license.txt',
path: 'https://raw.github.com/andris9/Nodemailer/master/LICENSE'
},
{ // encoded string as an attachment
filename: 'text1.txt',
content: 'aGVsbG8gd29ybGQh',
encoding: 'base64'
},
{ // data uri as an attachment
path: 'data:text/plain;base64,aGVsbG8gd29ybGQ='
}
]}
Choose the option that adjust to your needs.
Link:Nodemailer Repository GitHub
Good Luck!!

Your code is almost right, just need to add, "attachments" property for attaching the files in your mail,
YOUR mailOption:
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html
}
Just add attachments like
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html,
attachments: [{
filename: change with filename,
path: change with file path
}]
}
attachments also provide some other way to attach file for more information check nodemailer community's documentation HERE

If you are passing options object in mail composer constructor and attachment is on http server then it should look like:
const options = {
attachments = [
{ // use URL as an attachment
filename: 'xxx.jpg',
path: 'http:something.com/xxx.jpg'
}
]
}

var express = require('express');
var router = express(),
multer = require('multer'),
upload = multer(),
fs = require('fs'),
path = require('path');
nodemailer = require('nodemailer'),
directory = path.dirname("");
var parent = path.resolve(directory, '..');
// your path to store the files
var uploaddir = parent + (path.sep) + 'emailprj' + (path.sep) + 'public' + (path.sep) + 'images' + (path.sep);
/* GET home page. */
router.get('/', function(req, res) {
res.render('index.ejs', {
title: 'Express'
});
});
router.post('/sendemail', upload.any(), function(req, res) {
var file = req.files;
console.log(file[0].originalname)
fs.writeFile(uploaddir + file[0].originalname, file[0].buffer, function(err) {
//console.log("filewrited")
//console.log(err)
})
var filepath = path.join(uploaddir, file[0].originalname);
console.log(filepath)
//return false;
nodemailer.mail({
from: "yourgmail.com",
to: req.body.emailId, // list of receivers
subject: req.body.subject + " ✔", // Subject line
html: "<b>" + req.body.description + "</b>", // html body
attachments: [{
filename: file[0].originalname,
streamSource: fs.createReadStream(filepath)
}]
});
res.send("Email has been sent successfully");
})
module.exports = router;

attachments: [
{
filename: "inovices_1.pdf", // the file name
path: "https://*************************/invoice/10_9_RMKUns.pdf",// link your file
contentType: "application/pdf", //type of file
},
{
filename: "inovices_2.pdf",
path: "https://**************************/invoice/10_9_RMKUns.pdf",
contentType: "application/pdf",
},
];
var nodemailer = require("nodemailer");
var all_transporter = nodemailer.createTransport({
host: process.env.MAIL_SERVICE,
port: 587,
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS,
},
maxConnections: 3,
pool: true,
});
exports.send_email = function (email, subject, html, extra_cc = [], attachments = []) {
return new Promise(async (resolve, reject) => {
var mailOptions = {
from: process.env.MAIL_FROM_ADDRESS,
to: email,
subject: subject,
html: html,
cc: [],
};
mailOptions["cc"] = mailOptions["cc"].concat(extra_cc);
if (attachments.length > 0) mailOptions["attachments"] = attachments;
all_transporter.sendMail(mailOptions, function (error, info) {
// console.log(error);
// console.log(info);
if (error) {
resolve({ failed: true, err: error });
} else {
resolve({ failed: false, data: info.response });
}
});
});
};

The alternative solution is to host your images online using a CDN and link to the online image source in your HTML, eg. <img src="list_image_url_here">.
(I had problems with nodemailer's image embedding using nodemailer version 2.6.0, which is why I figured out this workaround.)
An added benefit of this solution is that you're sending no attachments to nodemailer, so the sending process is more streamlined.

var mailer = require('nodemailer');
mailer.SMTP = {
host: 'host.com',
port:587,
use_authentication: true,
user: 'you#example.com',
pass: 'xxxxxx'
};
Then read a file and send an email :
fs.readFile("./attachment.txt", function (err, data) {
mailer.send_mail({
sender: 'sender#sender.com',
to: 'dest#dest.com',
subject: 'Attachment!',
body: 'mail content...',
attachments: [{'filename': 'attachment.txt', 'content': data}]
}), function(err, success) {
if (err) {
// Handle error
}
}
});

Just look at here. Nodemailer > Message configuration > Attachments
The code snippet is below (pdfkit gets the stream):
// in async func
pdf.end();
const stream = pdf;
const attachments = [{ filename: 'fromFile.pdf', path: './output.pdf',
contentType: 'application/pdf' }, { filename: 'fromStream.pdf', content: stream, contentType: 'application/pdf' }];
await sendMail('"Sender" <sender#test.com>', 'reciver#test.com', 'Test Send Files', '<h1>Hello</h1>', attachments);
Stream uses content not streamSource This bothered me before, share with everyone :)

Reference = https://nodemailer.com/message/attachments/
var mailOption = {
from: from,
to: to,
subject: subject,
text: text,
html: html,
attachments: [
{
filename: filename,
path: filePath
},
]
}

Related

How to add image in my email, nodemailer and handlebars?

I am using nodemailer along with handlebars in my node project. The email is working fine but I am not able to attach image in the html template created by handlebars. I tried giving it in img src tag directly in the html but still not working. What i have is that the image is in svg form and in my assets folder of the project.
I also tried the example on the official nodemailer site which did not work as well. Please help me out!
https://nodemailer.com/message/embedded-images/
This is my function which will be called when I get the request from the client.
sendEmail.js
var nodemailer = require("nodemailer");
const emailConfig = require("../readEmailConfigFile");
//reading username and password from json file
let fromemail = emailConfig.readFromEmail();
let password = emailConfig.readFromPassword();
var handlebars = require("handlebars");
var fs = require("fs");
const readHTMLFile = function(path, callback) {
fs.readFile(path, { encoding: "utf-8" }, function(err, html) {
if (err) {
throw err;
callback(err);
} else {
callback(null, html);
}
});
};
/* Method for sending Email */
const sendEmail = (details) => {
var transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: fromemail,
pass: password
}
});
readHTMLFile(
__dirname + "/../emailTemplates/EmailTemplate.html",
function(err, html) {
var template = handlebars.compile(html);
var replacements = {
firstName: details.firstName,
lastName: details.lastName,
address: details.address,
};
var htmlToSend = template(replacements);
var mailOptions = {
from: fromemail,
to: details.email,
subject: "ABC",
html: htmlToSend
};
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log(error);
callback(error);
} else {
console.log("Email Sent : " + info.response);
}
});
}
);
};
This is my html-template file
EmailTemplate.html
<html>
<head>
<title> </title>
</head>
<body>
<p>
Dear {{{firstName}}} {{{lastName}}}, your address is {{{address}}}</span
>
</p>
</body>
</html>
I want to embed an svg image in this html!
just add attachments parameter to your mailoptions object :
var mailOptions = {
from: fromemail,
to: details.email,
subject: "ABC",
attachments: [{
filename: 'imagename.svg',
path: __dirname +'/assets/imagename.svg',
cid: 'imagename'
}],
html: htmlToSend
};
then add the img tag in your HTML <img src="cid:imagename">

Send PDF generated with jsPDF to server

I am generating a PDF client side with jsPDF. I need to send it to my Express server using Axios. At the end I need to send it via email with Nodemailer. Where am I wrong?
Client side code:
//doc creation ....
var res = doc.output('datauristring'); //this line!!!!
axios.post('/mailsender', res).then((res) => {
if(res.status === 'ok') console.log("Yeah!");
else console.log(":(");
});
Server side code:
...
api_router.post('/mailsender', (req, res) => {
mail.send(req.body, (res) => {
res.status(200).json({"status": res ? 'ok' : 'error' });
});
});
mail.js that is:
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
host: 'smtp.mail.yahoo.com',
port: 465,
secure: true,
auth: {
user: 'example#yahoo.it',
pass: 'password'
}
});
exports.send = function (data, callback) {
let mailOptions = {
from: '"My application" <example#myapp.com>',
to: "receiverAddress",
subject: "Attachment experiment",
text: "My <3",
attachments: [
{
filename: 'attachment.pdf',
content: data,
contentType: 'application/pdf',
encoding: 'base64' //this line!!!!
}
]
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
callback(false);
}
callback(true);
});
}
All is working fine, except that if I try to open the attachment in the received mail, Preview says that the file is damaged. The same if I try to open it with google chrome or with other PDF readers. Probably, the two lines with a comment has to be changed. Thank you for your attention!
It was very simple: I had only to change the the attachment part in this way:
attachments: [
{
path: data
}
]
Below code worked for me , i used axios in client to post the pdf and nodemailer in server side in node.js to send pdf as attachment
Client :
const out = pdf.output('datauristring');
const response = await axios.post(`/email/sendReport`, {
pdf: out.split('base64,')[1],
});
Server:
let mailOptions = {
from: '"My application" <example#myapp.com>',
to: "receiverAddress",
subject: "Attachment experiment",
text: "My <3",
attachments: [
{
filename: 'attachment.pdf',
content: req.body.pdf,
contentType: 'application/pdf',
encoding: 'base64'
}
]
};
I am saving pdf on the server and also sending pdf in Laravel mail from jsPDF.I'm posting my code.perhaps it helps someone.
sendPdfInMail() {
const doc = new jsPDF()
doc.text('Pdf from jspdf!', 10, 10)
var formData = new FormData()
formData.append('file', doc.output('datauristring').split('base64,')[1])
axiosIns
.post('auth/currency_statement', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then(function (response) {
console.log(response)
})
.catch(function (err) {
console.log(err.response)
alert('error')
})
},
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
PHP Laravel (Server Code)
public function send_currency_statement(Request $request) {
$data["email"] = "text#money.com";
$data["title"] = "Currency statement";
$data["body"] = "Please check your invoice";
$fileName = time().
'.pdf';
$path = public_path('temp/').$fileName;
//Decode pdf content
$pdf_decoded = base64_decode($request - > file);
//Write data back to pdf file
$pdf = fopen('temp/'.$fileName, 'w');
fwrite($pdf, $pdf_decoded);
//close output file
fclose($pdf);
Mail::send('emails.myTestMail', $data, function($message) use($data, $path) {
$message - > to($data["email"], $data["email"]) -
>
subject($data["title"]);
$message - > attach($path);
});
return response() - > json(['message' => 'send successfully']);
}

Pass variable to html template in nodemailer

I want to send email with nodemailer using html template. In that template I need to inject some dynamically some variables and I really can't do that. My code:
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
smtpTransport = nodemailer.createTransport(smtpTransport({
host: mailConfig.host,
secure: mailConfig.secure,
port: mailConfig.port,
auth: {
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
}
}));
var mailOptions = {
from: 'my#email.com',
to : 'some#email.com',
subject : 'test subject',
html : { path: 'app/public/pages/emailWithPDF.html' }
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
callback(error);
}
});
Let's say I want in emailWithPDF.html something like this:
Hello {{username}}!
I've found some examples, where was smth like this:
...
html: '<p>Hello {{username}}</p>'
...
but I want it in separate html file. Is it possible?
What you can do is read the HTML file using fs module in node and then replace the elements that you want changed in the html string using handlebars
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var handlebars = require('handlebars');
var fs = require('fs');
var readHTMLFile = function(path, callback) {
fs.readFile(path, {encoding: 'utf-8'}, function (err, html) {
if (err) {
callback(err);
}
else {
callback(null, html);
}
});
};
smtpTransport = nodemailer.createTransport(smtpTransport({
host: mailConfig.host,
secure: mailConfig.secure,
port: mailConfig.port,
auth: {
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
}
}));
readHTMLFile(__dirname + 'app/public/pages/emailWithPDF.html', function(err, html) {
if (err) {
console.log('error reading file', err);
return;
}
var template = handlebars.compile(html);
var replacements = {
username: "John Doe"
};
var htmlToSend = template(replacements);
var mailOptions = {
from: 'my#email.com',
to : 'some#email.com',
subject : 'test subject',
html : htmlToSend
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
}
});
});
I use it in all my projects. more clean and up to date and understandable. callback hell doesn't exist.
sendMail.ts The html file reads with handlebar, puts the relevant variables into the contents, and sends.
import * as nodemailer from 'nodemailer';
import * as handlebars from 'handlebars';
import * as fs from 'fs';
import * as path from 'path';
export async function sendEmail(email: string, subject: string, url: string) {
const __dirname = path.resolve();
const filePath = path.join(__dirname, '../emails/password-reset.html');
const source = fs.readFileSync(filePath, 'utf-8').toString();
const template = handlebars.compile(source);
const replacements = {
username: "Umut YEREBAKMAZ"
};
const htmlToSend = template(replacements);
const transporter = nodemailer.createTransport({
host: "smtp.mailtrap.io",
port: 2525, // 587
secure: false,
auth: {
user: "fg7f6g7g67",
pass: "asds7ds7d6"
}
});
const mailOptions = {
from: '"noreply#yourdomain.com" <noreply#yourdomain.com>',
to: email,
subject: subject,
text: url,
html: htmlToSend
};
const info = await transporter.sendMail(mailOptions);
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", "https://mailtrap.io/inboxes/test/messages/");
}
String replace isn't a good idea because you'll have to restore old strings or create a backup file to be able to change them another time, also it won't be asynchrone and it will cause a problem in every way!
you can do it much easier and more cleaner:
just go to your mail options and add context with your variables:
var mailOptions = {
from: 'nginx-iwnl#gmail.com',
to: 'username#gmail.com',
subject: 'Sending email',
template: 'yourTemplate',
context: { // <=
username: username,
whatever: variable
}
};
next thing to do is openning your html file and call your variables like:
{{username}}
If you're using Nodemailer 2.0.0 or higher, check this documentation:
https://community.nodemailer.com/2-0-0-beta/templating/ There they explain how to make use of external rendering with templates like that:
// external renderer
var EmailTemplate = require('email-templates').EmailTemplate;
var send = transporter.templateSender(new EmailTemplate('template/directory'));
They also give this example:
// create template based sender function
// assumes text.{ext} and html.{ext} in template/directory
var sendPwdReminder = transporter.templateSender(new EmailTemplate('template/directory'), {
from: 'sender#example.com',
});
where you see how to pass variables.
You will need the email-templates module: https://github.com/crocodilejs/node-email-templates and a template engine of your choice.
Also in the documentation of email-templates you'll find how to make your file structure in order that your templates can be found:
html.{{ext}} (required) - for html format of email
text.{{ext}} (optional) - for text format of email style.
{{ext}}(optional) - styles for html format subject.
{{ext}}(optional) - for subject of email
See supported template engines for possible template engine extensions (e.g. .ejs, .jade, .nunjucks) to use for the value of {{ext}} above.
You may prefix any file name with anything you like to help you identify the files more easily in your IDE. The only requirement is that the filename contains html., text., style., and subject. respectively.
Create one file emailTemplates.js there yo can store each template as a function
emailTemplates.js
const newsLetterEmail = (clientName) => `<p>Hi ${clientName}, here you have today news.</p>`
const welcomeEmail = (clientName, username) => `<p>Welcome ${clientName}, your username is ${username}.</p>`
export {newsLetterEmail, welcomeEmail}
Then in the controllers call any templateFunction and store in output varaible
controller.js
import {welcomeEmail} from './emailTeamplates.js'
const registerUser = async(req, res) => {
const {name, usename, email} = req.body
// User register code....
const output = welcomeEmail(name, username)
let mailOptions = {
from: '"Welcome" <welcome#welcome.com>',
to: 'client#gmail.com',
subject: 'Welcome email!',
text: 'Hello World',
html: output,
}
For those using pug as templating engine
Just a quick way to render a template in a separate file using pug's render function:
// function to send an e-mail. Assumes you've got nodemailer and pug templating engine installed.
// transporter object relates to nodemailer, see nodemailer docs for details
const nodemailer = require('nodemailer');
const pug = require('pug');
function send_some_mail(iterable){
var message = {
from: 'from#example.com',
to: 'to#example.com',
subject: 'Message title',
html: pug.renderFile(__dirname + 'path_to_template.pug', {iterable: iterable})
};
transporter.sendMail(message, function(err, info){...})
}
// template.pug
each item in iterable
li
p #{item.name}
See https://pugjs.org/api/getting-started.html for further details. Note that this will cause template re-compilation every time a message is sent. That is fine for occasional e-mail deliveries. If you send tons of e-mails, you can cache the compiled template to work around that. Check out pug docs for that set up if you need it.
You can use a Web Request to build an html template using handlebars or any other engine.
Create a template
First you must create an html template for the email body. In this example I used a handlebars hbs file.
Do your design stuff with html and add the variables that you will need in the message:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Welcome Email Template</title>
</head>
<body>
<p style="font-size: 14px; font-weight: normal;">Hi {{data.name}}</p>
</body>
</html>
Create a template request
You must create the access to this view. Then a request is created where we can send the template name as an url parameter to make the request parameterizable for other templates.
const web = express.Router()
web.post('/template/email/:template', function(req, res) {
res.render(`templates/email/${req.params.template}`, {
data: req.body
})
})
Mail function
Finally you can send the email after making the request to the template. You can use a function like the following:
const nodemailer = require('nodemailer')
const request = require("request")
function sendEmail(toEmail, subject, templateFile) {
var options = {
uri: `http://localhost:3000/template/email/${templateFile}`,
method: 'POST',
json: { name: "Jon Snow" } // All the information that needs to be sent
};
request(options, function (error, response, body) {
if (error) console.log(error)
var transporter = nodemailer.createTransport({
host: mailConfig.host,
port: mailConfig.port,
secure: true,
auth: {
user: mailConfig.account,
pass: mailConfig.password
}
})
var mailOptions = {
from: mailConfig.account,
to: toEmail,
subject: subject,
html: body
}
transporter.sendMail(mailOptions, function(error, info) {
if (error) console.log(error)
})
})
}
This can be done without templates.
Try changing it to this:
`Hello ${username}!`
Make sure that these are not inverted commas but back ticks.
There is one easy way to insert variable inside html in nodemailer.
html:"<p>Your message "+variable1+".Message continueous "+variable 2+"</p>"
You can also use async/await syntax or promises and avoid using callbacks, like I did here, using async/await:
const fs = require("fs").promises;
const path = require("path");
const handlebars = require("handlebars");
const relativeTemplatePath = "../../html/reset-pw-email-template.html";
function sendEmail(){
const templatePath = path.join(__dirname, relativeTemplatePath);
const templateFile = await fs.readFile(templatePath, 'utf-8');
const template = handlebars.compile(templateFile);
const replacements = {
username:""
};
const finalHtml = template(replacements);
const mailOptions = {
from: "",
to: "",
subject: "",
html: finalHtml,
};
}

How to send message with nodemailer and email-templates?

I try to send email with nodemailer and email-templates. Now I have example from here example email templates. But when I check this code, I have error a promise was rejected with a non-error: [object Undefined]
Help me please. This is my code
var nodemailer = require('nodemailer');
var EmailTemplate = require('email-templates').EmailTemplate;
exports.sendOne = function () {
var templatesDir = config.templatesDir;
var template = new EmailTemplate(path.join(templatesDir, 'hello.jade'))
var transport = nodemailer.createTransport({
service: config.service,
auth: config.auth
});
// An example users object with formatted email function
var locals = {
email: 'example#mail.com',
name: {
first: 'Mamma',
last: 'Mia'
}
}
// Send a single email
template.render(locals, function (err, results) {
if (err) {
return console.error(err)
}
transport.sendMail({
from: 'Spicy Meatball <spicy.meatball#spaghetti.com>',
to: locals.email,
subject: 'Mangia gli spaghetti con polpette!',
html: results.html,
text: results.text
}, function (err, responseStatus) {
if (err) {
return console.error(err)
}
console.log(responseStatus.message)
})
})
}
My error :
Warning: a promise was rejected with a non-error: [object Undefined]
at /home/project/node_modules/email-templates/lib/util.js:31:39
at FSReqWrap.oncomplete (fs.js:82:15)
From previous event: ...
Tell me please how to fix this error? thanks!
UPDATE code
exports.sendOne = function () {
var nodemailer = require("nodemailer");
var transport = nodemailer.createTransport({
service: "gmail",
auth: {
user: "test#gmail.com",
pass: "123456",
},
});
var EmailTemplate = require("email-templates").EmailTemplate;
var path = require("path");
var templateDir = path.join(__dirname, "templates", "hello");
var myTemplate = new EmailTemplate(templateDir);
var locals = {
email: "example#mail.com",
name: {
first: "Mamma",
last: "Mia",
},
};
myTemplate.render(locals, function (err, result) {
// result.html
// result.text
if (err) {
return console.error(err);
}
transport.sendMail(
{
from: "Spicy Meatball <spicy.meatball#spaghetti.com>",
to: locals.email,
subject: "Mangia gli spaghetti con polpette!",
html: results.html,
text: results.text,
},
function (err, responseStatus) {
if (err) {
return console.error(err);
}
console.log(responseStatus.message);
return responseStatus; // return from status or as you need;
}
);
});
};
I updated my code but now i have error { [Error: ENOENT: no such file or directory, stat '/path-to-my-project/templates/hello''] errno: -2, code: 'ENOENT', syscall: 'stat', path: '/path-to-my-project/templates/hello' }
I guess template rendering issue and you should return something from function (err, responseStatus){} for success
Here I assume hello.jade in templates folder and templates folder in root directory and ensure jade is using as template engine
can try it
var EmailTemplate = require('email-templates').EmailTemplate;
var path = require('path');
var templateDir = path.join(__dirname, 'templates', 'hello');
var myTemplate = new EmailTemplate(templateDir);
var locals = {
email: 'example#mail.com',
name: {
first: 'Mamma',
last: 'Mia'
}
}
myTemplate .render(locals , function (err, result) {
// result.html
// result.text
if (err) {
return console.error(err)
}
// check here what is showing in your result
transport.sendMail({
from: 'Spicy Meatball <spicy.meatball#spaghetti.com>',
to: locals.email,
subject: 'Mangia gli spaghetti con polpette!',
html: results.html,
text: results.text
}, function (err, responseStatus) {
if (err) {
return console.error(err)
}
console.log(responseStatus.message)
return responseStatus;// return from status or as you need;
})
})
Updated: As far I guess it's not nodemailer related issue it's may be template rendering issue. can check by directory or by html page.
Thanks to the previous contributions I have been able to adapt Nodemailer with the current version of email-emplates
const nodemailer = require('nodemailer');
const Email = require('email-templates');
const path = require('path');
//Nodemailer Transporter
const transport = nodemailer.createTransport({
host: "mail.mydomain.com",
port: 465,
secure: true,
auth: {
user: "noreply#mydomain.com",
pass: "841%POHYRYK%",
},
tls: {
rejectUnauthorized: false
}
});
//Generate template (Example: templates/emails/demo/index.pug)
var template = path.join(__dirname, 'templates/emails', 'demo');
var email = new Email({views: { root: template }});
var locals = {email:'myemail#gmail.com', username:'CompaCode'};
async function(){
var html = await email.render(template, locals);
//Send Email
await transport.sendMail({from: 'Apolobit <noreply#apolobit.com>', to: locals.email, subject:'Demo Subject', html});
}

How to authenticate the URLs that serves Static files in Hapi JS

I have a route as below which serves the static pages:
{
method: 'GET',
path: '/webapp/{param*}',
config: {
handler: {
directory :{
path : Path.join(__dirname, '../../webapp/'),
index: true
}
}
}
}
So, I want to check if the user is logged in or not before it takes user to that url "/webapp/#blabla".
User Can only access that url if user is logged in.
I tried to add pre option with a function in the above route but no luck.
{
method: 'GET',
path: '/webapp/{param*}',
pre:[{method:checkUrl, assign:'m1'}],
config: {
handler: {
directory :{
path : Path.join(__dirname, '../../webapp/'),
index: true
}
}
}
}
And the checkUrl function is as:
var checkUrl = function(request, reply) {
if (!request.auth.isAuthenticated) {
// redirect to login page
reply.redirect('/login');
}
return true;
}
Why is that i cannot get redirected to login page?
It depends slightly on which auth scheme you're using but the same principle applies. Here's an example using hapi-auth-basic (adapted from the example in the README):
var Bcrypt = require('bcrypt');
var Hapi = require('hapi');
var Path = require('path');
var Inert = require('inert');
var server = new Hapi.Server();
server.connection({ port: 4000});
var users = {
john: {
username: 'john',
password: '$2a$10$iqJSHD.BGr0E2IxQwYgJmeP3NvhPrXAeLSaGCj6IR/XU5QtjVu5Tm', // 'secret'
name: 'John Doe',
id: '2133d32a'
}
};
var validate = function (request, username, password, callback) {
var user = users[username];
if (!user) {
return callback(null, false);
}
Bcrypt.compare(password, user.password, function (err, isValid) {
callback(err, isValid, { id: user.id, name: user.name });
});
};
server.register([
require('inert'),
require('hapi-auth-basic')
], function (err) {
server.auth.strategy('simple', 'basic', { validateFunc: validate });
server.route({
method: 'GET',
path: '/webapp/{param*}',
config: {
auth: 'simple', // THIS IS THE IMPORTANT BIT
handler: {
directory :{
path : Path.join(__dirname, 'files'),
index: true
}
}
}
});
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server started!');
})
});
The important point is just to add an auth property to the route config with the strategy name. It's the same as you would do for any routes. Have a read of this tutorial, it might clear it up for you.
Are you able to adapt that to your needs?

Categories

Resources