SendGrid No response from send function if attachment exists - javascript

Issue Summary
If I try to send an email with attachment added, I get no Promise resolve and no response, However, if I comment out the attachment logic, I receive an error (I entered invalid token to get an error), like I expected. The path to the doc file is real, but for this piece of code I changed it.
Code not working:
const fs = require('fs');
const sgMail = require('#sendgrid/mail');
(async () => {
sgMail.setApiKey('SG.XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXX');
const pathToAttachment = 'Path\\To\\doc\\file.doc';
const attachment = fs.readFileSync(pathToAttachment).toString('base64');
const msg = {
to: 'myemail#gmail.com',
from: 'youremail#gmail.com',
subject: 'test',
text: 'test',
attachments: [
{
content: attachment,
filename: 'file.doc',
type: 'application/doc',
disposition: 'attachment'
}
]
};
let result = null;
try {
result = await sgMail.send(msg);
console.log('sent!');
} catch (err) {
console.error(err.toString());
}
console.log(`result: ${result}`);
})();
Not getting any response, the code ignores the rest of any code that goes after the 'send' function.
Code working:
const fs = require('fs');
const sgMail = require('#sendgrid/mail');
(async () => {
sgMail.setApiKey('SG.XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXX');
const pathToAttachment = 'Path\\To\\doc\\file.doc';
const attachment = fs.readFileSync(pathToAttachment).toString('base64');
const msg = {
to: 'myemail#gmail.com',
from: 'youremail#gmail.com',
subject: 'test',
text: 'test',
/* attachments: [
{
content: attachment,
filename: 'file.doc',
type: 'application/doc',
disposition: 'attachment'
}
] */
};
let result = null;
try {
result = await sgMail.send(msg);
console.log('sent!');
} catch (err) {
console.error(err.toString());
}
console.log(`result: ${result}`);
})();
Code works as I expected, getting:
Unauthorized (401)
The provided authorization grant is invalid, expired, or revoked
null
null
result: null
Technical details:
"#sendgrid/mail": "^7.4.0"
node version: v14.15.1
I posted an issue on this on the their GitHub page:
https://github.com/sendgrid/sendgrid-nodejs/issues/1220
But they seem not to be able to produce the bug.Has anyone else faced this issue before?

As I write to SendGrid developers, they admit it's a bug on their package and it will be fixed:
"#orassayag Thanks for providing more information. I was able to
recreate this issue and it looks like a bug on our end. We will add it
to our internal backlog to be prioritized. Pull requests and +1s on
the issue summary will help it move up the backlog. In the meantime I
would suggest using node version 12.20.0 and Sendgrid/mail: 7.4.0 as a
work around solution for now. Using these versions, I was able to get
the error logs to show up when attaching the same file."
Question close.
here

Related

Can't figure out why I am getting this error in my terminal while creating a webpage with the help of API

This is my javascript code . while I am running it using nodemon I am getting error in my terminal . The error is mentioned at the bottom of the code
const express=require("express");
const bodypraser=require("body-parser");
const request =require("request");
const https=require("https");
const app=express();
app.use(express.static("public"));
app.use(bodypraser.urlencoded({extended:true}))
posting from route
app.post("/",function(req,res)
{
const firstname=req.body.fname;
const lastname=req.body.lname;
const email=req.body.email;
const data={
members:[
{
email_address:email,
status:"suscribed",
merge_fields:{
FNAME:firstname,
LNAME:lastname
}
}
]};
const jsondata=JSON.stringify(data);
const url= "https://us1.api.mailchimp.com/3.0/lists/a6b99f4c3c";
creating option object
const options={
method:"POST",
auth:"deco:d6550609e1d79db44b409d81841d74bf-us1"
}
const request=https.request(url,options,function(response){
response.on("data",function(data){
console.log(JSON.parse(data));
})
})
request.write(jsondata);
request.end();
});
app.get("/" ,function(req ,res){
res.sendFile(__dirname+"/signup.html");
});
app.listen(3000,function(req,res){
console.log("ok ");
});
End of code
This is the error which I am facing in my terminal
{
type: 'https://mailchimp.com/developer/marketing/docs/errors/',
title: 'Invalid Resource',
This is the error status
status: 400,
detail: "The resource submitted could not be validated. For field-specific
details, see the 'errors' array.",
instance: '26cacd7a-d1b6-4195-9407-9eb39a9ec224',
errors: [
{
field: 'members.item:0.status',
message: 'Data presented is not one of the accepted values: subscribed,
unsubscribed, cleaned, pending.'
}
]
}
Read the error message. Mailchimp requires status to be one of the four values mentioned in the error. Your status has two typos (status:"Suscribed") instead of subscribed (note the case sensitivity).
Next time you post a question please use proper code indentation.

