Creating a multi-part binary MIME message for an HTTP request in Python 3

I am trying to encode a binary with MIMEApplication in Python 3.3, as part of a multi-threaded MIME HTTP POST. I have a problem that the character 0x0d is interpreted as a new string 0xa, despite the fact that everything is set to binary bytes.

Here's a minimal test case with a binary string with 0x0d in it that got the wrong interpretation:

from email.encoders import encode_noop
from email.generator import BytesGenerator
from email.mime.application import MIMEApplication
import io

app = MIMEApplication(b'Q\x0dQ', _encoder=encode_noop)
b = io.BytesIO()
g = BytesGenerator(b)
g.flatten(app)
for i in b.getvalue()[-3:]:
    print("%02x " % i, end="")
print()

Exit: 51 0a 51when it should be51 0d 51

Note that this is necessary to create the binary part for the multi-page HTTP POST message.

0
source share
2 answers

, "" MIMEApplication, MIME:

from email.encoders import encode_noop
from email.generator import BytesGenerator
from email.mime.application import MIMEApplication
import io

# Actual binary "file" I want to encode (in real life, this is a file read from disk)
bytesToEncode = b'Q\x0dQ'

# unique marker that we can find and replace after message generation
binarymarker = b'GuadsfjfDaadtjhqadsfqerasdfiojBDSFGgg'

app = MIMEApplication(binarymarker, _encoder=encode_noop)
b = io.BytesIO()
g = BytesGenerator(b)
g.flatten(app, linesep='\r\n')  # linesep for HTTP-compliant header line endings

# replace the marker with the actual binary data, then you have the output you want!
body = b.getvalue().replace(binarymarker, bytesToEncode)

body , , :

b'Content-Type: application/octet-stream\r\nMIME-Version: 1.0\r\n\r\nQ\rQ'

, replace() .

0

( , base64 base64):

import email
from email.encoders import encode_noop
from email.generator import BytesGenerator
from email.mime.application import MIMEApplication
import io

app = MIMEApplication(b'Q\x0dQ')
b = io.BytesIO()
g = BytesGenerator(b)
g.flatten(app)
msg = email.message_from_bytes(b.getvalue())
assert msg.get_payload(decode=True) == b'Q\x0dQ'
+1

All Articles