带有 Pub/Sub 触发器的云函数无法将电子邮件附件保存到云存储

问题描述 投票:0回答:1

我正在构建一个带有 Pub/Sub 触发器的 Google Cloud Function 来处理电子邮件附件。该函数应该将允许的电子邮件地址中的附件保存到指定的 Cloud Storage 存储桶中。

虽然 Pub/Sub 触发器工作并且日志确认函数调用,但没有附件被保存到存储桶中。此外,在某些情况下,即使测试电子邮件中包含有效附件,功能日志也会显示“电子邮件中未找到有效附件”。

设置详情 云功能:

触发器:Pub/Sub 主题 运行时:Python 3.9 权限:所有相关角色(云函数调用者、Pub/Sub 发布者、存储管理员)均已授予关联的服务帐户。 发布/订阅主题:

使用默认设置创建的主题(添加订阅、拉取传递类型、7 天消息保留)。 预期流量:

电子邮件附件通过 Pub/Sub 消息接收。 函数处理 Pub/Sub 消息,验证发件人和主题,并将附件保存到指定的 Cloud Storage 存储桶。 当前观察:

Pub/Sub消息发布成功,函数日志显示调用情况。 但是,没有附件保存到存储桶中。 在某些情况下,尽管发送了有效附件,但日志仍显示“在电子邮件中找不到有效附件”。 有时,电子邮件会因未送达而被退回,日志中没有进一步的错误详细信息。

供参考的代码片段 这是该函数的代码。任何识别问题的反馈或建议将不胜感激:

@functions_framework.cloud_event
def handle_email_attachment(cloud_event):
    """Handles email attachments sent via Pub/Sub."""
    try:
        pubsub_message = base64.b64decode(cloud_event.data["message"]["data"]).decode("utf-8")
        email_message = message_from_bytes(base64.b64decode(pubsub_message))

        # Extract sender, recipient, and subject
        sender_email = email_message.get("from", "").strip()
        recipient_email = email_message.get("to", "").strip()
        subject = email_message.get("subject", "").strip()

        # Validate sender email
        if sender_email not in ALLOWED_EMAILS:
            print(f"Email from {sender_email} is not allowed. Ignoring.")
            return

        # Process attachments
        for part in email_message.walk():
            if part.get_content_maintype() == 'multipart':
                continue
            if part.get('Content-Disposition') is None:
                continue

            file_name = part.get_filename()
            file_data = part.get_payload(decode=True)
            if file_name:
                save_to_storage(sender_email, file_name, file_data)

    except Exception as e:
        print(f"Error processing email attachment: {e}")

def save_to_storage(sender_email, file_name, file_data):
    """Save the attachment to Cloud Storage."""
    folder_name = sender_email.replace("@", "at").replace(".", "_")
    bucket = storage_client.bucket(ATTACHMENT_BUCKET)
    blob = bucket.blob(f"{folder_name}/{file_name}")
    blob.upload_from_string(file_data)
    print(f"File {file_name} uploaded to folder {folder_name} in bucket {ATTACHMENT_BUCKET}.")

发布/订阅消息结构:

正确处理电子邮件附件是否需要特定的 Pub/Sub 消息结构?

电子邮件验证:

Gmail 或其他域等电子邮件提供商触发的 Pub/Sub 消息中的“发件人”或“收件人”字段格式是否不同?

附件处理:

是否有必须在云函数中显式处理的特定内容类型(例如,text/csv、application/vnd.ms-excel)?

测试环境:

调试 Pub/Sub 触发的云功能是否需要额外的步骤,特别是附件处理?

python google-cloud-platform google-cloud-functions google-cloud-pubsub
1个回答
0
投票

据我了解,您正在尝试将电子邮件附件保存到特定的 Google Cloud Storage,但没有附件保存到存储桶中。

您首先需要考虑的是关联服务帐号所需的权限角色,以便在 Cloud Storage 存储桶中创建对象或验证该函数对 Cloud Storage 存储桶具有正确的权限。仔细检查存储对象管理员等角色或至少存储对象创建者

回答您的问题:

正确处理电子邮件附件是否需要特定的 Pub/Sub 消息结构?

Gmail 或其他域等电子邮件提供商触发的 Pub/Sub 消息中的“发件人”或“收件人”字段格式是否不同?

  • 是的,Gmail 通常会按预期在其标头中包含 FromToSubject,而对于其他标头,它们具有独特的标头和编码方式,尤其是在使用自定义格式或标头时。

是否有必须在云函数中显式处理的特定内容类型(例如text/csv、application/vnd.ms-excel)?

  • 是的,您当前的代码不会检查附件的特定内容类型(例如应用程序/pdf、图像/jpeg)。如果您想按类型过滤附件(仅保存PDF或图像),可以修改代码以在保存文件之前检查

    part.get\_content\_type()

    if part.get_content_type() == 'application/pdf':
        # Only save PDF attachments
        file_name = part.get_filename()
        file_data = part.get_payload(decode=True)
        save_to_storage(sender_email, file_name, file_data)
    

调试 Pub/Sub 触发的云函数(特别是附件处理)是否需要额外的步骤?

  • 利用 Cloud Run Function 中的 logging,使用 print() 语句来记录解析的电子邮件字段、附件详细信息(如文件名)以及遇到的任何错误。确保处理电子邮件的每一步都记录完整。

例如:

print(f"Attachment found: {file_name}, Content-Type: {part.get_content_type()}")
© www.soinside.com 2019 - 2024. All rights reserved.