The email package consists of two major conceptual pieces: the API, and the internal data model. The API needs to have facilities for accepting data in either text format or bytes format, and this data is used to generate a model of the input message (a Message). Likewise the API needs to provide facilities for serializing a Message as either bytes or text. The API also provides ways to build up a Message from pieces, or to extract information from a Message in pieces, and to modify a Message, and again input and output as both text and bytes must be supported, except that in some cases text output may not make sense (eg: binary attachments).
The data model used by the email package is an "implementation detail", and we should not spend effort at this stage trying to optimize it for anything except memory requirements with respect to potentially large sub-objects, and even there it is more a matter of providing ways to deal with potentially large sub-objects than it is a true optimization. In general correctness and robustness is much more important than speed.
The data model will need to be a practical hybrid of the input data, possibly transformed in some way in some cases, and various sorts of meta-data. The current email package already works this way.
An important characteristic of the model is that it be invertable whenever sensible; that is, if a given byte stream is used to create a Message or subobject, serializing that Message or subobject as bytes should return the original byte stream whenever sensible (ie: when the data is not pathologically malformed). Likewise if a text stream is used to create a Message or subobject, serializing it as text should produce, whenever sensible, the original text stream. In particular, well-formed (per RFC) message data should always come out of a round trip through the email module in exactly the format it went in.
An important property of the API is that both the parser that transforms an input stream into a Message and Message serialization should not raise exceptions. Instead a defects list is maintained and exposed through the API. In the face of some defects it may not be sensible to maintain invertability. In the worst case for parser input the resulting Message object may have no headers, a binary blob body, and a defect list, but a Message object will always be produced.
The APIs that manipulate the data model either for piecewise construction or for transformations may raise exceptions, and in most cases should raise exceptions when encountering invalid data or operations. APIs that query the model should return as much information as possible without throwing an exception. (The current proposal to implement this is to return objects that have defect lists, and/or raise exceptions when methods of the object are called that would have worked if the input data were valid, leaving the queryable object itself in the hands of the application so that the application has the maximum possible information available to try to handle the error if it wishes to do so.)