Send attached file with Mailgun using python

Question:

I’m trying to send an email with an attached file with the Mailgun API using requests.post.

In their documentation they alert that you must use multipart/form-data encoding when sending attachments, I’m trying this:

import requests
MAILGUN_URL = 'https://api.mailgun.net/v3/sandbox4f...'
MAILGUN_KEY = 'key-f16f497...'


def mailgun(file_url):
    """Send an email using MailGun"""

    f = open(file_url, 'rb')

    r = requests.post(
        MAILGUN_URL,
        auth=("api", MAILGUN_KEY),
        data={
            "subject": "My subject",
            "from": "[email protected]",
            "to": "[email protected]",
            "text": "The text",
            "html": "The<br>html",
            "attachment": f
        },
        headers={'Content-type': 'multipart/form-data;'},
    )

    f.close()

    return r


mailgun("/tmp/my-file.xlsx")

I’ve defined the header to be sure that the content type is multipart/form-data, but when I run the code, I get a 400 status with reason: Bad Request

What’s wrong? I need be sure that i’m using multipart/form-data and I’m using correctly the attachment parameter

Asked By: maoaiz

||

Answers:

You need to use the files keyword argument. Here is the documentation in requests.

And an example from the Mailgun documentation:

def send_complex_message():
    return requests.post(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
        auth=("api", "YOUR_API_KEY"),
        files=[("attachment", open("files/test.jpg")),
               ("attachment", open("files/test.txt"))],
        data={"from": "Excited User <YOU@YOUR_DOMAIN_NAME>",
              "to": "[email protected]",
              "cc": "[email protected]",
              "bcc": "[email protected]",
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!",
              "html": "<html>HTML version of the body</html>"})

So modify your POST to:

r = requests.post(
    MAILGUN_URL,
    auth=("api", MAILGUN_KEY),
    files = [("attachment", f)],
    data={
        "subject": "My subject",
        "from": "[email protected]",
        "to": "[email protected]",
        "text": "The text",
        "html": "The<br>html"
    },
)

This should work fine for you.

Answered By: That1Guy