HTTP does not recognize the body

this is my http code:
POST http://localhost:8000/register
host: localhost:8000
Content-Type: application/json
{
"id":111111,
"name":"example",
"email":"example#example.com",
"password":"example"
}
and the "/register" function is this (I am using react):
async register(ctx : RouterContext){
await console.log(ctx.request.body());
// const { value: {id,name, email, password} } = await ctx.request.body();
// const user = await User.findOne({email})
// if (user) {
// ctx.response.status = 422;
// ctx.response.body = {message : "Email is already in use"};
// return;
// }
// console.log(id,name, email, password);
}
I initially wanted to run what is commented out, to create a user. But when I do so I get a request error: ECONNREFUSED. So I just made it to console log what the body() actually is, but its empty. I have checked lots of websites and stack overflow posts yet no one has come across this bug where it doesn't identify my code. When I run it the way I just showed you I get this:
{ type: "json", value: Promise { <pending> } }
Please try:
async register(ctx: RouterContext){
console.log(await ctx.request.body().value);
}

How can I download and send a file from firebase cloud storage before deletion?

This is my current solution which is sending an empty file. I basically need to email a file before it gets deleted from a specific bucket
exports.sendBeforeDelete = functions.storage.bucket('reports').object().onDelete(async (object:any) => {
const fileBucket = object.bucket;
if (fileBucket === 'reports') {
const filePath = object.name;
if (filePath) {
const file = await request(`${object.mediaLink}&token=${object.metadata.firebaseStorageDownloadTokens}`);
const email = example#example.com
const mailOptions = {
from: 'example',
to: email,
subject: 'Report Deleted',
text: ` Mail Body
`,
attachments: [{
file
}
]
};
transporter.sendMail(mailOptions, function (error: any, info: any) {
if (error) {
console.log('error', error);
} else {
console.log('Email sent: ' + info.response);
}
});
}
}
return Promise.resolve()
});
I have tried just using the object but never seem to get a valid file.
It seems that the code provided is indeed not dealing with promises and asynchronous programming correctly. Please attempt to return a resolved promise once the async work has been completed. You can do so through using the Await operator.
This function terminates before any work has been done as you attempt to return Promise.resolve before the async work has completed.
The issue we found was that the file was already deleted on this function
functions.storage.bucket('reports').object().onDelete()
so it was no longer accessible to us. instead we ran a cronjob at 6AM to check if a file was due to be deleted that day and then sent it then instead of on deletion of the file

How to send zip file using #sendgrid/mail

