You can create a lambda (nodejs) with the following code (written in typescript) to send an email to a user with a file attachment.
In the below example, we are first getting the content from S3 bucket, then creating a csv and sending it to a user (SES verified user).
import {
S3Client,
GetObjectCommand
} from "@aws-sdk/client-s3";
import { SESClient, SendRawEmailCommand } from "@aws-sdk/client-ses";
import { Readable } from "stream";
const s3Client = new S3Client({ region: "ap-southeast-2" });
const sesClient = new SESClient({ region: "ap-southeast-2" });
export const sendEmail = async () => {
const senderEmail = process.env.SENDER_EMAIL_ADDRESS;
const recipientEmail: any = process.env.RECIEVER_EMAIL_ADRESS;
const subject = "SUBJECT here";
const bodyText =
"Hello,\r\n\nPlease see the attached csv file \n\nThanks";
const getObjectCommand = new GetObjectCommand({
Bucket: process.env.BUCKET,
Key: process.env.BUCKET_KEY,
});
const attachmentData = await s3Client.send(getObjectCommand);
const attachmentBuffer = await streamToBuffer(
attachmentData.Body as Readable
);
const attachmentBase64 = attachmentBuffer.toString("base64");
const emailData =
`From: ${senderEmail}\r\n` +
`To: ${recipientEmail}\r\n` +
`Subject: ${subject}\r\n` +
`MIME-Version: 1.0\r\n` +
`Content-Type: multipart/mixed; boundary="boundary"\r\n\r\n` +
`--boundary\r\n` +
`Content-Type: text/plain; charset=utf-8\r\n` +
`${bodyText}\r\n\r\n` +
`--boundary\r\n` +
`Content-Type: application/octet-stream\r\n` +
`Content-Disposition: attachment; filename="file.csv"\r\n` +
`Content-Transfer-Encoding: base64\r\n\r\n` +
`${attachmentBase64}\r\n\r\n` +
`--boundary--`;
const sendRawEmailCommand = new SendRawEmailCommand({
RawMessage: {
Data: Buffer.from(emailData),
},
Source: senderEmail,
Destinations: [recipientEmail],
});
const result = await sesClient.send(sendRawEmailCommand);
return result.MessageId;
}
async function streamToBuffer(stream: Readable): Promise<Buffer> {
return new Promise((resolve, reject) => {
const chunks: Uint8Array[] = [];
stream.on("data", (chunk) => chunks.push(chunk));
stream.on("end", () => resolve(Buffer.concat(chunks)));
stream.on("error", reject);
});
}