使用 API 网关 cURL 请求触发 Lambda 函数时解析 JSON 正文
Parsing JSON body when triggering a Lambda function with API Gateway cURL request
我正在 运行在 AWS Lambda 上使用一个简单的函数来通过 SMTP 发送电子邮件。
该函数使用 event
中的各种参数,例如 "event["reply_to_msg_id"]
”和“event["sender_name"]
”。
import smtplib
from email.message import EmailMessage
from email.utils import make_msgid
def lambda_handler(event, context):
msg = EmailMessage()
if event["reply_to_msg_id"] != "":
msg['References'] = event["reply_to_msg_id"]
msg['In-Reply-To'] = event["reply_to_msg_id"]
msg['subject'] = "Re: " + event["content"]["Subject Line"]
else:
msg['subject'] = event["content"]["Subject Line"]
msg['from'] = event["sender_name"]
msg['To'] = event["target_email"]
msg['Message-ID'] = make_msgid('random_client_id')
msg.add_header('Content-Type', 'text/html')
msg.set_payload(event["content"]["Body"])
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
result = {"Message-ID": msg['Message-ID']}
try:
server.login(event["email_account"]["email_address"], event["email_account"]["password"])
server.send_message(msg)
server.quit()
result["Status"] = "Success"
except Exception as E:
result["Status"] = str(E)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(result),
"isBase64Encoded": False
}
当我 运行 在 AWS Lambda 中使用以下正文进行测试时,一切正常:
{
"reply_to_msg_id": "",
"content": {
"Subject Line": "Test subject line.",
"Body": "This is <b>a body</b>."
},
"sender_name": "Joe Peschi",
"target_email": "test@gmail.com",
"email_account": {
"email_address": "***********",
"password": "***********"
}
}
问题:
我不知道如何使用 API 网关实际重现它。我为此功能创建了一个 API 网关触发器,但无论我尝试什么 - 我都无法将上述参数正确传递到事件中,就像我 运行 Lambda 测试时一样。
events
通过 API 网关有 different format, and you can't change that for proxy lambda integration. For non-proxy, you can use mapping templates.
验证 event
结构的最佳方法是将其打印出来并检查,如果您不使用映射模板,则在需要时修改 lambda 代码:
print(json.dumps(event, default=str))
我花了好几个小时胡思乱想,但我想通了。
json_body = json.loads(json.loads(json.dumps(event, default=str))["body"])
使用上面的行,我可以发送这个 JSON 正文并将其转换为字典变量:
{
"reply_to_msg_id": "",
"content": {
"Subject Line": "Test subject line.",
"Body": "This is <b>a body</b>."
},
"sender_name": "Joe Peschi",
"target_email": "test@gmail.com",
"email_account": {
"email_address": "***********",
"password": "***********"
}
}
不过,我也想继续使用 event
,这样我就可以在 Lambda 中使用原始 JSON 结构继续 运行ning 测试。
所以我创建了这段代码:
# THIS LINE TAKES THE REQUEST'S JSON BODY, AND TURNS IT INTO A DICT:
try:
json_body = json.loads(json.loads(json.dumps(event, default=str))["body"])
except:
json_body = ""
if json_body != "":
event = json_body
现在我可以 运行 cURL 请求,它会完美地工作:
curl --location --request GET 'https://********.execute-api.us-east-2.amazonaws.com/default/send_email_via_smtp' \
--header 'x-api-key: ****************' \
--header 'Content-Type: text/plain' \
--data-raw '{
"reply_to_msg_id": "",
"content": {
"Subject Line": "Test subject line.",
"Body": "This is <b>a body</b>."
},
"sender_name": "Joe Peschi",
"target_email": "robbyqla@gmail.com",
"email_account": {
"email_address": "**********",
"password": "********"
}
}'
但我也可以 运行 使用原始 JSON 结构通过 Lambda 测试的请求,它也可以完美地工作:
这是最终代码:
import smtplib
from email.message import EmailMessage
from email.utils import make_msgid
def lambda_handler(event, context):
try:
json_body = json.loads(json.loads(json.dumps(event, default=str))["body"])
except:
json_body = ""
if json_body != "":
event = json_body
msg = EmailMessage()
if event["reply_to_msg_id"] != "":
msg['References'] = event["reply_to_msg_id"]
msg['In-Reply-To'] = event["reply_to_msg_id"]
msg['subject'] = "Re: " + event["content"]["Subject Line"]
else:
msg['subject'] = event["content"]["Subject Line"]
msg['from'] = event["sender_name"]
msg['To'] = event["target_email"]
msg['Message-ID'] = make_msgid('random_client_id')
msg.add_header('Content-Type', 'text/html')
msg.set_payload(event["content"]["Body"])
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
result = {"Message-ID": msg['Message-ID']}
try:
server.login(event["email_account"]["email_address"], event["email_account"]["password"])
server.send_message(msg)
server.quit()
result["Status"] = "Success"
except Exception as E:
result["Status"] = str(E)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(result),
"isBase64Encoded": False
}
我正在 运行在 AWS Lambda 上使用一个简单的函数来通过 SMTP 发送电子邮件。
该函数使用 event
中的各种参数,例如 "event["reply_to_msg_id"]
”和“event["sender_name"]
”。
import smtplib
from email.message import EmailMessage
from email.utils import make_msgid
def lambda_handler(event, context):
msg = EmailMessage()
if event["reply_to_msg_id"] != "":
msg['References'] = event["reply_to_msg_id"]
msg['In-Reply-To'] = event["reply_to_msg_id"]
msg['subject'] = "Re: " + event["content"]["Subject Line"]
else:
msg['subject'] = event["content"]["Subject Line"]
msg['from'] = event["sender_name"]
msg['To'] = event["target_email"]
msg['Message-ID'] = make_msgid('random_client_id')
msg.add_header('Content-Type', 'text/html')
msg.set_payload(event["content"]["Body"])
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
result = {"Message-ID": msg['Message-ID']}
try:
server.login(event["email_account"]["email_address"], event["email_account"]["password"])
server.send_message(msg)
server.quit()
result["Status"] = "Success"
except Exception as E:
result["Status"] = str(E)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(result),
"isBase64Encoded": False
}
当我 运行 在 AWS Lambda 中使用以下正文进行测试时,一切正常:
{
"reply_to_msg_id": "",
"content": {
"Subject Line": "Test subject line.",
"Body": "This is <b>a body</b>."
},
"sender_name": "Joe Peschi",
"target_email": "test@gmail.com",
"email_account": {
"email_address": "***********",
"password": "***********"
}
}
问题:
我不知道如何使用 API 网关实际重现它。我为此功能创建了一个 API 网关触发器,但无论我尝试什么 - 我都无法将上述参数正确传递到事件中,就像我 运行 Lambda 测试时一样。
events
通过 API 网关有 different format, and you can't change that for proxy lambda integration. For non-proxy, you can use mapping templates.
验证 event
结构的最佳方法是将其打印出来并检查,如果您不使用映射模板,则在需要时修改 lambda 代码:
print(json.dumps(event, default=str))
我花了好几个小时胡思乱想,但我想通了。
json_body = json.loads(json.loads(json.dumps(event, default=str))["body"])
使用上面的行,我可以发送这个 JSON 正文并将其转换为字典变量:
{
"reply_to_msg_id": "",
"content": {
"Subject Line": "Test subject line.",
"Body": "This is <b>a body</b>."
},
"sender_name": "Joe Peschi",
"target_email": "test@gmail.com",
"email_account": {
"email_address": "***********",
"password": "***********"
}
}
不过,我也想继续使用 event
,这样我就可以在 Lambda 中使用原始 JSON 结构继续 运行ning 测试。
所以我创建了这段代码:
# THIS LINE TAKES THE REQUEST'S JSON BODY, AND TURNS IT INTO A DICT:
try:
json_body = json.loads(json.loads(json.dumps(event, default=str))["body"])
except:
json_body = ""
if json_body != "":
event = json_body
现在我可以 运行 cURL 请求,它会完美地工作:
curl --location --request GET 'https://********.execute-api.us-east-2.amazonaws.com/default/send_email_via_smtp' \
--header 'x-api-key: ****************' \
--header 'Content-Type: text/plain' \
--data-raw '{
"reply_to_msg_id": "",
"content": {
"Subject Line": "Test subject line.",
"Body": "This is <b>a body</b>."
},
"sender_name": "Joe Peschi",
"target_email": "robbyqla@gmail.com",
"email_account": {
"email_address": "**********",
"password": "********"
}
}'
但我也可以 运行 使用原始 JSON 结构通过 Lambda 测试的请求,它也可以完美地工作:
这是最终代码:
import smtplib
from email.message import EmailMessage
from email.utils import make_msgid
def lambda_handler(event, context):
try:
json_body = json.loads(json.loads(json.dumps(event, default=str))["body"])
except:
json_body = ""
if json_body != "":
event = json_body
msg = EmailMessage()
if event["reply_to_msg_id"] != "":
msg['References'] = event["reply_to_msg_id"]
msg['In-Reply-To'] = event["reply_to_msg_id"]
msg['subject'] = "Re: " + event["content"]["Subject Line"]
else:
msg['subject'] = event["content"]["Subject Line"]
msg['from'] = event["sender_name"]
msg['To'] = event["target_email"]
msg['Message-ID'] = make_msgid('random_client_id')
msg.add_header('Content-Type', 'text/html')
msg.set_payload(event["content"]["Body"])
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
result = {"Message-ID": msg['Message-ID']}
try:
server.login(event["email_account"]["email_address"], event["email_account"]["password"])
server.send_message(msg)
server.quit()
result["Status"] = "Success"
except Exception as E:
result["Status"] = str(E)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(result),
"isBase64Encoded": False
}