2017-11-24 1 views
0

Es scheint mir, wie email.Message.as_bytes gebrochen:MIMEBase: Konvertierung in Bytes und zurück entfernt r in Binärdaten: Dokumentiertes oder nur gebrochenes Verhalten in Python 3?

import email 

from email.encoders import encode_7or8bit 
from email.mime.base import MIMEBase 

orig_data = b"Zeilenenden\n<Unix\r\n<DOS\rMac" 

msg = MIMEBase('application/octet-stream', "gzip") 

msg.set_payload(orig_data) 

encode_7or8bit(msg) 

print("orig_data = %r" % orig_data) 
print("payload = %r" % msg.get_payload(decode=1)) 

b = msg.as_bytes() 
msg2 = email.message_from_bytes(b) 
print("payload2 = %r" % msg2.get_payload(decode=1)) 

Der Ausgang

orig_data = b'Zeilenenden\n<Unix\r\n<DOS\rMac' 
payload = b'Zeilenenden\n<Unix\r\n<DOS\rMac' 
payload2 = b'Zeilenenden\n<Unix\n<DOS\nMac' 

Hinweis ist, wie die Nachrichtenkonvertierung> Bytes> Meldung des binären Nutzlast bricht. Diese

verwendet arbeitet mit ähnlichem Code in Python 2.

Ist das ein Bug oder sollte und wenn ja, wo es dokumentiert?

Antwort

0

Es scheint, dass mein Anwendungsfall mehr oder weniger invali ist ???

Offensichtlich verwendet Python 3 base64-Codierung für Binärdaten und unterstützt nicht die Übertragung von reinen Bytes.

Wie auch immer, durch einen Blick in den Quellcode des E-Mail-Pakets, kam ich auf der folgenden Abhilfe up:

import io 
import email 
import email.generator 

from email.encoders import encode_7or8bit 
from email.mime.base import MIMEBase 

orig_data = b"Zeilenenden\n<Unix\r\n<DOS\rMac" 

msg = MIMEBase('application/octet-stream', "gzip") 

msg.set_payload(orig_data) 

encode_7or8bit(msg) 

print("orig_data = %r" % orig_data) 
print("payload = %r" % msg.get_payload(decode=1)) 

class MyBytesGenerator(email.generator.BytesGenerator): 
    def _write_lines(self, lines): 
     self.write(lines) 

def as_bytes(msg, unixfrom=False, policy=None): 
    """Return the entire formatted message as a bytes object. 

    Optional 'unixfrom', when true, means include the Unix From_ envelope 
    header. 'policy' is passed to the BytesGenerator instance used to 
    serialize the message; if not specified the policy associated with 
    the message instance is used. 
    """ 
    from email.generator import BytesGenerator 
    policy = msg.policy if policy is None else policy 
    fp = io.BytesIO() 
    g = MyBytesGenerator(fp, mangle_from_=False, policy=policy) 
    g.flatten(msg, unixfrom=unixfrom) 
    return fp.getvalue() 

b = as_bytes(msg) 
msg2 = email.message_from_bytes(b) 
print("payload2 = %r" % msg2.get_payload(decode=1)) 

Mit diesem Problem zu umgehen, die as_bytes Funktion und email.message_from_bytes erlaubt die Nachricht im Binärformat übertragen ohne base64-overhead.