sendgrid : add cc in email - node.js

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',
}),
}
}

Related

Nodemailer : How to send two different email to two different email address?

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));
}
})

Send email from G-Suite in nodejs server using Gmail API returns 400 bad request

I want to send an email from my G-Suite account in a nodejs server using Gmail API.
I know the credentials are ok, cause I have no problem to get messages/labels from my G-Suite.
this is my code:
const {GoogleAuth} = require('google-auth-library');
async sendMessage(to, from, subject, message) {
let raw = makeBody(to, from, subject, message);
let url = `https://www.googleapis.com/gmail/v1/users/${<MyEmail>}/messages/send`
let option = {
method: 'POST',
headers: {
'Content-Type': 'message/rfc822',
},
body: raw,
};
let client = await getClient()
client.request({url, option}, (res, err) => {
if (err) {
console.log('error', err);
} else {
console.log('res');
}
});
}
async getClient() {
try {
let auth = new GoogleAuth({
credentials: {
client_email: <clientEmail>,
private_key: <privateKey>,
},
scopes: [
"https://mail.google.com/",
"https://www.googleapis.com/auth/gmail.compose",
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.send"],
clientOptions: {subject: <myEmail>}
});
const client = await auth.getClient();
if (client)
return client
} catch (e) {
console.log('error accured while getClient', e);
return e;
}
}
I added the scopes of send, compose and modify to Admin Google, unfortunately I get this 400 bad request:
error [
{
domain: 'global',
reason: 'invalidArgument',
message: 'Invalid id value'
}
]
Use googleapis library.
const {google} = require('googleapis');
const gmail = google.gmail('v1');
async sendMessage(to, from, subject, message) {
let raw = makeBody(to, from, subject, message);
let client = await auth.getClient()
google.options({
auth: client
});
const res = await gmail.users.messages.send({
userId: 'me',
requestBody: {
raw: raw,
},
});
}

How to pass email receiver params in NodeJS to send email function with send grid service

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);
}
};

Need simultaneous working of Axios post for data and file from React

I can either have my axios post send some data ( example below ) or FormData. How would I set the call up so that I can send it all at once. The problem is that if I send both simultaneously, it doesn't send anything at all. My current call is :
async handleSubmit(e) {
e.preventDefault();
const { name, email, message } = this.state;
const formData = new FormData();
formData.append('file',this.state.file)
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
const form = await axios.post("/api/formPDF", {
name, ******
email, *****
message ****
}).post("/api/formPDF", formData, config);
}
The section I have indicated with * is where I believe my problem to be. The way I have it send now, I will have access to name/email/message on req.body. If I remove the object of the three, and replace it with formData it will correctly email the file but everything is clearly undefined. If I edit it as so :
const form = await axios.post("/api/formPDF", {
name,
email,
message,
formData
It makes it so both my req.body and the way I parse my file is an empty object. My relevant server code is :
app.post("/api/formPDF", (req, res) => {
var fileLoc, fileExt, fileName, fileEmail, fileMessage;
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
console.log("Files: ", files);
fileLoc = files.file.path;
fileExt = files.file.name.split('.').pop();
});
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({
name: *removed*,
host: *removed*,
port: 465,
secure: true,
auth: {
user: *removed*,
pass: *removed*
}
})
let mailOptions = {
from: *removed*,
to: *removed*,
replyTo: req.body.email,
subject: "New Message",
text: req.body.message,
html: htmlEmail,
attachments: [
{
filename: `${req.body.name}Resume.${fileExt}`,
path: fileLoc
}
]
};
fileLoc = "";
transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return console.log(err)
}
})
})
});
Am I missing something that is causing the objects to be empty? I know its not possible to read the formData client side, but I should be able to see it on my server. Thanks in advance.

How to enable error In Nodemailer if email is not exist

nodemailer : "^2.4.2"
I am sending mail using nodemailer. It's working fine. But while using not existing email, I am not getting any error:
I have code as;
exports.sendMail = function (req, resp, reqBody, callback) {
var smtpTransport = nodemailer.createTransport(settings.smtpConfig);
var data = JSON.parse(reqBody);
var mailOptions={
to : data.toAddress,
cc : data.ccAddress,
bcc : data.bccAddress,
subject : data.subject,
html : data.message
}
smtpTransport.sendMail(mailOptions, function(error, response){
if (error) {
callback(null, error);
}else{
callback(response);
}
});
};
So if i use any not existing email Id it doesn't throw any error;
For eg:If I send toAddress as 'dummy#gmail.com' -- it doesn't throw any error.
I got response as
{ accepted: [ 'dummy#gmail.com' ],
rejected: [],
response: '250 2.0.0 OK 1466501212 23sm18003603qty.40 - gsmtp',
envelope: { from: '', to: [ 'dummy#gmail.com' ] },
messageId: '1466501201867-84b63b27-ce337819-b06c739f#localhost' }
Same case for cc also.
Any help appreciated.

Resources