email: Stub out send_imap()

Arun Persaud suggested IMAP as an additional email delivery mechanism.
The benefit of using IMAP over SMTP is that you can set the target
mailbox directly (instead of filtering the incoming mail with procmail
or a similar external tool).  This commit restructures the 'send'
configuration to support IMAP output with a configurable mailbox.
That means you can do something like:

  [DEFAULT]
  email-protocol: imap
  imap-auth: True
  imap-username: myname
  imap-password: mypass
  imap-server: imap.yourisp.net
  imap-port: 993
  imap-ssl: True

  [feed.rss2email]
  url = http://www.allthingsrss.com/rss2email/feed/
  imap-mailbox = rss2email

  [feed.xkcd]
  url = http://xkcd.com/atom.xml
  imap-mailbox = xkcd

For non-IMAP users, note that the boolean `use-smtp` configuration
variable is gone, replaced by the more flexible `email-protocol`.
You'll want to replace:

  use-smtp = False

with:

  email-protocol = sendmail

and replace:

  use-smtp = True

with:

  email-protocol = smtp

Signed-off-by: W. Trevor King <wking@tremily.us>
email: small fixes for using imap as a backend

* fixed two typos in "def send"
* removed some unecessary calls to imap.connect and
  imap.close (which seems to be only needed in case you open
  a mailbox, which we don't)

Signed-off-by: Arun Persaud <apersaud@lbl.gov>
Add configurable post-process hooks

On Mon, Jan 21, 2013 at 11:16:58PM -0800, Arun Persaud wrote:
> but I was wondering if there is any chance to add some hooks, so
> that the user can modify the feed before it gets send, something
> that takes the url, uid, and other interesting information and
> returns the body of the feed that should get emailed.

This is not quite what he asked for (e.g., I don't pass the URL
explicitly, the hook should return the full message instead of just
payload, ...), but I think it get's the job done.

Signed-off-by: W. Trevor King <wking@tremily.us>
post_process: add documentation and a prettify example

* also mention it in the README file.
* package the filter via setup.py

Signed-off-by: Arun Persaud <apersaud@lbl.gov>
README: Update the link to the NetBSD package

Although they're still packaging rss2email-2.71nb2.  I'll see if I can
dig up a maintainer to ping about that.

Signed-off-by: W. Trevor King <wking@tremily.us>
rss2email/post_process/downcase.py: Move my test hook into Arun's directory

All the built-in hooks should live in the same sub-package.  The
`post_process` name Arun used is more descriptive than my `hook`, so
move my downcase code there.

Signed-off-by: W. Trevor King <wking@tremily.us>
Merge branch 'post-process'

* post-process:
  rss2email/post_process/downcase.py: Move my test hook into Arun's directory
  post_process: add documentation and a prettify example
  Add configurable post-process hooks

Signed-off-by: W. Trevor King <wking@tremily.us>
CHANGELOG: Update with summary of post-process addition

Documenting:
3a331d6 Merge branch 'post-process'

Signed-off-by: W. Trevor King <wking@tremily.us>
.update-copyright.conf: Use aliases to remove Aaron Swartz's email

Not much use in sending email to the deceased :(.

Signed-off-by: W. Trevor King <wking@tremily.us>
Run update-copyright.py

Signed-off-by: W. Trevor King <wking@tremily.us>
feed: Add the digest setting for multi-entry email

For high-volume feeds, some users want to receive a single email per
Feed.run() instead of a separate email for each new entry in the feed.
If you enable the new digest setting, the per-entry messages are
packed into a single multipart/digest message instead of being mailed
individually.  The MIME details for digests are spelled out in RFC
2046 [1].

Peripheral changes:
* Added rss2email.feed._USER_AGENT, to get version information into
  the User-Agent message headers and to avoid repeating myself.
* Normalize multipart MIME boundaries for easier testing of
  multipart/digest messages.

[1]: http://tools.ietf.org/html/rfc2046#section-5.1.5

Signed-off-by: W. Trevor King <wking@tremily.us>
feed: Add the digest-post-process setting

For users that want to manipulate the multi-entry message.  For
example, if the stock `digest for <feed.name>` title doesn't cut it
for you, you can now use a post-processing hook to set the title
however you like.

Signed-off-by: W. Trevor King <wking@tremily.us>
email: Remove debugging logging from _decode_header()

This was accidentally committed in e08e198 (email: Decode headers when
checking .as_string() flatten fallback, 2013-02-17).

Signed-off-by: W. Trevor King <wking@tremily.us>
Merge branch 'imap'

* imap:
  email: small fixes for using imap as a backend
  email: Stub out send_imap()

Signed-off-by: W. Trevor King <wking@tremily.us>
CHANGELOG: Update with summary of IMAP delivery addition

Documenting:
a7f2222 Merge branch 'imap'

Signed-off-by: W. Trevor King <wking@tremily.us>
email: Pass 'config' and 'section' through from send() to *_send()

Otherwise only the default configuration will be used, which is almost
certainly not what the user wants.

Signed-off-by: W. Trevor King <wking@tremily.us>
Bump to version 3.4

Signed-off-by: W. Trevor King <wking@tremily.us>
config: Replace Config._setup() with Config.setup_html2text()

Since 7bbbf62 (Setup html2text in Config._setup(), 2012-10-04), the
html2text configuration options have only been referenced from
Config._setup(), and that method was never called.  With this commit,
we rename the method to setup_html2text(), and add a new
Feed._html2text() which invokes the setup before calling
html2text.html2text().

This caused a fair amount of churn in the expected test results, as
previously ignored default values for html2text kicked in.  I also
added a test exercising the non-default values (allthingsrss/3), and
it looks like everything works as expected.

Signed-off-by: W. Trevor King <wking@tremily.us>
README: Link to Fedora package

Also remove 'Linux' from distribution names.  The goal is to point
folks using $DISTRO to their package, not to give details about the
technical underpinnings of a given distribution.

I've sorted the distributions by packaging format: deb, rpm, ebuild,
and Makefile.

Signed-off-by: W. Trevor King <wking@tremily.us>
command: Fix opmlexport crash due to orphaned feed data

When you remove a feed from your config file by hand, you might leave
the dynamic 'seen' data in the JSON data file by accident.  If you
have such orphan data, the feed is loaded by Feeds._load_feeds() with
the default configuration (since you removed the config file entry).
This can lead to opmlexport errors like:

  Traceback (most recent call last):
    File "./r2e", line 5, in <module>
      rss2email.main.run()
    File "/.../rss2email/rss2email/main.py", line 163, in run
      args.func(feeds=feeds, args=args)
    File "/.../rss2email/rss2email/command.py", line 157, in opmlexport
      url = _saxutils.escape(feed.url)
    File "/usr/lib64/python3.2/xml/sax/saxutils.py", line 34, in escape
      data = data.replace("&", "&amp;")
  AttributeError: 'NoneType' object has no attribute 'replace'

because the feeds lack the per-feed 'url' setting that had been
defined in the config file.  With this commit, opmlexport drops these
URL-less feeds, instead of choking to death trying to format them ;).

Signed-off-by: W. Trevor King <wking@tremily.us>