Microsoft Graph API outlook send attachments - node.js

How do you send attachments with the Microsoft graph outlook API? I understand everything for sending attachments up until the content bytes. The files that I need to send are a word document a pdf and a jpeg Is it asking me to turn the file into bytes, if so how would I do that? I am using node.js and I have the following code:
exports.send_mail = async function(req, res, next) {
let parms = { title: 'Inbox', active: { inbox: true } };
const accessToken = await authHelper.getAccessToken(req.cookies, res);
const userName = req.cookies.graph_user_name;
if (accessToken && userName) {
parms.user = userName;
// Initialize Graph client
const client = graph.Client.init({
authProvider: (done) => {
done(null, accessToken);
}
});
//read test.html
//so you have to wait for the file to read then send it
message = fs.readFileSync('views/test.html', 'utf8');
console.log(rawImage.data.toString('utf8'))
try {
mailMess ={
message:{
subject: 'This is a test',
body:{
ContentType: 'HTML',
Content: message
},
ToRecipients:[
{
EmailAddress:{
Address: 'name#email.com'
}
}
],
"attachments": [
{
"#odata.type": "#microsoft.graph.fileAttachment",
"name": "attachment.jpeg",
"contentBytes": "not sure what to put here"
}
]
}
}
//sendmail
const result = await client
.api('/me/sendmail')
.version('v1.0')
.post(mailMess);
res.status('202')
parms.messages = result.value;
res.redirect('/');
} catch (err) {
parms.message = 'Error retrieving messages';
parms.error = { status: `${err.code}: ${err.message}` };
parms.debug = JSON.stringify(err.body, null, 2);
res.render('error', parms);
}
} else {
// Redirect to home
res.redirect('/');
}
}

I found out that param takes the file encoded as base64

Related

Submitting without files resets the all images in the array when making a PATCH request

I'm trying to make a dynamic field for adding team members using Formik.
In my backend, if I do not choose any file and edit only other field such as "memberName" I'm getting message saying;
"Cast to embedded failed for value "{
_id: '63c5687832a80d5d8f717715',
memberName: 'qqaa',
memberJobTitle: 'qq',
memberDescription: 'qq',
images: [ 'undefined' ]
}" (type Object) at path "team" because of "CastError""
I want to keep the existing images if there is no changes in the input field. I'm having this issue for a week and couldn't figure it out.
This is my controller for making a PATCH request;
const updateSection = async (req, res, next) => {
const files = req.files;
const {
pageId,
welcomeTitle,
welcomeDescription,
aboutUsTitle,
aboutUsDescription,
team,
teamTitle,
} = req.body;
let updates = {};
//update other fields if they are provided in the request body
if (welcomeTitle) {
updates.welcomeTitle = welcomeTitle;
}
if (welcomeDescription) {
updates.welcomeDescription = welcomeDescription;
}
if (aboutUsTitle) {
updates.aboutUsTitle = aboutUsTitle;
}
if (aboutUsDescription) {
updates.aboutUsDescription = aboutUsDescription;
}
if (teamTitle) {
updates.teamTitle = teamTitle;
}
if (team) {
let teamPromises = []; //create an empty array to store promises for updating or creating team members
// updates.team.images = [];
team.forEach((item, i) => {
// item -> current team member being processed, i-> index in the array
let teamMember = {
_id: item._id,
memberName: item.memberName,
memberJobTitle: item.memberJobTitle,
memberDescription: item.memberDescription,
images: item.images,
};
if (files && files[i]) {
let file = files[i];
let img = fs.readFileSync(file.path);
let decode_image = img.toString("base64");
teamMember.images = [
{
filename: file.originalname,
contentType: file.mimetype,
imageBase64: decode_image,
},
];
} else {
teamMember.images = item.images;
}
teamPromises.push(
Section.updateOne(
{ pageId: pageId, "team._id": item._id },
{ $set: { "team.$": teamMember } },
{ new: false }
)
);
});
Promise.all(teamPromises)
.then((result) => {
res.status(200).json({ message: "Section updated successfully!" });
})
.catch((error) => {
res.status(500).json({ error: error.message });
});
} else {
//update other fields if no team member provided
Section.findOneAndUpdate({ pageId: pageId }, updates).then(() => {
res.status(200).json({ message: "Section updated successfully!" });
});
}
};

