簡體   English   中英

如何將HTTP請求中的文件附加到電子郵件? (Python / AWS Lambda)

[英]How can I attach a file from an HTTP request to an email? (Python/ AWS Lambda)

我目前正在嘗試將電子郵件發送微服務遷移到雲中。 我的代碼在AWS Lambda函數中,該函數由發送到終端節點的http請求觸發。 如果該HTTP請求包含文件附件,則我的代碼應將該文件附加到它發送的電子郵件中。

目前,我的代碼可以正常發送電子郵件,但是當我嘗試發送附件時,它顯示為亂碼。 在通過HTTP請求發送文件然后將其附加到電子郵件的過程中,文件的內容會在某處更改。 但是,.txt文件可以毫無問題地發送。 為什么會搞砸這樣的文件?

先謝謝您的幫助。

我懷疑編碼存在問題,因此我嘗試(如下所示)發送附件的二進制數據,以二進制形式讀取該數據,然后編寫包含該二進制文件的附件對象,但這沒有幫助。 我還嘗試更改將文件附加到HTTP請求的方式,以防讀取方式有問題,但是沒有任何變化。 另外,我嘗試上傳到s3存儲桶,而不是附加到電子郵件,但這也沒有任何改變。

這是發送HTTP請求的代碼:

import requests
import json
import os

url = "..."

payload = {
    "requester": "Our robotic overlords",
    "recipients": [
        "..."
    ],
    "message": "This is the message the recipient will see",
    "subject": "THIS IS A SAMPLE. DO NOT BE ALARMED"
}

headers = {
    'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
    'Accept': "application/json",
    'Cache-Control': "no-cache",
    'Postman-Token': "79f6f992-0b1b-45a4-a00e-f095be17dc56,ce0c120c-b3f6-4658-89cd-269b122f0342",
    'Host': "q4kisdfuog.execute-api.us-east-1.amazonaws.com",
    'Accept-Encoding': "gzip, deflate",
    'Connection': "keep-alive",
    'cache-control': "no-cache"
    }

toupload = open("VPC.png", "rb")

files = { 
    "file" : ("VPC.png", toupload.read(), "application/octet-stream"),
    "json" : (None, json.dumps(payload), "application/json")
}

response = requests.request("POST", url,  headers=headers, files=files)

print(response.text)

這是我的Lambda函數中托管的代碼,該代碼接收HTTP請求,並基於該請求發送電子郵件(帶有附件):

    # get the system time when the request is received.
    time_received = datetime.now()

    # Get the incoming request body
    en = EmailNotification("n/a", "n/a", "n/a", time_received)

    try:

        req_body = request["body"]
        first_new_line = req_body.find("\r\n")
        req_boundary = req_body[:first_new_line]
        print(req_boundary)

        req_body_parts = req_body.split(req_boundary)

        message_body = req_body_parts[len(req_body_parts)-2]
        body_start = message_body.find("{")
        message_body = message_body[body_start:]
        file_data = req_body_parts[1]

        # process the request's main body to a EmailNotification object
        req_json = json.loads(message_body)
        requester = req_json["requester"]
        recipients = req_json["recipients"]
        subject = req_json["subject"]
        message = req_json["message"]

        en.set_requester(requester)
        en.set_recipients(recipients)
        en.set_subject(subject)
        en.set_message(message)

        print("Message Good")

        file_data_parts = file_data.split("\r\n")

        file_name_start = file_data_parts[1].find("filename=") + 10
        file_name = file_data_parts[1][file_name_start : len(file_data_parts[1]) - 1]
        print(file_name)

        # add the basic info of the attached file to the EmailNotification object
        filesize = -1
        filetype_start = file_data_parts[2].find("Content-Type: ") + 14
        filetype = file_data_parts[2][filetype_start : len(file_data_parts[2])]
        print(filetype)

        attach_obj = Attachment(file_name, filetype, filesize)
        en.set_attachment(attach_obj)

        print("creates attachment")

        # Prepare the email to send 
        msg = MIMEMultipart()
        msg['From'] = EmailNotification.SERVER_EMAIL_ACCOUNT
        msg['To'] = ','.join(en.get_recipients())
        msg['Subject'] = en.get_subject()

        # prepare the main message part of the email
        main_msg = MIMEText(en.get_message(),'plain')

        print("Creates message")

        # prepare the attachment part of the email
        content_type = filetype
        main_type = content_type.split("/")[0]
        sub_type = content_type.split("/")[1]

        binary_parts = []

        for part in file_data_parts[4:]:
            binary_parts.append(BytesIO((part.join("\r\n")).encode("utf-8")))

        print("reads contents")

        path = "/tmp/" + file_name
        target_file = open(path, "wb+")

        for item in binary_parts:
            target_file.write(item.read())

        target_file.close()
        print("WRITES")

        toupload = open(path, "rb")

        att_part = MIMEBase(main_type,sub_type)
        att_part.set_payload(toupload.read())
        encoders.encode_base64(att_part)
        att_part.add_header('Content-Disposition','attachment; filename={}'.format(file_name))

        toupload.close()

        print("ACTUALLY CREATES ATTACHMENT")

        # attach each sub part to the email message
        msg.attach(main_msg)
        msg.attach(att_part)

        print("ATTACHES PARTS TO MESSAGE")

        # Send the email according to SMTP protocol
        try:
            with smtplib.SMTP(SERVER, PORT) as server:
                print(server.ehlo())
                print(server.sendmail(SERVER_EMAIL_ACCOUNT, ','.join(en.get_recipients()), msg.as_string()))','.join(en.get_recipients()), msg.as_string()))
        except Exception as ex:
            print("FAILS IN EMAIL SENDING")
            en.log()
            response = prep_response(en)
            return response
        else:
            print("SUCCEEDS")
            los = []
            for i in range(len(en.get_recipients())):
                los.append(Status.SUCCESS)
            en.set_status(los)
            en.log()
            response = prep_response(en)
            # Send a HTTP response to the client
            return response

    except Exception as ex:

        print("FAILS! w/")
        print(ex)

        # catch exception during parsing the request received
        los = []
        for i in range(len(en.get_recipients())):
            los.append(Status.REQUEST_BODY_ERROR)
        en.set_status(los)
        en.log()
        response = prep_response(en)
        return response

此代碼返回的附件具有正確的名稱和文件類型,但不可打開,並且與原始文件相比具有不同的內容。 例如,如果我附加VPC.png(56kb),我會取回VPC.png(99kb)。

如果我查看文件的實際內容,則原始文件如下所示(只是一個示例):

‰PNG

IHDRé^)¸sRGB

隨附的版本如下所示(僅作為示例):

PNG

IHDR ^^)。sRGB

設法自己得到它。 我懷疑這是一個編碼問題。 發送附件文件之前,先在Base64中對其進行編碼,然后在Lambda中對其進行解碼就可以了。 似乎在將附件文件發送到Lambda之前未正確讀取附件文件,這導致了問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM