I have tried all and searched all stackoverflow but couldn't figure it out. Is there anyone who can help me out:
example:
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'youremail#gmail.com',
pass: 'yourpassword'
}
});
var mailOptions1 = {
from: 'company#gmail.com',
to: 'customer#yahoo.com',
subject: 'Sending Email to customers',
html: '<h1>Email to Custmer</h1>'
};
var mailOptions2 = {
from: 'company#gmail.com',
to: 'sales#yahoo.com',
subject: 'Sending Email to sales department',
html: '<h1>New Sales Order</h1>'
};
transporter.sendMail([mailOptions1, mailOptions2], function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
I have tried to pass mailOptions1 & mailOptions2 as array in the transporter.sendMail function but only one email is sent. How to make both emails to send ??
Thanks in advance...
Look at the interface of sendMail method of "nodemailer": "^6.5.0":
/** Sends an email using the preselected transport object */
sendMail(mailOptions: Mail.Options, callback: (err: Error | null, info: SentMessageInfo) => void): void;
sendMail(mailOptions: Mail.Options): Promise<SentMessageInfo>;
It only supports accept one mail option, does NOT support mail option array.
So you can use Promise.all() to send different email to different user concurrencily.
E.g.
Promise.all([mailOptions1, mailOptions2].map((opt) => transporter.sendMail(opt).catch(console.log))).then(
([sendMail1Res, sendMail2Res]) => {
console.log('sendMail1Res: ', sendMail1Res);
console.log('sendMail2Res: ', sendMail2Res);
},
);
Promise.all([transporter.sendMail(mailOptions), transporter.sendMail(mailOptions2)],(error,info)=>{
if (error) {
console.log(error)
} else {
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
}
})
Related
I have this code in a cloud function where I want to use nodemailer to send some notification emails.
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: 'mygmailaddress#gmail.com',
pass: 'apppassword'
}
})
/* Send email for custom programs to unsigned patients */
exports.sendEmailToNewPatient = functions.https.onRequest( (req, res) => {
cors( req, res, () => {
const mailOptions = {
to: req.body.userEmail,
from: 'mygmailaddress#gmail.com',
subject: `${req.body.doctorName} test!`,
text: 'Test message',
html: '<h1>Test message/h1>'
}
transporter.sendMail(mailOptions, (error, info) => {
if( error ) {
res.send(error.message)
}
const sendMailResponse = {
accepted: info.accepted,
rejected: info.rejected,
pending: info.pending,
envelope: info.envelope,
messageId: info.messageId,
response: info.response,
}
res.send(sendMailResponse)
})
})
})
I'm calling the function using a POST request made with axios, when the request is send I will get a status code of 200 and in the data object of axios response I will have this informations
data:
code: "EENVELOPE"
command: "API"
When I check my test email address to verify if the email is sent, I will not have any message as expected.
Any suggestion about?
I can see a small mistake in your code that the heading tag is not closed in the html message.
For more reference on how to send the mail using node mailer you can follow the below code.
As mentioned in the link:
const functions = require("firebase-functions");
const nodemailer = require('nodemailer');
const smtpTransport = require('nodemailer-smtp-transport');
const cors = require("cors")({
origin: true
});
exports.emailMessage = functions.https.onRequest((req, res) => {
const { name, email, phone, message } = req.body;
return cors(req, res, () => {
var text = `<div>
<h4>Information</h4>
<ul>
<li>
Name - ${name || ""}
</li>
<li>
Email - ${email || ""}
</li>
<li>
Phone - ${phone || ""}
</li>
</ul>
<h4>Message</h4>
<p>${message || ""}</p>
</div>`;
var sesAccessKey = 'YOURGMAIL#gmail.com';
var sesSecretKey = 'password';
var transporter = nodemailer.createTransport(smtpTransport({
service: 'gmail',
auth: {
user: sesAccessKey,
pass: sesSecretKey
}
}));
const mailOptions = {
to: "myemail#myemail.com",
from: "no-reply#myemail.com",
subject: `${name} sent you a new message`,
text: text,
html: text
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
console.log(error.message);
}
res.status(200).send({
message: "success"
})
});
}).catch(() => {
res.status(500).send("error");
});
})
;
For more information you can check the blog , thread and documentation where brief explanations including code is provided.
If all above has been followed well then you can check this thread for further details:
First of all, you have to enable the settings to allow less secure apps for the gmail account that you are using. Here is the link.
Secondly, Allow access for "Display Unlock captcha option" (Allow access to your Google account). Here is the link.
As mentioned by Frank van Puffelen ,here you can process POST data in Node.js using console.log(req.body.userEmail) for reference you can check link.
i try to send an email with nodemailer and outlook but after multi try and multiple forum i visited, i found nothing.
I try all the solution i've seen but nothing work. can you help me please
this is my code :
{
const path = require('path');
var message=fs.readFileSync(path.join(__dirname+'../../../asset/templateMail/mail.html')).toString();
message=message.replace('${user}', user.confirmation_code.toString());
var nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport(
{
//service :"Outlook365",
//pool:true,
host: 'SMTP.office365.com',
port: '587',
secure:false,
auth: { user: "it-factory-flex#outlook.fr", pass: process.env.NODEMAILLERPASS },
//secureConnection: false,
//requireTLS:true,
//tls: { ciphers: 'SSLv3' }
}
);
var mailOptions = {
name:"FlexOffice",
from: "it-factory-flex#outlook.com",
to: user.email,
subject: "FlexOffice: Code d'inscription",
html: message
}
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
}
all the commented part are my test
and i always got this:
Error: Connection timeout
at SMTPConnection._formatError (/home/romain/bred/flex-server/node_modules/nodemailer/lib/smtp-connection/index.js:784:19)
at SMTPConnection._onError (/home/romain/bred/flex-server/node_modules/nodemailer/lib/smtp-connection/index.js:770:20)
at Timeout.<anonymous> (/home/romain/bred/flex-server/node_modules/nodemailer/lib/smtp-connection/index.js:235:22)
solved, due to my network who block the flux.
I added to my NodeJS API an endpoint to send an email, for now, is a simple function that sent an email hardcoded and I did it using Send Grid service.
What I would like to achieve now is that I can pass the receiver email in the endpoint request and send the email.
Example of the endpoint url/email/:email
the :email will be the receiver of the email. I would like to pass this param to my email function which will send there. But I stack as cannot understand how to pass the param inside the sen email like it is now my code.
What I tried so far:
Router
// POST email send
router.post("/email/:email", async (req, res) => {
const email = req.params.email;
try {
const sent = await sendEmail(email);
if (sent) {
res.send({ message: "email sent successfully", status: 200 });
console.log("Email sent");
}
} catch (error) {
throw new Error(error.message);
}
});
// Routes
module.exports = router;
Send email
const mailGenerator = new MailGen({
theme: "salted",
product: {
name: "Awesome Movies",
link: "http://example.com"
}
});
const email = {
body: {
name: receiver here??,
intro: "Welcome to the movie platform",
action: {
instructions:
"Please click the button below to checkout new movies",
button: {
color: "#33b5e5",
text: "New Movies Waiting For you",
link: "http://example.com/"
}
}
}
};
const emailTemplate = mailGenerator.generate(email);
require("fs").writeFileSync("preview.html", emailTemplate, "utf8");
const msg = {
to: receiver here??,
from: "jake#email.io",
subject: "Testing email from NodeJS",
html: emailTemplate
};
const sendEmail = () => {
try {
sgMail.setApiKey(sg_token);
return sgMail.send(msg);
} catch (error) {
throw new Error(error.message);
}
};
module.exports = { sendEmail };
Your sendEmail method not accept parameters. Add receiver on signature and use it
const sendEmail = (receiver) => {
try {
sgMail.setApiKey(sg_token);
return sgMail.send({ ...msg, to: receiver });
} catch (error) {
throw new Error(error.message);
}
};
I'm aware that Firebase doesn't allow you to send emails using 3rd party email services. So the only way is to send through Gmail.
So I searched the internet for ways, so here's a snippet that works and allows me to send email without cost.
export const shareSpeechWithEmail = functions.firestore
.document("/sharedSpeeches/{userId}")
.onCreate(async (snapshot, context) => {
// const userId = context.params.userId;
// const data = snapshot.data();
const mailTransport = nodemailer.createTransport(
`smtps://${process.env.USER_EMAIL}:${process.env.USER_PASSWORD}#smtp.gmail.com`
);
const mailOptions = {
to: "test#gmail.com",
subject: `Message test`,
html: `<p><b>test</b></p>`
};
try {
return mailTransport.sendMail(mailOptions);
} catch (err) {
console.log(err);
return Promise.reject(err);
}
});
I want to create a template, so I used this package called email-templates for nodemailer.
But the function doesn't get executed in Firebase Console and it doesn't show an error and shows a warning related to "billing".
export const shareSpeechWithEmail = functions.firestore
.document("/sharedSpeeches/{userId}")
.onCreate(async (snapshot, context) => {
const email = new Email({
send: true,
preview: false,
views: {
root: path.resolve(__dirname, "../../src/emails")
// root: path.resolve(__dirname, "emails")
},
message: {
// from: "<noreply#domain.com>"
from: process.env.USER_EMAIL
},
transport: {
secure: false,
host: "smtp.gmail.com",
port: 465,
auth: {
user: process.env.USER_EMAIL,
pass: process.env.USER_PASSWORD
}
}
});
try {
return email.send({
template: "sharedSpeech",
message: {
to: "test#gmail.com",
subject: "message test"
},
locals: {
toUser: "testuser1",
fromUser: "testuser2",
title: "Speech 1",
body: "<p>test using email <b>templates</b></p>"
}
});
} catch (err) {
console.log(err);
return Promise.reject(err);
}
});
You can definitely send emails using third party services and Cloud Functions, as long as your project is on the Blaze plan. The official provided samples even suggest that "if switching to Sendgrid, Mailjet or Mailgun make sure you enable billing on your Firebase project as this is required to send requests to non-Google services."
https://github.com/firebase/functions-samples/tree/master/quickstarts/email-users
The key here, no matter which email system you're using, is that you really need to upgrade to the Blaze plan in order to make outgoing connections.
you can send emails by using nodemailer:
npm install nodemailer cors
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const nodemailer = require('nodemailer');
const cors = require('cors')({origin: true});
admin.initializeApp();
/**
* Here we're using Gmail to send
*/
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'yourgmailaccount#gmail.com',
pass: 'yourgmailaccpassword'
}
});
exports.sendMail = functions.https.onRequest((req, res) => {
cors(req, res, () => {
// getting dest email by query string
const dest = req.query.dest;
const mailOptions = {
from: 'Your Account Name <yourgmailaccount#gmail.com>', // Something like: Jane Doe <janedoe#gmail.com>
to: dest,
subject: 'test', // email subject
html: `<p style="font-size: 16px;">test it!!</p>
<br />
` // email content in HTML
};
// returning result
return transporter.sendMail(mailOptions, (erro, info) => {
if(erro){
return res.send(erro.toString());
}
return res.send('Sended');
});
});
});
See also here
Set Security-Level to avoid error-messages:
Go to : https://www.google.com/settings/security/lesssecureapps
set the Access for less secure apps setting to Enable
Refer to
Call a sendMail() cloud function directly via functions.https.onCall(..) :
As #Micha mentions don't forget to enable Less Secure Apps for the outgoing email: https://www.google.com/settings/security/lesssecureapps
const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
let mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'supportabc#gmail.com',
pass: '11112222'
}
});
exports.sendMail = functions.https.onCall((data, context) => {
console.log('enter exports.sendMail, data: ' + JSON.stringify(data));
const recipientEmail = data['recipientEmail'];
console.log('recipientEmail: ' + recipientEmail);
const mailOptions = {
from: 'Abc Support <Abc_Support#gmail.com>',
to: recipientEmail,
html:
`<p style="font-size: 16px;">Thanks for signing up</p>
<p style="font-size: 12px;">Stay tuned for more updates soon</p>
<p style="font-size: 12px;">Best Regards,</p>
<p style="font-size: 12px;">-Support Team</p>
` // email content in HTML
};
mailOptions.subject = 'Welcome to Abc';
return mailTransport.sendMail(mailOptions).then(() => {
console.log('email sent to:', recipientEmail);
return new Promise(((resolve, reject) => {
return resolve({
result: 'email sent to: ' + recipientEmail
});
}));
});
});
Thanks also to: Micha's post
You can send for free with Firebase extensions and Sendgrid:
https://medium.com/firebase-developers/firebase-extension-trigger-email-5802800bb9ea
DEPRECATED: https://www.google.com/settings/security/lesssecureapps
Use "Sign in with App Passwords": https://support.google.com/accounts/answer/185833?hl=en to create an app password.
follow the steps in the link then use the given password with your user in mailTransport:
const mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'user#gmail.com',
pass: 'bunchofletterspassword'
}
});
I am sending email using sendgrid from my app. Now I want to add cc or bcc if user reply to my mail. How Do I do this. let me explain first. I am sending answer of user's feedback comes on my web application using my application let say I am sending email via 'noreply#mydomain.com', and user receive this mail in his/her inbox in gmail/yahoo or any other email service. In this case user may click reply to this mail. so now, yours 'To:' has contain 'noreply#mydomain.com' default reply address. it's fine. Now I want to add 'cc:' (carbon copy) as follows 'feedback#mydomain.com'. How to do this?
You can pass the cc value when calling the sendgrid npm module. See below.
var sendgrid = require('sendgrid')(api_user, api_key);
var email = new sendgrid.Email({
to: 'foo#bar.com',
from: 'you#yourself.com',
cc: 'someone#else.com',
subject: 'Subject goes here',
text: 'Hello world'
});
sendgrid.send(email, function(err, json) {
if (err) { return console.error(err); }
console.log(json);
});
For sendGrid V3 you can follow this process to add .
var sgMailHelper = require('sendgrid').mail,
sg = require('sendgrid')('apiKey');
var sender = new sgMailHelper.Email(sender, senderName||'');
var receiver = new sgMailHelper.Email(receiver);
var content = new sgMailHelper.Content("text/plain", "Test mail");
var subject = "Mail subject";
var mailObj = new sgMailHelper.Mail(sender, subject, receiver, content);
// add cc email
mailObj.personalizations[0].addCc(new sgMailHelper.Email('cc.email#gmail.com'));
var request = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: mailObj.toJSON()
});
sg.API(request, function(error, response) {
if(error) {
console.log(error)
} else {
console.log('success')
}
});
If you are using version 7.6.2 of #sendgrid/mail, there is a cc attribute that works:
import sgMail from '#sendgrid/mail'
sgMail.setApiKey(process.env.SENDGRID_API_KEY)
const msg = {
to: toAddress,
from: fromAddress, // Use the email address or domain you verified above
cc: ccAddress,
subject: `Fresh message from - ${name}`,
text: `A new message was sent by ${name} from ${ccAddress}.
${message}
`,
html: `
<p>hello world</p>
<blockquote>${message}</blockquote>
`,
}
//ES8
try {
await sgMail.send(msg)
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: 'contactSubmission function',
}),
}
} catch (error) {
console.error(error)
if (error.response) {
console.error(error.response.body)
}
return {
statusCode: 400,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: 'error in email submission',
}),
}
}