GianniTee
GianniTee

Reputation: 177

Email message forwarding: Python AWS lambda function is producing the wrong FROM address

The lambda function is designed to use AWS Simple Email Service (SES) for email forwarding. The "sender" address stands for the AWS-hosted email inbox that is filling up with messages. These messages are forwarded to the final "recipient" address by calling the lambda function to execute an S3 action on each individual stored email file. Both sender and recipient email addresses are verified in the SES email verification system. However, SES is blocking email forwarding. It detects that the "sender" address equals the "original sender" address, which represents an unverified address by definition because it comes from a random website visitor. My question is, how do I change the final message structure to include the appropriate "From" field and make SES know that it is the verified owner of the inbox who is forwarding the message to the verified recipient address?

import email
import os
import boto3
from botocore.exceptions import ClientError

region = os.environ['Region']


def get_message_from_s3(message_id):
    incoming_email_bucket = os.environ['MailS3Bucket']
    incoming_email_prefix = os.environ['MailS3Prefix']
    print("incoming_email_bucket " + incoming_email_bucket)
    print("incoming_email_prefix " + incoming_email_prefix)

    if incoming_email_prefix:
        object_path = (incoming_email_prefix + "/" + message_id)
    else:
        object_path = message_id

    object_http_path = (
        f"http://s3.console.aws.amazon.com/s3/object/{incoming_email_bucket}/{object_path}?region={region}")
    print("object_http_path " + object_http_path)

    # Create a new S3 client.
    client_s3 = boto3.client("s3")

    # Get the email object from the S3 bucket.
    object_s3 = client_s3.get_object(Bucket=incoming_email_bucket, Key=object_path)
    # Read the content of the message.
    file = object_s3['Body'].read()

    file_dict = {
        "file": file,
        "path": object_http_path
    }

    return file_dict


def create_message(file_dict):
    sender = os.environ['MailSender']
    print("sender " + sender)

    recipient = os.environ['MailRecipient']
    print("recipient " + recipient)

    # The email message is loaded from a file.
    email_message_original = email.message_from_string(file_dict['file'].decode('utf-8'))

    # Create a new subject line.
    subject_original = email_message_original['Subject']
    print("subject_original " + subject_original)

    separator = ";"
    print("The message was received from "
          + separator.join(email_message_original.get_all('From'))
          + ". This message is archived at " + file_dict['path'])

    email_message_original.replace_header("From", sender)
    email_message_original.replace_header("To", recipient)

    message = {
        "Source": sender,
        "Destinations": recipient,
        # copy data from the original email message.
        "Data": email_message_original.as_string()
    }

    return message


def send_email(message):
    # Create a new SES client.
    client_ses = boto3.client('ses', region)

    # Send the email.
    try:
        # Provide the contents of the email.
        response = client_ses.send_raw_email(
            Source=message['Source'],
            Destinations=[
                message['Destinations']
            ],
            RawMessage={
                'Data': message['Data']
            }
        )

    # Display an error if something goes wrong.
    except ClientError as e:
        output = e.response['Error']['Message']
    else:
        output = "Email sent! Message ID: " + response['MessageId']

    return output


def lambda_handler(event, context):
    # get the email message id
    message_id = event['Records'][0]['ses']['mail']['messageId']
    print(f"Received message ID {message_id}")

    # Retrieve the file from the S3 bucket.
    file_dict = get_message_from_s3(message_id)

    # Create the message.
    message = create_message(file_dict)

    # Send the email and print the result.
    result = send_email(message)
    print(result)

Upvotes: 0

Views: 863

Answers (1)

Adam Winter
Adam Winter

Reputation: 1914

You'll find the From address under "Return-Path"

mailobject = email.message_from_string(file_dict['file'].decode('utf-8'))
sentFrom = mailobject['Return-Path']

Upvotes: -1

Related Questions