Python Sendgrid发送带有PDF附件的电子邮件。

15
我正在尝试在使用SendGrid发送的电子邮件中附加PDF文件。
这是我的代码:

I'm trying to attach a PDF file to my email sent with sendgrid.

Here is my code :

sg = sendgrid.SendGridAPIClient(apikey=os.environ.get('SENDGRID_API_KEY'))

from_email = Email("from@example.com")
subject = "subject"
to_email = Email("to@example.com")
content = Content("text/html", email_body)

pdf = open(pdf_path, "rb").read().encode("base64")
attachment = Attachment()
attachment.set_content(pdf)
attachment.set_type("application/pdf")
attachment.set_filename("test.pdf")
attachment.set_disposition("attachment")
attachment.set_content_id(number)

mail = Mail(from_email, subject, to_email, content)
mail.add_attachment(attachment)

response = sg.client.mail.send.post(request_body=mail.get())

print(response.status_code)
print(response.body)
print(response.headers)

但是Sendgrid Python库遇到了一个“HTTP错误400:坏请求”的错误。

我的代码有什么问题?


你能否使用https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/sandbox_mode.html检查请求是否有效? - WannaBeCoder
我认为问题出在base64那一行。如果我像这里https://github.com/sendgrid/sendgrid-python/blob/ca96c8dcd66224e13b38ab8fd2d2b429dd07dd02/examples/helpers/mail/mail_example.py#L66设置内容,它就可以工作。但是当我使用我的base64编码的pdf文件时,我遇到了错误。 - John
5个回答

21

我找到了一个解决方案。我替换了这行代码:

pdf = open(pdf_path, "rb").read().encode("base64")

通过这样做:

with open(pdf_path, 'rb') as f:
    data = f.read()

encoded = base64.b64encode(data)

现在它可以工作了。我可以在set_content中发送编码文件:

attachment.set_content(encoded)

注意:上面的答案适用于Sendgrid v2或更低版本。对于v3及以上版本,请使用以下内容:

encoded = base64.b64encode(data).decode()

12
顺便提一句,由于离开with语句时文件会关闭,因此您无需使用f.close() - elgehelge

12

这是我的解决方案,适用于Sendgrid V3

    # Where it was uploaded Path.
    file_path = "MY_FILE_PATH"

    with open(file_path, 'rb') as f:
        data = f.read()

    # Encode contents of file as Base 64
    encoded = base64.b64encode(data).decode()

    """Build attachment"""
    attachment = Attachment()
    attachment.content = encoded
    attachment.type = "application/pdf"
    attachment.filename = "my_pdf_attachment.pdf"
    attachment.disposition = "attachment"
    attachment.content_id = "PDF Document file"

    sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)

    from_email = Email("origin@gmail.com")
    to_email = Email('recipient@gmail.com')
    content = Content("text/html", html_content)

    mail = Mail(from_email, 'Attachment mail PDF', to_email, content)
    mail.add_attachment(attachment)

    try:
        response = sg.client.mail.send.post(request_body=mail.get())
    except urllib.HTTPError as e:
        print(e.read())
        exit()

11
直接引用Sendgrid文档:

Sendgrid docs

import urllib.request as urllib
import base64
import os
import json
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import (Mail, Attachment, FileContent, FileName, FileType, Disposition, ContentId)

import os
import json
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

message = Mail(
    from_email='from_email@example.com',
    to_emails='to@example.com',
    subject='Sending with Twilio SendGrid is Fun',
    html_content='<strong>and easy to do anywhere, even with Python</strong>')
file_path = 'example.pdf'
with open(file_path, 'rb') as f:
    data = f.read()
encoded = base64.b64encode(data).decode()
attachment = Attachment()
attachment.file_content = FileContent(encoded)
attachment.file_type = FileType('application/pdf')
attachment.file_name = FileName('test_filename.pdf')
attachment.disposition = Disposition('attachment')
attachment.content_id = ContentId('Example Content ID')
message.attachment = attachment
try:
    sendgrid_client = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
    response = sendgrid_client.send(message)
    print(response.status_code)
    print(response.body)
    print(response.headers)
except Exception as e:
    print(e.message)

5
现在这个文件里有我的代码,因为他们拿走了我的代码。我因此得到了奖励,他们给了我一些SendGrid的东西以表彰我的贡献^^ - John
如何在一条消息中附加多个文件?“无法设置属性'attachments'”。 - Vishal
嗨,我将尝试使用此方法发送带附件的电子邮件,ContentID应该填什么? - Jakhongir Alikhanov

1

如何在一条消息中添加多个文件?

构建附加的附件:

file_path = 'test_filename1.pdf'
with open(file_path, 'rb') as f:
    data = f.read()
    f.close()
encoded = base64.b64encode(data).decode()
attachment1 = Attachment()
attachment1.file_content = FileContent(encoded)
attachment1.file_type = FileType('application/pdf')
attachment1.file_name = FileName('test_filename1.pdf')
attachment1.disposition = Disposition('attachment')
attachment1.content_id = ContentId('Example Content ID1')

file_path = 'test_filename2.pdf'
with open(file_path, 'rb') as f:
    data = f.read()
    f.close()
encoded = base64.b64encode(data).decode()
attachment2 = Attachment()
attachment2.file_content = FileContent(encoded)
attachment2.file_type = FileType('application/pdf')
attachment2.file_name = FileName('test_filename2.pdf')
attachment2.disposition = Disposition('attachment')
attachment2.content_id = ContentId('Example Content ID2')

mail.attachment = [attachment1,attachment2]

0

以下方法对我有效:

    mail = Mail(
        from_email=SendgridEmail(from_email_str),
        to_emails=[To(e) for e in to_emails],
        subject=email_subject,
        html_content=HtmlContent(email_html_content)
    )
    attachment = Attachment(
        file_content=file_content_b64_encoded,
        file_name=filename,
        file_type=file_type,
        disposition='attachment',
        content_id=filename
    )
    mail.add_attachment(attachment)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接