How to attach a node.js readable stream to a Sendgrid email?

I'm using PDFKit to generate PDFs. I'm using Nodejitsu for hosting, so I can't save the PDFs to file, but I can save them to a readable stream. I'd like to attach that stream in a Sendgrid email, like so:

sendgrid.send({ to: email, files: [{ filename: 'File.pdf', content: /* what to put here? */ }] /* ... */ });

I've tried doc.output() to no avail.


To use the SendGrid nodejs API with a streaming file, just convert the streaming into a buffer. You can convert a readable stream into a buffer using stream-to-array.

var streamToArray = require('stream-to-array'); streamToArray(your_stream, function (err, arr) { var buffer = Buffer.concat(arr) sendgrid.send({ to: email, files: [{ filename: 'File.pdf' content: buffer }] }) })


I recently struggled with this issue myself, and I just wanted to share what worked for me:

//PdfKit var doc = new PDFDocument({ size: 'letter' }); doc.text('My awesome text'); doc.end(); //Sendgrid API var email = new sendgrid.Email(); email.addTo ('XXX@gmail.com'); email.setFrom ('XXX@gmail.com'); email.setSubject ('Report'); email.setText ('Check out this awesome pdf'); email.addFile ({ filename: project.name + '.pdf', content: doc, contentType: 'application/pdf' }); sendgrid.send(email, function(err, json){ if(err) {return console.error(err);} console.log(json); });

The key is to make "doc" the content in your file attachment


  • Amazon SES custom header List-Unsubscribe isn't working
  • adding sendgrid addon to my heroku django app
  • Variable substitution in SendGrid templates with Nodejs does not work
  • How to use a global selector to respond to all click events except on one element?
  • Why use CDN(Content Delivery Network‎)? [duplicate]
  • Possible Autoit-like JavaScript macros?
  • Javascript variables for Get http
  • miss prototype functions when “new” a instance
  • shutdown and update job in Google Dataflow with PubSubIO + message guarantees
  • How many percent of the tweets does twitter sample API give?
  • How do I prepend to a stream in Bash?
  • PHP UTF-8 to GB2312
  • to implement a spinner in angular2+
  • What's the name of this finding square root algorithm?
  • Why must we declare a variable name when adding a method to a struct in Golang?
  • Not able to aggregate on nested fields in elasticsearch
  • rspec simple example getting error on request variable in integration test
  • why xml file does not aligned properly after append the string in beginning and end of the file usin
  • iOS: Detect app start via notification press
  • PostgreSQL Query without WHERE only ORDER BY and LIMIT doesn't use index
  • Exception “firebase.functions() takes … no argument …” when specifying a region for a Cloud Function
  • Java: can you cast Class into a specific interface?
  • Spray.io: When (not) to use non-blocking route handling?
  • DotNetZip - Calculate final zip size before calling Save(stream)
  • AES padding and writing the ciphertext to a disk file
  • Updating server-side rendering client-side
  • How to extract text from Word files using C#?
  • Deserializing XML into class C#
  • JSON with duplicate key names losing information when parsed
  • Updated Ionic CLI but shows previous version (Windows)
  • Hazelcast - OperationTimeoutException
  • Function pointer “assignment from incompatible pointer type” only when using vararg ellipsis
  • Warning: Can't call setState (or forceUpdate) on an unmounted component
  • RestKit - RKRequestDelegate does not exist
  • Revoking OAuth Access Token Results in 404 Not Found
  • Load html files in TinyMce
  • Free memory of cv::Mat loaded using FileStorage API
  • python draw pie shapes with colour filled
  • Append folder name and increment by 1 using batch script
  • How to Embed XSL into XML