Tạo Extract Email Function

Đây là hàm đầu tiên, với các nhiệm vụ:

  • Trích xuất nội dung email từ kiểu MIME thành dữ liệu JSON
  • Gửi dữ liệu đó đến SQS.

Tại sao tôi cần hàm này?

Vì nhiều lý do:

  • Tôi muốn tiết kiệm chi phí khi gọi Amazon Bedrock và Lambda function trong Generate email (Nếu email có dữ liệu sai, chúng ta có thể phân tích chúng thành dữ liệu đã định dạng trước khi gọi AI agent, giảm số lượng token gửi đến mô hình LLM)
  • Dễ debug hơn
  • Trong thực tế, có thể một số hater sẽ tấn công endpoint này bằng cách gửi thư rác, vì vậy chúng ta có thể đặt một hàm xử lý ở đây.

Các bước thực hiện

  1. AWS Console, tìm kiếm “lambda” và chọn Lambda
lambda1
  1. Chọn Create function
lambda2
  1. Ở mục AWS Console, chọn Author from scratch, Function name là ExtractEmailLambda, nodejs Nodejs 22.x. Chọn role đã tạo trước đó ExtractEmailFunctionRole và chọn Create function
lambda3
  1. Tiếp, chúng ta cần upload source code cho function, bạn có thể download tại đây index.zip hoặc bạn có thể tự build tại đây. Sau khi tải về thì chọn Code > Upload from > .zip file
lambda4
  1. Chọn Save để tải lên
lambda5
  1. Upload thành công lambda6

  2. Tiếp theo, chúng ta cần thêm biến môi trường

lambda7
  1. Chúng ta có 2 giá trị
KeyValueDescription
QUEUE_NAMEsqs-generate-email-content-queueQueue này dùng để chứa email tới và gọi function tạo nội dung
BUCKET_NAMEai-powered-email-auto-repliesTên bucket để lấy nội dung email, vì SES không emit nội dung email mà chỉ emit key path (messageId) của email trên S3

Chọn Save

lambda8
  1. Cập nhật thành công
lambda9

Thông tin chi tiết

ConfigurationValueDescription
function_nameExtractEmailLambdaThe unique name identifier for the Lambda function
roleExtractEmailFunctionRoleIAM role that defines the permissions and access policies for the function
runtimenodejs20.xThe execution environment and version for the Lambda function (Node.js 20)
handlerindex.handlerThe entry point for the function
memory_size128Amount of memory allocated to the function in MB (128MB)
timeout30Maximum execution time allowed for the function in seconds
  1. Nhận event data từ SES và lấy dữ liệu từ S3
// Helper function to extract email data from SES event
const extractEmailData = async (event: SESEvent) => {
  const sesRecord = event.Records[0].ses;
  const messageId = sesRecord.mail.messageId;
  const emailData = {
    sender: sesRecord.mail.source,
    key: messageId,
  };

  // Get email content from S3
  const getObjectCommand = new GetObjectCommand({
    Bucket: env.bucketName,
    Key: `received-email/${messageId}`
  });

  const response = await s3Client.send(getObjectCommand);
  const emailContent = await response.Body?.transformToString();

  // Parsing MIME type to JSON object
  const { text, subject } = await simpleParser(emailContent);
  return {
    ...emailData,
    subject,
    content: text || "No email data"
  };
};
  1. Gửi data qua message SQS
const body = await extractEmailData(event);
const command = new GetQueueUrlCommand({ // GetQueueUrlRequest
    QueueName: env.queueName, // required
});
const queueUrlResponse = await sqsClient.send(command);
const params = {
    QueueUrl: queueUrlResponse.QueueUrl,
    MessageBody: JSON.stringify(body),
};
await sqsClient.send(new SendMessageCommand(params));

Full source code

import { Handler, SESEvent } from 'aws-lambda';
import { GetQueueUrlCommand, SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { Logger } from '@aws-lambda-powertools/logger';
import * as mailparser from 'mailparser';

require('dotenv').config();

const simpleParser = mailparser.simpleParser;
const logger = new Logger();

const env = {
  queueName: process.env.QUEUE_NAME || "",
  bucketName: process.env.BUCKET_NAME || ""
}

const sqsClient = new SQSClient();
const s3Client = new S3Client();

// Helper function to extract email data from SES event
const extractEmailData = async (event: SESEvent) => {
  const sesRecord = event.Records[0].ses;
  const messageId = sesRecord.mail.messageId;
  const emailData = {
    sender: sesRecord.mail.source,
    key: messageId,
  };
  // logger.info("Email Data: ", JSON.stringify(emailData, null, 2));

  // Get email content from S3
  const getObjectCommand = new GetObjectCommand({
    Bucket: env.bucketName,
    Key: `received-email/${messageId}`
  });

  const response = await s3Client.send(getObjectCommand);
  const emailContent = await response.Body?.transformToString();
  const { text, subject } = await simpleParser(emailContent);
  return {
    ...emailData,
    subject,
    content: text || "No email data"
  };
};

export const handler: Handler = async (event: SESEvent): Promise<void> => {
  try {
    const body = await extractEmailData(event);
    // logger.info({
    //     message: "Extracted email data",
    //     body: body
    // });
    const command = new GetQueueUrlCommand({ // GetQueueUrlRequest
      QueueName: env.queueName, // required
    });
    const queueUrlResponse = await sqsClient.send(command);
    const params = {
      QueueUrl: queueUrlResponse.QueueUrl,
      MessageBody: JSON.stringify(body),
    };
    await sqsClient.send(new SendMessageCommand(params));
  }
  catch (error) {
    logger.error(error as string);
  }
};

Tạo SES rule để trigger Extract Email function

  1. Vào SES dashboard sau đó vào phần Configuration > Email receiving > Create rule set
lambda17a
  1. Thêm tên rule TriggerEmailIncoming và chọn Create rule set
lambda18a
  1. Chọn tiếp “Create rule”
lambda19
  1. Nhập ExtractAndSaveToS3 và chọn Next
lambda20
  1. Như bạn có thể thấy Recipient conditions giống như Guidelines, để đơn giản thì tôi chỉ muốn trigger lambda function và lưu nội dung vào S3. Khi đó tôi chọn Next
lambda21
  1. Chọn Add new action > Invoke AWS lambda function
lambda22
  1. Chọn ExtractEmailLambda và thêm action khác là thêm vào S3
lambda23
  1. Tiếp theo chúng ta chọn thư mục đã tạo received-email. Chúng ta cũng cần thêm policies để SES có thể thêm nội dung email vào S3, choose Create IAM Role
lambda24
  1. Thêm role name SESSaveEmailToS3RoleCreate role
lambda25
  1. Chúng ta cần thêm vào policies đã tạo ở bước 4.4, chọn View role
lambda26
  1. Chúng ta sẽ attach policies này vào. Chọn Attach policies
lambda27
  1. Tìm kiếm từ khoá SESSaveEmailToS3Policy > SESSaveEmailToS3Policy > Add permissions
lambda28
  1. Attach thành công
lambda29
  1. Chúng ta quay ngược lại SES và chọn Next
lambda30
  1. Chọn Create rule
lambda31
  1. Cuối cùng là active rule, chọn rule và chọn Set as active
lambda32
  1. Xác nhận
lambda33
  1. Cấu hình thành công
lambda34