This is the code I have written to send email with attachment using #sendgrid
const mailOptions = {}
if(mailOptions){
mailOptions.from = 'APP NAME'
mailOptions.to = 'emailId'
mailOptions.subject = 'Subject' // Subject line
//mailOptions.attachments = attachments
mailOptions.text = 'attachments'
}
const sendEmail = await sgMail.send(mailOptions)
But it only sends the mail with subject "no attachment"
The error I am getting when I uncomment the attachment line
{ Error: Bad Request
at Request.http [as _callback] (node_modules/#sendgrid/client/src/classes/client.js:124:25)
Why this is happening can someone please help me.
It's been a while since this question has been asked, but answering for future reference.
In order to fix the error, the attachment must have Base64 encoding - and its filetype should be set to 'application/zip'. The .js code to be input has also been vastly updated. An example today would look as follows
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const fs = require("fs");
pathToAttachment = `${__dirname}/attachment.zip`;
attachment = fs.readFileSync(pathToAttachment).toString("base64");
const msg = {
to: 'test#example.com',
from: 'test#example.com',
subject: 'Subject',
text: 'Sent using Node.js',
attachments: [{
content: data.toString('base64'),
filename: filename,
type: fileType,
disposition: 'attachment',
}, ],
};
sgMail.send(msg).catch(err => {
console.log(err);
});
Happy coding!

Tweeting w/ media fails using Firebase Cloud Functions

My Firebase web project has been working for several months now. But on Sunday June 3, 2018, my application stopped sending tweets with media (images) attached. Before this, it was working for several months. I have not changed the failing code before the 3rd and I have even reverted to code that worked before that date but the app still fails :(
SDK versions:
I am using the most up to date versions of Firebase tools (3.18.6), and cloud functions (1.0.3). Along with twit (2.2.10) a javascript library for twitter api.
Do note my project was also working on older versions of the above including pre v1.0 cloud functions. Also note, I am still able to send regular text tweets just not ones with any media (image,gif,mp4).
This mainly relates to Twitter's API, but I cannot rule out something funky going on in Firebase's Node.js environment.
How to reproduce:
For simplicity, I will link to the code in a tutorial which I originally used when starting the project.
Setup a twitter account and retrieve all the necessary tokens as outlined in the tutorial. Then simply call the cloud function below and it will attempt to tweet the NASA image of the day.
The function is able to upload the picture to the twitter server and the response I get is expected:
{ media_id: 1004461244487643100,
media_id_string: '1004461244487643136',
media_key: '5_1004461244487643136',
size: 92917,
expires_after_secs: 86400,
image: { image_type: 'image/jpeg', w: 960, h: 1318 } }
However, once it attempts to post the tweet with the media attached, I receive an error
code 324: 'Unsupported raw media category'
which doesn't exist in Twitter's docs: https://developer.twitter.com/en/docs/basics/response-codes.html
Now, Code 324 does exist but in Twitter's docs there is a different description:
"The validation of media ids failed"
Which I have yet to receive. So my media id is valid, so something else is wrong? No where on the internet can I find someone with this exact error.
Link to tutorial code:
https://medium.freecodecamp.org/how-to-build-and-deploy-a-multifunctional-twitter-bot-49e941bb3092
Javascript code that reproduces the issue:
**index.js
'use strict';
const functions = require('firebase-functions');
const request = require('request');
const path = require('path');
const os = require('os');
const fs = require('fs');
const tmpDir = os.tmpdir(); // Ref to the temporary dir on worker machine
const Twit = require('twit');
const T = new Twit({
consumer_key: 'your twitter key'
,consumer_secret: 'your twitter secret'
,access_token: 'your twitter token'
,access_token_secret: 'your twitter token secret'
});
exports.http_testMediaTweet = functions.https.onRequest((req, res) => {
function getPhoto() {
const parameters = {
url: 'https://api.nasa.gov/planetary/apod',
qs: {
api_key: 'DEMO_KEY'
},
encoding: 'binary'
};
request.get(parameters, (err, response, body) => {
if (err) {console.log('err: ' + err)}
body = JSON.parse(body);
var f = path.join(tmpDir, 'nasa.jpg');
saveFile(body, f);
});
}
function saveFile(body, fileName) {
const file = fs.createWriteStream(fileName);
request(body).pipe(file).on('close', err => {
if (err) {
console.log(err)
} else {
console.log('Media saved! '+body.title)
const descriptionText = body.title
uploadMedia(descriptionText, fileName);
}
})
}
function uploadMedia(descriptionText, fileName) {
const filePath = path.join(__dirname, `../${fileName}`)
console.log(`uploadMedia: file PATH ${fileName}`)
T.postMediaChunked({
file_path: fileName
}, (err, data, respone) => {
if (err) {
console.log(err)
} else {
console.log(data)
const params = {
status: descriptionText,
media_ids: data.media_id_string
}
postStatus(params);
}
})
}
function postStatus(params) {
T.post('statuses/update', params, (err, data, respone) => {
if (err) {
console.log(err)
res.status(500).send('Error: ' + err);
} else {
console.log('Status posted!')
res.status(200).send('success');
}
})
}
// Do thing
getPhoto();
});
I was hoping to launch my app next week but this has become a major issue for me. I've tried everything I can think of and consulted the docs for Twitter and the js library but I seem to be doing everything right. Hopefully someone can shed some light on this, thanks.

Categories