Sending Email with attachments of more than 3mb using nodejs sdk

Nodejs sdk do not support to send email with multipart form data with attachments more than 3MB.

The sdk requires a model of SendMessageRequest, but there isn’t a way to pass multipart form data.

Using the following code to send the

===============SDK code =================

export const sendEmailWithAttachments = async ({
  grantId,
  from,
  fromName,
  to,
  subject,
  text,
  replyToMessageId,
  files = [],
  cc = [],
}: SendEmailParams) => {
  console.log(`SendEmail with reply to: ${replyToMessageId}, subject: ${subject}`)

  const filesToUpload = Array.isArray(files) ? files : [files]
  const attachments: CreateAttachmentRequest[] = []

  for (const file of filesToUpload) {
    attachments.push({
      content: file.data.split("base64,")?.[1] ?? "",
      filename: file.filename,
      contentType: getContentType(file.filename),
    })
  }

  const message: SendMessageRequest = {
    subject,
    body: text,
    to: [{ email: to }],
    cc: cc.map((email) => ({ email })),
    from: [{ email: from, name: fromName }],
    ...(replyToMessageId && { replyToMessageId: replyToMessageId }),
    trackingOptions: {
      threadReplies: true,
      opens: true,
    },
    attachments: attachments,
  }
  const resp = await nylas.messages.send({
    identifier: grantId,
    requestBody: message,
  })
  return resp.data
}

How can i send attachments of more than 3MB using nodejs sdk?

What i’m doing wrong here?

Hello @zeshanvirk I know there we some conversations around this topic…and a fix was released…are you using Gmail or Outlook?

Will tag @ram who is our Node expert… :slight_smile:

Hello @Blag ,

I’m using gmail, and nylas 7.5.2 is being used which is latest.

@zeshanvirk thanks for posting, let me take a look at this shortly.

@zeshanvirk so to clarify, all SDKs are setup to send via multipart/form-data so this should not be a blocker.

Taking a look at your code, are you receiving an error message from the API or SDK?

Yes, it throws and error which says files larger than 3MB are not supported.

BTW, if you can write some sample code to send multipart/form-data it would be easier for me to understand. or may be you can confirm if my code should work, but is not working.

@zeshanvirk thanks for confirming, I’m just following up with our team on this. Will share any working code sample as soon as possible.

Hi @zeshanvirk, here is a working code sample, we need to specify the file size:

import 'dotenv/config';
import Nylas from 'nylas';
import fs from 'fs';
import path from 'path';

const NylasConfig = {
  apiKey: process.env.NYLAS_API_KEY as string,
  apiUri: process.env.NYLAS_API_URI as string,
};

const nylas = new Nylas(NylasConfig);

async function sendEmail() {
  const attachmentPath = path.resolve('./src/example.jpg');
    
  if (!fs.existsSync(attachmentPath)) {
    throw new Error(`File not found: ${attachmentPath}`);
  }

  const fileContent = fs.readFileSync(attachmentPath);

  try {
    const sentMessage = await nylas.messages.send({
        identifier: process.env.GRANT_ID as string,
        requestBody: {
          to: [{ name: "Ram", email: process.env.EMAIL as string}],
          replyTo: [{ name: "Ram", email: process.env.EMAIL as string}],
          subject: "Subject",
          body: "Email Body",
          attachments: [{
            content: fileContent.toString('base64'),
            contentType: "image/jpeg",
            filename: 'example.jpg',
            size: 4549260 // specify the file size
          }]
        },
    });
    
    console.log('Email sent:', sentMessage);
  } catch (error) {
    console.error('Error sending email:', error);
  }
}


sendEmail();

Hello @ram ,

Sepcifying the size does send the email with attachments more than 3MB, but there is one problem occurring. The file which is being sent is corrupted.

I have file data like data:application/pdf;base64,JVBERi0xLjcKCjEgMCBv…

I’m sending the JVBERi0xLjcKCjEgMCBv… part as content, but the file in attachement doesn’t opens correctly.

I get the following error:

What i’m doing wrong here?

export const sendEmailWithAttachments = async ({
grantId,
from,
fromName,
to,
subject,
text,
replyToMessageId,
files = ,
cc = ,
}: SendEmailParams) => {
console.log(SendEmail with reply to: ${replyToMessageId}, subject: ${subject})

const filesToUpload = Array.isArray(files) ? files : [files]
const attachments: CreateAttachmentRequest =

for (const file of filesToUpload) {
attachments.push({
content: file.data.split(“base64,”)?.[1] ?? “”,
filename: file.filename,
contentType: getContentType(file.filename),
size: file.size,
})
}

const message: SendMessageRequest = {
subject,
body: text,
to: [{ email: to }],
cc: cc.map((email) => ({ email })),
from: [{ email: from, name: fromName }],
trackingOptions: {
threadReplies: true,
opens: true,
},
attachments,
}

const sentMessage = await nylas.messages.send({
identifier: grantId,
requestBody: message,
})

return sentMessage.data
}

@ram waiting for you to reply here.

Whats the best way to send attachments?

Hi,
If the SDK imposes a restriction on attachment size (e.g., 3MB), it can be challenging to bypass this limit directly within the SDK.

You can try by utilizing a third-party file storage service (like AWS S3, Google Cloud Storage) to handle large file attachments. Upload the file to the storage service, then include a link to the file in the email body instead of attaching the file directly.

In addition, here’s how you can modify your sendEmailWithAttachments function to include a link to an attachment:

JavaScript

import { getContentType } from './utils'; // Assume this is a utility to get content type

export const sendEmailWithAttachments = async ({
  grantId,
  from,
  fromName,
  to,
  subject,
  text,
  replyToMessageId,
  files = [],
  cc = [],
  fileLinks = [], // New parameter for file links
}: SendEmailParams) => {
  console.log(`SendEmail with reply to: ${replyToMessageId}, subject: ${subject}`)

  const filesToUpload = Array.isArray(files) ? files : [files]
  const attachments: CreateAttachmentRequest[] = []

  // Handle file links
  for (const fileLink of fileLinks) {
    attachments.push({
      content: '', // No content here since it's just a link
      filename: '', // Not needed
      contentType: 'text/plain', // Or another appropriate type
      url: fileLink, // Use fileLink instead of file content
    })
  }

  // Handle file uploads
  for (const file of filesToUpload) {
    attachments.push({
      content: file.data.split("base64,")?.[1] ?? "",
      filename: file.filename,
      contentType: getContentType(file.filename),
    })
  }

  const message: SendMessageRequest = {
    subject,
    body: text,
    to: [{ email: to }],
    cc: cc.map((email) => ({ email })),
    from: [{ email: from, name: fromName }],
    ...(replyToMessageId && { replyToMessageId: replyToMessageId }),
    trackingOptions: {
      threadReplies: true,
      opens: true,
    },
    attachments: attachments,
  }

  const resp = await nylas.messages.send({
    identifier: grantId,
    requestBody: message,
  })
  
  return resp.data
}

I hope this will help you.

Thanks :slightly_smiling_face:

1 Like