

Envelopes - Python email for humans - RobSpectre
http://tomekwojcik.github.io/envelopes/

======
ghc
If this works as well as Python's requests library, then you are my hero. I
_hate_ dealing with email in Python, because the standard library interfaces
to email are horrible.

I have a have a project that could use this _now_ , so I will give it a shot.
I will report back with my findings.

~~~
fsckin
Anyone who calls their project "Library_Name for Humans" has big shoes to
fill. Looking at the examples, it appears to be exactly that.

~~~
Chris2048
perhaps there should be an official group for 'for humans' projects?

------
ianstormtaylor
From an API standpoint:

(1) I feel like sending emails isn't a task that's going to be repeated
endlessly across a codebase, so is it really necessary to save three
characters by truncating "from_address" to "from_addr"? You lose clarity for
very little gain.

(2) If truncating the above was so important, why is it "text_body" instead of
just plain "body"? In this case, you'd lose almost no clarity.

I prefer APIs to not have unnecessarily abbreviated words—especially when,
realistically, I'm going to type them once per file.

(Sorry, pet peeve.)

~~~
ihuman
It is called text_body because there is also an html_body.

[http://tomekwojcik.github.io/envelopes/api/envelope.html](http://tomekwojcik.github.io/envelopes/api/envelope.html)

~~~
ianstormtaylor
Ah good call. Maybe it's just my very maleable Javascript side talking, but if
I were making this API in Javascript I'd probably have a "body" and do a super
simple check if the first character is a "<", which will solve the 99.999%
case for HTML vs. text emails.

~~~
ihuman
But then your emails can't have HTML and a plaintext backup.

~~~
ianstormtaylor
Ah I should have clarified that "body" would be a shorthand of sorts. I'd
still have an "html" and "text" alternative to satisfy the case where you want
to set both, and in that case "text" and "html" are very meaningful. But the
"body" makes the simple case, and the examples extremely clean too.

------
habitue
I feel I should mention Mailer

[https://pypi.python.org/pypi/mailer](https://pypi.python.org/pypi/mailer)

I think everyone who has ever used the python standard library email modules
has had the thought "Well, if I just made a small wrapper around this... it
wouldn't be so bad"

And just about everyone who thought that did it.

------
codegeek
Looks pretty good. Being a Flask user, happy to see the flask example as well.
Would definitely try and use it in side projects of mine. You open to any
forks and/or pull requests ?

~~~
dignan
As a Flask user, you might want to check out Flask-Mail
[http://pythonhosted.org/flask-mail/](http://pythonhosted.org/flask-mail/)

~~~
codegeek
Thx. I know of flask-mail already. Just wanted to see how different would the
"envelopes" be .

------
tghw
If they can add IMAP, POP, possibly Exchange, and good email parsing (it's
truly a pain in the ass to do yourself) this will be a killer library.

~~~
anonymoushn
I'd also be interested in an email parsing library for Python. Last time I
used Twisted to read email the parser was completely worthless and could not
be fixed other than by rewriting it from scratch.

------
topherjaynes
Nice wrapper, though it took me a while to get it to work. Tried with Google
SMTP, but ended up throwing Sendgrid on a heroku app and hit that api.

Wondering if a debug mode would be helpful for the initial set up. See what
requests are being sent/received to see what the possible errors are.

~~~
tomekwojcik
Debug mode is a nice catch. Thanks.

As far as GMail SMTP goes, I've been using Envelopes over GMail SMTP for about
a week with great success. The first example in the docs shows just that.
Also, I have customized SMTP subclasses for GMail, SendGrid and local
Mailcatcher in the pipeline. Using one of them, you'll only have to provide
your creds to send e-mails.

------
omaranto
What is the advantage of having an Envelope class? Why not just have a send
function?

~~~
YokoZar
Maybe so you can more deliberately build different parts of the email in
different parts of the code without having to create your own set of variables
for that.

~~~
TemporalAnomaly
I find it a little weird that you would create the email in one part of the
code and then send it somewhere else though. The only advantage I can think
off is something like falling back to another connection if the primary one
fails. But it's strange to support reuse of messages while at the same time
not being able to reuse a connection.

Why not have a set of classes for flexibility and simple helper functions for
the most common cases? Requests is so great to use because the API matches the
expectations of its users (how do I make a GET request? oh, use the get
function...) and I think for email a single send function does what people
want most of the time.

send( 'smtp.googlemail.com', login='from@example.com', password='password',
from_address=u'from@example.com', from_name=u'From Example',
to_address=u'to@example.com', to_name=u'To Example', subject=u'Envelopes
demo', text=u"I'm a helicopter!" )

connection = Connection( 'smtp.googlemail.com', login='from@example.com',
password='password' )

message = Envelope( from_address=u'from@example.com', from_name=u'From
Example', to_address=u'to@example.com', to_name=u'To Example',
subject=u'Envelopes demo', text=u"I'm a helicopter!" )

message.add_attachment('/Users/bilbo/Pictures/helicopter.jpg')

connection.send(message)

~~~
tomekwojcik
envelopes.conn.SMTP is a wrapper for smtplib.SMTP that supports Envelope
objects and is reusable. Envelope.send() is just a shorthand you can use if
you don't care about reusing connections.

For requests it's simpler to support top-level functions, since in general
HTTP request is self-contained. Envelope (or email.mime.MIMEMessage) object
isn't enough to send an e-mail - you need to know the SMTP host, port, creds
and set up the connection. While it's certainly possible to write
envelopes.send() function that'd internally create an Envelope object and send
it (all based on the args the function gets) I don't think it's that crucial.

------
ajaxaddicted
Envelopes looks very good for sending emails and for reading emails there is
another cool library - Imbox
[https://github.com/martinrusev/imbox](https://github.com/martinrusev/imbox)

------
bobbyi_settv
We use boto to send email via Amazon's Simple Email Service and it is fairly
simple. SES allows you to send up to 2000 emails per day for free.

~~~
jp_sc
Would you be willing to collaborate a SES mailer wrapper for this similar
project?
[https://github.com/lucuma/MailShake](https://github.com/lucuma/MailShake)

------
gpsarakis
Seems really nice with a first glance. Are you considering any Django support
in the future?

~~~
mattoc
Django's Email API is already pretty solid, see the EmailMessage[0] class.
Attachments and multiple MIME types are handled for sending text & html
versions of the email body.

However, given that Django is just Python there's nothing precluding you from
using the library as a drop-in replacement.

[0]
[https://docs.djangoproject.com/en/dev/topics/email/#emailmes...](https://docs.djangoproject.com/en/dev/topics/email/#emailmessage-
objects)