How to send PDF file object from Facebook messaging API

I have developed a facebook messenger app in Node.js.
I am using PDFKit to generate a PDF and send it to the user from the messenger bot. The problem I am facing is I am not able to send the generated file object.
generatePDF.js
require('dotenv').config("./env");
const getStream = require('get-stream')
const PDFDocument = require('pdfkit');
const fs = require('fs');
async function createPDF(name) {
const doc = new PDFDocument({
layout: 'landscape',
size: 'A4',
});
doc.rect(0, 0, doc.page.width, doc.page.height).fill('#fff');
``
doc.fontSize(10);
doc.image('src/airtable/assets/corners.png', -1, 0, { scale: 0.585 }, { fit: [doc.page.width, doc.page.height], align: 'center' })
doc
.font('src/airtable/fonts/Pinyon Script 400.ttf')
.fontSize(65)
.fill('#125951')
.text(`${name}`, 240, 240, {
// width: 500,
// align: 'center'
});
doc.end();
return await getStream.buffer(doc)
}
module.exports = { createPDF}
Invoking the above function after receiving specific postback
main.js
const pdf= require('./generatePDF')
name = "John"
const generated_pdf = await pdf.createPDF(name)
sendMedia(sender_psid, generated_pdf )
async function sendMedia(sender_psid, file) {
try {
let response = {
"attachment": {
"type": "file",
"payload": file
}
}
}
callSendAPI(sender_psid, response);
}
catch (e) {
console.log("Error cert ", e)
}
}
function callSendAPI(sender_psid, response) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
};
// Send the HTTP request to the Messenger Platform
request({
"uri": "https://graph.facebook.com/v7.0/me/messages",
"qs": { "access_token": process.env.FB_PAGE_TOKEN },
"method": "POST",
"json": request_body
}, (err, res, body) => {
if (!err) {
console.log('message sent!!!');
} else {
console.error("Unable to send message:" + err);
}
});
}
How can I send the file object without a URL and without fetching locally?
any help or advice is appreciated!
There is no such type ("application/pdf"), for sending attachments like a PDF you'd use the file type. Also, as stated in the docs, there is no "filedata" parameter, instead you'd use "payload".
Docs can be found here by the way:
https://developers.facebook.com/docs/messenger-platform/reference/send-api/

Error while sending PDF as an email attachment - Failed to launch the browser process

We're facing an issue while sending an attachment to a mail. Our scenario is something like, we're having a button "Send to My Email" which collects the logged-in user email and sends the filled form as a pdf to an email attachment. Everything is working fine on our local machine, but we're getting an error on the live testing site.
Our backend expressjs controller code:
const sendFormToEmail = async (req, res, next) => {
try {
const { formDetails } = req.body;
const to = formDetails?.email;
const from = "Our App Name here";
const subject = `Form Attachment`;
const html = emailTemplate({ formDetails });
let options = { format: "A4" };
let file = { content: html };
const pdfBuffer = await html_to_pdf.generatePdf(file, options);
await sendEmail({
to,
subject,
from,
html,
pdfBuffer,
filename: "form.pdf",
});
res.status(200).send({
status: true,
message: "Form sent to email successfully",
});
} catch (err) {
console.log("Error is ", err);
res.status(500).send({
status: false,
message: "Failed to send Form on an email",
});
}
};
sendEmail function code:
async function sendEmail({
to,
from,
subject,
text,
html,
pdfBuffer,
filename,
}) {
try {
const sendEmailResponse = await SENDGRID.send({
from,
to,
text,
html,
subject,
attachments: [
{
content: pdfBuffer.toString("base64"),
filename: filename,
type: "application/pdf",
disposition: "attachment",
},
],
});
console.log("EMAIL_SUCCESSFULLY_SEND: ", sendEmailResponse);
return true;
} catch (err) {
console.log(err.response.body.errors);
throw err;
}
}
The error we're facing:
Error is Error: Failed to launch the browser process!
/root/application-name/node_modules/html-pdf-node/node_modules/puppeteer/.local-chromium/linux-901912/chrome-linux/chrome: error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory
Please, help us in getting rid of this issue
So, basically, I found the solution for this here.

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

Resources