如何通过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
相关产品推荐
相关产品推荐

