JBM
JBM

Reputation: 483

Attach image in S3 bucket to send with SendGrid

I am writing an iOS app in Swift 2.2 using Xcode 7.3.1. Then, for backend services I am using AWS Mobilehub (S3 and Lambda)

What the app should do: Take a screenshot, send it to an AWS S3 bucket, send the screenshot through SendGrid by using an AWS Lambda function trigger.

My problem: I can't seem to attach the damn image in the S3 bucket to the email. Locally it works fine, but when uploaded to Lambda is throws the following error:

Error: ENOENT: no such file or directory, open '...'

Using the following code:

'use strict';

var fs = require('fs');

console.log('Loading function');

let aws = require('aws-sdk');
let s3 = new aws.S3({ apiVersion: '2006-03-01' });

exports.handler = (event, context, callback) => {

    // Get the object from the event and show its content type
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));

    var helper = require('sendgrid').mail;

    let from_email = new helper.Email("[email protected]");
    let to_email = new helper.Email("[email protected]");
    let subject = "Hello World from the SendGrid Node.js Library";
    let content = new helper.Content("text/plain", "Email content");

    let mail = new helper.Mail(from_email, subject, to_email, content);


    var bse64 = base64_encode(INeedThisFrigginPath);

    let attachment = new helper.Attachment();
    attachment.setContent(bse64);
    attachment.setType("image/png");
    attachment.setFilename(key);
    attachment.setDisposition("attachment");
    mail.addAttachment(attachment);

    var sg = require('sendgrid')('SG.sengridkey');

    var requestBody = mail.toJSON();
    var emptyRequest = require('sendgrid-rest').request;
    var requestPost = JSON.parse(JSON.stringify(emptyRequest));
    requestPost.method = 'POST';
    requestPost.path = '/v3/mail/send';
    requestPost.body = requestBody;
    sg.API(requestPost, 
            function (error, response) 
            {
                console.log(response.statusCode);
                console.log(response.body);
                console.log(response.headers);
            }
    );
};

// function to encode file data to base64 encoded string
function base64_encode(file) 
{
    // read binary data
    var bitmap = fs.readFileSync(file);
    // convert binary data to base64 encoded string
    return new Buffer(bitmap).toString('base64');
}

Specifically this line:

var bse64 = base64_encode(INeedThisFrigginPath);

It's quite obvious what the problem is, so what I need to know is, what is the correct path to my image.

I have tried using the key value, and the image link:

https://s3.eu-central-1.amazonaws.com/bucketname/public/test0.png

No luck.

It would be great if anyone can help me by supplying code, a tutorial or just general pointers to boost me into the right direction. Maybe using AWS S3, AWS Lambda and SendGrid isn't necessarily the best technologies to use here?

Thanks a bunch!

Upvotes: 1

Views: 2546

Answers (1)

Mark B
Mark B

Reputation: 201093

You are trying to build a path to that file and then you are trying to open it as a local file. The file isn't local, it's on S3, so you can't do that. You have two options:

  • Download the file from S3 to Lambda first (into the /tmp directory) and then refer to the local path when you open the file.
  • Open a ReadStream to the file using the AWS S3 SDK.

Upvotes: 1

Related Questions