-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlambda_funciton.py
162 lines (129 loc) · 5.16 KB
/
lambda_funciton.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import json
import logging
import os
import urllib.parse
from email import policy
from email.header import decode_header
from email.parser import BytesParser
from email.utils import formataddr, parseaddr
import boto3
from botocore.exceptions import ClientError
# Set up logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Set up AWS clients
s3_client = boto3.client("s3")
ses_client = boto3.client("ses", region_name="ap-northeast-1")
CHARSET = "utf-8"
SENDER_EMAIL_DOMAIN = "example.com"
DEFAULT_RECIPIENTS = ["[email protected]"]
def load_forwarding_rules():
with open("forward_config.json", "r") as f:
return json.load(f)
FORWARDING_RULES = load_forwarding_rules()
# Environment variables
PRIVATE_BUCKET_NAME = os.environ["BUCKET_NAME"]
def lambda_handler(event, context):
# Log the full event
logger.info("Received event: %s", event)
# Parse S3 event and decode key
encoded_key = event["Records"][0]["s3"]["object"]["key"]
decoded_key = urllib.parse.unquote_plus(encoded_key)
logger.info("Decoded key: %s", decoded_key)
logger.info("Encoded key: %s", encoded_key)
try:
# Read email content from S3
response = s3_client.get_object(Bucket=PRIVATE_BUCKET_NAME, Key=decoded_key)
raw_email = response["Body"].read()
# Parse the .eml file
msg = BytesParser(policy=policy.default).parsebytes(raw_email)
# Extract original sender
original_sender_header = msg["From"]
original_sender_name, original_sender_email = parseaddr(original_sender_header)
logger.info("Original sender name: %s", original_sender_name)
logger.info("Original sender email: %s", original_sender_email)
if not original_sender_name:
display_name = original_sender_email
else:
display_name = original_sender_name
# Extract recipient address
to_address = msg["To"]
if isinstance(to_address, str):
to_address = to_address.lower().strip()
else:
decoded_to_address = decode_header(str(to_address))
to_address = ""
for header in decoded_to_address:
if isinstance(header[0], bytes):
to_address += header[0].decode(header[1] or "utf-8")
else:
to_address += header[0]
to_address = to_address.lower().strip()
# Determine forwarding rules
forwarding_rule = FORWARDING_RULES.get(to_address, None)
if forwarding_rule:
recipient_emails = forwarding_rule["recipients"]
sender_local_part = forwarding_rule["sender_local_part"]
else:
recipient_emails = DEFAULT_RECIPIENTS
sender_local_part = to_address.split("@")[
0
] # Use the local part of the address
sender_email = f"{sender_local_part}@{SENDER_EMAIL_DOMAIN}"
# Ensure From uses our domain
from_address = sender_email
# Modify the original email's From and To headers
if msg.get("From"):
msg.replace_header("From", formataddr((display_name, from_address)))
else:
msg["From"] = formataddr((display_name, from_address))
if msg.get("To"):
msg.replace_header("To", ", ".join(recipient_emails))
else:
msg["To"] = ", ".join(recipient_emails)
# Add Reply-To header
msg.add_header("Reply-To", original_sender_email)
# Remove unnecessary headers
if msg.get("Return-Path"):
del msg["Return-Path"]
if msg.get("Sender"):
del msg["Sender"]
if msg.get("Message-ID"):
del msg["Message-ID"]
while msg.get("DKIM-Signature"):
del msg["DKIM-Signature"]
# Construct new raw email content
raw_email = msg.as_bytes()
# Forward the email using SES
logger.info("Attempting to send email via SES...")
response = ses_client.send_raw_email(
Source=from_address,
Destinations=recipient_emails,
RawMessage={"Data": raw_email},
)
logger.info("SES response: %s", response)
logger.info("Email forwarded successfully")
return {"statusCode": 200, "body": "Email forwarded successfully"}
except s3_client.exceptions.NoSuchKey as e:
logger.error(
"NoSuchKey error: The specified key %s does not exist.", decoded_key
)
logger.error("Exception: %s", str(e))
return {
"statusCode": 404,
"body": f"Failed to retrieve the object {decoded_key} from bucket {PRIVATE_BUCKET_NAME}.",
}
except ClientError as e:
error_code = e.response["Error"]["Code"]
error_message = e.response["Error"]["Message"]
logger.error("ClientError: %s - %s", error_code, error_message)
return {
"statusCode": 500,
"body": f"Client error occurred: {error_code} - {error_message}",
}
except Exception as e:
logger.error("General error: %s", str(e))
return {
"statusCode": 500,
"body": "An error occurred while processing the email.",
}