You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Java Lambda(RequestStreamHandler)获取SES消息内容?

解决AWS SES投递到Java Lambda(RequestStreamHandler)无法获取邮件内容的问题

嘿,我来帮你搞定这个问题!你遇到的核心差异在于:SES给S3发的是原始邮件本身,但给Lambda(不管是直接投递还是经SNS转发)发的是事件通知对象——邮件内容是经过Base64编码后嵌入在事件结构里的,不是直接给你一个"content"字段。下面分情况给你具体的解决方案和代码示例:

1. 直接从SES投递到Lambda的场景

当SES直接触发你的Lambda时,输入流里的JSON事件结构中,原始邮件内容藏在 Records[0].ses.mail.rawMessage.data 这个字段里,它是Base64编码的字符串。因为你用的是RequestStreamHandler,得先把输入流读成JSON,再提取这个字段解码。

给你一段可直接用的示例代码:

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.util.Base64;

public class SesLambdaHandler implements RequestStreamHandler {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        // 把输入流解析成JSON节点
        JsonNode rootNode = objectMapper.readTree(inputStream);
        
        // 提取Base64编码的原始邮件内容
        String base64Mail = rootNode.path("Records").get(0)
                .path("ses").path("mail").path("rawMessage").path("data").asText();
        
        // 解码得到原始邮件(和S3里存的内容完全一致)
        byte[] decodedMailBytes = Base64.getDecoder().decode(base64Mail);
        String rawMailContent = new String(decodedMailBytes);
        
        // 这里就可以处理邮件内容了,比如打印或者解析正文/附件
        System.out.println("原始邮件内容:\n" + rawMailContent);
        
        // Lambda需要返回响应,这里简单返回成功状态
        outputStream.write("{\"statusCode\":200,\"message\":\"邮件内容已获取\"}".getBytes());
        outputStream.close();
    }
}

2. 通过SNS转发SES消息到Lambda的场景

如果是先把SES消息推到SNS,再由SNS触发Lambda,那Lambda收到的是SNS的事件结构,得先提取SNS里的Message字段(这个字段是SES事件的JSON字符串),再按上面的步骤处理。

调整后的核心代码片段:

// 读取输入流为JSON节点
JsonNode rootNode = objectMapper.readTree(inputStream);

// 先拿到SNS消息里的SES事件JSON
String sesEventJson = rootNode.path("Records").get(0)
        .path("Sns").path("Message").asText();

// 解析SES事件JSON
JsonNode sesRootNode = objectMapper.readTree(sesEventJson);

// 后续步骤和直接投递一致,提取Base64编码的邮件内容
String base64Mail = sesRootNode.path("Records").get(0)
        .path("ses").path("mail").path("rawMessage").path("data").asText();

byte[] decodedMailBytes = Base64.getDecoder().decode(base64Mail);
String rawMailContent = new String(decodedMailBytes);

额外的实用技巧

如果你的邮件是带附件或者多部分MIME格式的,解码后的rawMailContent是完整的MIME邮件,你可以用Java的MimeMessage类来解析具体的正文、附件等:

import javax.mail.internet.MimeMessage;
import javax.mail.Session;
import java.io.ByteArrayInputStream;
import java.util.Properties;

// 基于解码后的字节数组创建MIME消息
Session mailSession = Session.getDefaultInstance(new Properties());
MimeMessage mimeMsg = new MimeMessage(mailSession, new ByteArrayInputStream(decodedMailBytes));

// 获取邮件主题、发件人
String subject = mimeMsg.getSubject();
String sender = mimeMsg.getFrom()[0].toString();

// 获取邮件正文(如果是多部分内容,需要额外解析,这里是简单示例)
String body = mimeMsg.getContent().toString();

另外要确认你的Lambda执行角色有足够权限接收SES/SNS的事件——SES直接触发Lambda时通常会自动配置权限,但如果是SNS转发,得给SNS添加触发Lambda的权限哦。

内容的提问来源于stack exchange,提问作者Mike Summers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:49:58