@dltj aqui. Não posso ajudar com Node/JavaScript, mas posso oferecer um pseudo-código na forma do Python que estou usando para fazer isso acontecer:
""" AWS Lambda para receber mensagem do SES e postá-la no Discourse """
import json
import logging
import boto3
import requests
from base64 import b64decode
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
# pylint: disable=C0301
ENCRYPTED_DISCOURSE_KEY = "{cyper-text}"
DISCOURSE_KEY = boto3.client("kms").decrypt(
CiphertextBlob=b64decode(ENCRYPTED_DISCOURSE_KEY)
)["Plaintext"]
DISCOURSE_SITE = "discuss.folio.org"
EMAIL_S3_BUCKET = "openlibraryfoundation-discourse-mail"
DISCOURSE_URL = f"https://{DISCOURSE_SITE}/admin/email/handle_mail"
DISCOURSE_API_HEADERS = {
"Api-Key": DISCOURSE_KEY,
"Api-Username": "system",
}
def log_lambda_context(context):
"""Registra os atributos do objeto de contexto recebido do invocador do Lambda"""
LOGGER.info(
"Tempo restante (ms): %s. Fluxo de log: %s. Grupo de log: %s. Limites de memória (MB): %s",
context.get_remaining_time_in_millis(),
context.log_stream_name,
context.log_group_name,
context.memory_limit_in_mb,
)
def lambda_handler(event, context):
""" Lida com o evento de entrega do SES """
log_lambda_context(context)
LOGGER.info(json.dumps(event))
processed = False
for record in event["Records"]:
mail = record["ses"]["mail"]
mailMessageId = mail["commonHeaders"]["messageId"]
sesMessageId = mail["messageId"]
mailSender = mail["source"]
LOGGER.info(
"Processando um SES com mID %s (%s) de %s",
mailMessageId,
sesMessageId,
mailSender,
)
deliveryRecipients = mail["destination"]
for recipientEmailAddress in deliveryRecipients:
LOGGER.info("Destinatário da entrega: %s", recipientEmailAddress)
s3resource = boto3.resource("s3")
bucket = s3resource.Bucket(EMAIL_S3_BUCKET)
obj = bucket.Object(sesMessageId)
LOGGER.info("Obtendo %s/%s", EMAIL_S3_BUCKET, sesMessageId)
post_data = {"email": obj.get()["Body"].read()}
LOGGER.info("Postando em %s", DISCOURSE_SITE)
r = requests.post(
DISCOURSE_URL, headers=DISCOURSE_API_HEADERS, data=post_data
)
if r.status_code == 200:
LOGGER.info("Email aceito pelo Discourse: %s", DISCOURSE_SITE)
obj.delete()
processed = True
else:
LOGGER.error(
"Email rejeitado por %s (%s): %s",
DISCOURSE_SITE,
r.status_code,
r.content,
)
return processed
Estou usando Serverless para gerenciar a implantação e a manutenção do Lambda. Caso queira seguir um caminho semelhante, sinta-se à vontade para começar com este arquivo serverless.yml:
service: ses-post-to-discourse
frameworkVersion: "=1.36.1"
provider:
name: aws
runtime: python3.7
onError: arn:aws:sns:us-east-1:{AWS_ACCOUNT}:ses-discourse-DLQ
region: us-east-1
iamRoleStatements:
- Effect: 'Allow'
Action:
- 'ses:SendBounce'
Resource:
- '*'
- Effect: 'Allow'
Action:
- 's3:*'
Resource:
- 'arn:aws:s3:::openlibraryfoundation-discourse-mail/*'
- Effect: 'Allow'
Action:
- 'kms:decrypt'
Resource:
- 'arn:aws:kms:us-east-1:{AWS_ACCOUNT}:key/{UUID-of-key}'
package:
include:
# - something
exclude:
- node_modules/**
- .venv/**
- __pycache__
- secrets.yml
functions:
emailDispatcher:
handler: post_ses_delivery_lambda.lambda_handler
events:
- sns: ses-discourse-inbound
# CloudFormation resource templates
resources:
Resources:
EmailDispatcherLogGroup:
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: "30"
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
pythonBin: .venv/bin/python
dockerizePip: false