Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SOLVED] How to send files and data in the same request #3571

Closed
sevaho opened this issue Jan 22, 2019 · 8 comments
Closed

[SOLVED] How to send files and data in the same request #3571

sevaho opened this issue Jan 22, 2019 · 8 comments

Comments

@sevaho
Copy link

sevaho commented Jan 22, 2019

Long story short

I want to send files (binary data) and json data in the same request but failing to grasp the documentation or see any examples in github issues.

Expected behaviour

Send file(s) and post data

Actual behaviour

It doesn't seem to include post parameters

Steps to reproduce

attachment = open("/tmp/some.pdf", "rb")

mailgun_data = {
    "from": "test@test.com",
    "to": "sebastiaan@sevaho.io",
    "subject": "testje",
    "html": "testje",
}

async def main():
    auth = aiohttp.BasicAuth(login="api", password=API_MAILGUN)
    try:
        async with aiohttp.ClientSession(auth=auth) as session:
            with aiohttp.MultipartWriter("mixed") as mpwriter:

                mpwriter.append(attachment, {"Content-Type": "multipart/form-data"})
                mpwriter.append_json(mailgun_data)

                async with session.post(
                    f"https://api.mailgun.net/v3/{ API_MAILGUN_DOMAIN }/messages",
                    data=mpwriter,
                ) as resp:
                    response = await resp.text()
                    print(response)

    except Exception as e:
        print(e)
        raise Exception("something went wrong while sending email")


asyncio.run(main())

output:

{
  "message": "'from' parameter is missing"
}

without the file the request works.

Your environment

I use aiohttp client, on arch linux 4.20.3 aiohttp version: 3.4.4

@aio-libs-bot
Copy link

GitMate.io thinks the contributor most likely able to help you is @asvetlov.

Possibly related issues are #1651 (request.files in addition to request.data), #1155 (how-to retrieve the data (body) in aiohttp server from requests.get), #1469 (Request.post() stores data in temp files), #3034 (Multipart file form data with name), and #370 (Server closes connection before sending data).

@sevaho
Copy link
Author

sevaho commented Jan 22, 2019

I guess it's more something like this, but still does not work:

        async with aiohttp.ClientSession(auth=auth) as session:
            with aiohttp.MultipartWriter("mixed") as mpwriter:
                with aiohttp.MultipartWriter("related") as subwriter:
                    subwriter.append(
                        attachment, {"Content-Type": "multipart/form-data"}
                    )
                mpwriter.append(subwriter)
                with aiohttp.MultipartWriter("related") as subwriter:
                    subwriter.append_json(
                        mailgun_data, {"Content-Type": "application/json"}
                    )
                mpwriter.append(subwriter)

                async with session.post(
                    f"https://api.mailgun.net/v3/{ API_MAILGUN_DOMAIN }/messages",
                    data=mpwriter,
                ) as resp:
                    response = await resp.text()
                    print(response)

@asvetlov
Copy link
Member

Sorry, I'm not familiar with MailGun API.
Maybe our multipart expert @kxepal can provide more information?

@kxepal
Copy link
Member

kxepal commented Jan 22, 2019

Well, your first example is quite correct, but it seems like there is some MailGun API specifics. According their examples, there should be something like:

with aiohttp.MultipartWriter("form-data") as mp:
  for key, value in mailgun_data.items():
    part = mp.append(value)
    part.set_content_disposition('form-data', name=key)
  mp.append(attachment)

@sevaho
Copy link
Author

sevaho commented Jan 22, 2019

Thank you for the reply,

the requests example that works look like:

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

if it helps.

It still didn't work with the above example but I keep digging.

@kxepal
Copy link
Member

kxepal commented Jan 22, 2019

Well, I took curl example, dump what it really sends and tried to reimplement the same payload with aiohttp. But honestly, didn't checked the result. But it looks like as sequential, without any nesting.

@asvetlov
Copy link
Member

Can we close it?

@sevaho
Copy link
Author

sevaho commented Feb 3, 2019

yes

@sevaho sevaho closed this as completed Feb 3, 2019
@sevaho sevaho changed the title How to send files and data in the same request [SOLVED] How to send files and data in the same request Feb 3, 2019
@lock lock bot added the outdated label Feb 3, 2020
@lock lock bot locked as resolved and limited conversation to collaborators Feb 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants