Design Decisions¶
This section is meant for those who are curious about why certain parts of Mailthon is designed the way it is, and should give you some idea on decisions which may seem quite weird at first.
The Postman Object¶
Usually most users would expect something like the following, where the envelope object itself knows how to send itself. After all, it’s an envelope, right? Before we start throwing buzzwords around consider a hypothetical Mailthon which looks like the following:
from hypmail.envelope import Envelope
Envelope(...).deliver(
host='smtp.google.com',
port=587,
auth=('username', 'password'),
)
Which, while convenient in some situations, just breaks down whenever you want to do something more complex. For example consider the following situations:
You want to send the same envelope using different servers or transport. Where should it go? I suppose you could do something like the following where the method calls are just replayed on each envelope:
env = Envelope(...) for server in servers: preparer[server](env) env.deliver(**options[server])
But then again you run into issues like “did I change this attribute before I delivered it?” Which ultimately leads to hard to find, hard to debug errors.
You want to send multiple envelopes but using the same server configuration and middleware. Once again this can be solved via some preparation functions:
for env in envelopes: prepare(env) env.deliver(**options)
Once again this leads to conceptual issues and practical issues. For example it is cumbersome to keep track of some configuration just to pass it to a method. Also it is extremely unweildly to have a giant Envelope class that does everything.
Unicode Headers¶
This design decision is in fact inspired by Werkzeug. Basically,
SMTP allows you to specify headers of different encodings, e.g.
UTF-8 headers for chinese characters in the subject field. While
the Message
objects allow you to pass in
unicode or byte strings, or even Header
objects as the header values- Mailthon chooses to pass in Unicode
values.
The background is simple- so that users writing special headers
do not need to worry about weird encoding problems that do not
usually show up until the time where you least expect them to.
Thus the UnicodeDict
class was born:
>>> from mailthon.helpers import UnicodeDict
>>> d = UnicodeDict()
>>> d['uni'] = u'unicode'
>>> d['uni']
u'unicode'
>>> d['key'] = b'value'
>>> d['key']
u'value'
Which automatically tries to decode bytes values into Unicode
strings. This makes development of Headers very painless; you
can pass in whatever value in Unicode- they will all look the
same and thus can be very easily programmed against. Also it
makes passing in a special mail_from
parameter to the
Envelope`
class simpler; you do
not need to worry about encoding since the Postman
object encodes it for you behind the scenes, using the
stringify_address()
function.