Add configurable post-process hooks
authorW. Trevor King <wking@tremily.us>
Tue, 22 Jan 2013 16:59:36 +0000 (11:59 -0500)
committerW. Trevor King <wking@tremily.us>
Wed, 10 Apr 2013 19:24:41 +0000 (15:24 -0400)
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>
rss2email/config.py
rss2email/feed.py
rss2email/hook.py [new file with mode: 0644]
rss2email/util.py
test/allthingsrss/2.config [new file with mode: 0644]
test/allthingsrss/2.expected [new file with mode: 0644]

index 0daa9799bb37417f0d7945b6ae43e09c50bd6a5e..2b9471986582a2b5a55d77c9247f5d9501537666 100644 (file)
@@ -92,6 +92,9 @@ CONFIG['DEFAULT'] = _collections.OrderedDict((
         # characters, we iterate through the list below and use the
         # first character set that works.
         ('encodings', 'US-ASCII, ISO-8859-1, UTF-8, BIG5, ISO-2022-JP'),
+        # User processing hooks.  Note the space after the module name.
+        # Example: post-process = 'rss2email.hook downcase_message'
+        ('post-process', ''),
         ## HTML conversion
         # True: Send text/html messages when possible.
         # False: Convert HTML to plain text.
index 9a1c70974b0dfdf9cbaff647d8ac69de1fdf56cb..d3ce1cdfd93e638c26a667bb6036b9a5775e2069 100644 (file)
@@ -181,6 +181,10 @@ class Feed (object):
         'encodings',
         ]
 
+    _function_attributes = [
+        'post_process',
+        ]
+
     def __init__(self, name=None, url=None, to=None, config=None):
         self._set_name(name=name)
         self.reset()
@@ -262,8 +266,12 @@ class Feed (object):
         self.__dict__.update(data)
 
     def _get_configured_option_value(self, attribute, value):
-        if value and attribute in self._list_attributes:
+        if value is None:
+            return ''
+        elif attribute in self._list_attributes:
             return ', '.join(value)
+        elif attribute in self._function_attributes:
+            return _util.import_name(value)
         return str(value)
 
     def _get_configured_attribute_value(self, attribute, key, data):
@@ -273,6 +281,10 @@ class Feed (object):
             return data.getint(key)
         elif attribute in self._list_attributes:
             return [x.strip() for x in data[key].split(',')]
+        elif attribute in self._function_attributes:
+            if data[key]:
+                return _util.import_function(data[key])
+            return None
         return data[key]
 
     def reset(self):
@@ -320,7 +332,14 @@ class Feed (object):
             _LOG.debug('processing {}'.format(entry.get('id', 'no-id')))
             processed = self._process_entry(parsed=parsed, entry=entry)
             if processed:
-                yield processed
+                guid,id_,sender,message = processed
+                if self.post_process:
+                    message = self.post_process(
+                        feed=self, parsed=parsed, entry=entry, guid=guid,
+                        message=message)
+                    if not message:
+                        continue
+                yield (guid, id_, sender, message)
 
     def _check_for_errors(self, parsed):
         warned = False
diff --git a/rss2email/hook.py b/rss2email/hook.py
new file mode 100644 (file)
index 0000000..45542d5
--- /dev/null
@@ -0,0 +1,40 @@
+# Copyright
+
+"""Useful hooks for post processing messages
+
+Along with some less useful hooks for testing the post-processing
+infrastructure.  The hook, when set, is called by ``Feed._process()``
+with the following keyword arguments:
+
+feed:
+  The ``rss2email.feed.Feed`` instance that generated the message.
+parsed:
+  The parsed feed as returned by ``feedparser.parse``
+entry:
+  The entry from ``parsed`` that lead to the current message.
+guid:
+  The feed's view of the identity of the current entry.
+message:
+  The ``email.message.Message`` instance that rss2email would send if
+  the post-processing hook were disabled.
+
+Post processing hooks should return the possibly altered message, or
+return ``None`` to indicate that the message should not be sent.
+"""
+
+def _downcase_payload(part):
+    if part.get_content_type() != 'text/plain':
+        return
+    payload = part.get_payload()
+    part.set_payload(payload.lower())
+
+def downcase_message(message, **kwargs):
+    """Downcase the message body (for testing)
+    """
+    if message.is_multipart():
+        for part in message.walk():
+            if part.get_content_type() == 'text/plain':
+                _downcase_payload(part)
+    else:
+        _downcase_payload(message)
+    return message
index f707dcb84323039f1c90daeb26365a34246e4681..dc087d095e7f1e4330e8c95a60de5244deb4de34 100644 (file)
@@ -17,6 +17,9 @@
 """Odds and ends
 """
 
+import importlib as _importlib
+import pickle as _pickle
+import pickletools as _pickletools
 import sys as _sys
 import threading as _threading
 
@@ -74,3 +77,65 @@ class TimeLimitedFunction (_threading.Thread):
         elif self.isAlive():
             raise _error.TimeoutError(time_limited_function=self)
         return self.result
+
+
+def import_name(obj):
+    """Return the full import name for a Python object
+
+    Note that this does not always exist (e.g. for dynamically
+    generated functions).  This function does it's best, using Pickle
+    for the heavy lifting.  For example:
+
+    >>> import_name(import_name)
+    'rss2email.util import_name'
+
+    Note the space between the module (``rss2email.util``) and the
+    function within the module (``import_name``).
+
+    Some objects can't be pickled:
+
+    >>> import_name(lambda x: 'muahaha')
+    Traceback (most recent call last):
+      ...
+    _pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed
+
+    Some objects don't have a global scope:
+
+    >>> import_name('abc')
+    Traceback (most recent call last):
+      ...
+    ValueError: abc
+    """
+    pickle = _pickle.dumps(obj)
+    for opcode,arg,pos in _pickletools.genops(pickle):
+        if opcode.name == 'GLOBAL':
+            return arg
+    raise ValueError(obj)
+
+def import_function(name):
+    """Import a function using the full import name
+
+    >>> import_function('rss2email.util import_function')  # doctest: +ELLIPSIS
+    <function import_function at 0x...>
+    >>> import_function(import_name(import_function))  # doctest: +ELLIPSIS
+    <function import_function at 0x...>
+
+    >>> import_function('rss2email.util does_not_exist')
+    Traceback (most recent call last):
+      ...
+    AttributeError: 'module' object has no attribute 'does_not_exist'
+    >>> import_function('rss2email.util has invalid syntax')
+    Traceback (most recent call last):
+      ...
+    AttributeError: 'module' object has no attribute 'has invalid syntax'
+    >>> import_function('rss2email.util.no_space')
+    Traceback (most recent call last):
+      ...
+    ValueError: rss2email.util.no_space
+    """
+    try:
+        module_name,function_name = name.split(' ', 1)
+    except ValueError as e:
+        raise ValueError(name) from e
+    module = _importlib.import_module(module_name)
+    return getattr(module, function_name)
diff --git a/test/allthingsrss/2.config b/test/allthingsrss/2.config
new file mode 100644 (file)
index 0000000..59a4427
--- /dev/null
@@ -0,0 +1,4 @@
+[DEFAULT]
+to = a@b.com
+date-header = True
+post-process = rss2email.hook downcase_message
diff --git a/test/allthingsrss/2.expected b/test/allthingsrss/2.expected
new file mode 100644 (file)
index 0000000..d36cb53
--- /dev/null
@@ -0,0 +1,408 @@
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Version 2.67 Released
+Date: Tue, 21 Sep 2010 16:55:07 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=62
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/aGbf5Gefkmc/
+X-RSS-TAGS: Uncategorized
+
+version 2.67 of rss2email is now available for both
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.67.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.67.zip), which
+includes the latest development version of feedparser. changes from the
+previous version:
+
+  * fixed entries that include an id which is blank (i.e., an empty string) were being resent
+  * fixed some entries not being sent by email because they had bad from headers
+  * fixed from headers with html entities encoded twice
+  * compatibility changes to support most recent development versions of feedparser
+  * compatibility changes to support google reader feeds
+
+complete list in the official
+[changelog](http://www.allthingsrss.com/rss2email/changelog).
+
+[![](http://feedads.g.doubleclick.net/~a/sjq8v-
+lq2dnkzkelsypic4fjplm/0/di)](http://feedads.g.doubleclick.net/~a/sjq8v-
+lq2dnkzkelsypic4fjplm/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/sjq8v-
+lq2dnkzkelsypic4fjplm/1/di)](http://feedads.g.doubleclick.net/~a/sjq8v-
+lq2dnkzkelsypic4fjplm/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/agbf5gefkmc)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/agbf5gefkmc/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Version 2.68 Released with Actual New Features
+Date: Fri, 01 Oct 2010 18:21:26 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=72
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/bT-I0iH2vw8/
+X-RSS-TAGS: Uncategorized
+
+unlike the last few versions of rss2email that have trickled out, i finally
+got around to adding a few new oft-requested features! version 2.68 of
+rss2email is now available for both
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.68.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.68.zip).
+
+changes from the previous version:
+
+  * added ability to pause/resume checking of individual feeds through pause and unpause commands
+  * added ability to import and export opml feed lists through importopml and exportopml commands
+
+complete list in the official
+[changelog](http://www.allthingsrss.com/rss2email/changelog).
+
+**pause/unpause**
+
+through `r2e pause _n_` where _n_ is a feed number, you can temporarily
+suspend checking that feed for new content. to start checking it again, simply
+run `r2e unpause _n_`. when you `r2e list`, an asterisk indicates that the
+feed is currently unpaused and active.
+
+**ompl import/export**
+
+[opml](http://en.wikipedia.org/wiki/opml) is an xml format commonly used to
+exchange a list of rss feeds between applications. `r2e opmlexport >
+_filename_` will give you a file that you can use to import your list of feeds
+into another application. if you've exported feeds from another application
+into a file, `r2e opmlimport _filename_` will add those feeds to your
+rss2email feed list.
+
+[![](http://feedads.g.doubleclick.net/~a/nygtsiuss9pmvrz6092xgghnnkg/0/di)](ht
+tp://feedads.g.doubleclick.net/~a/nygtsiuss9pmvrz6092xgghnnkg/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/nygtsiuss9pmvrz6092xgghnnkg/1/di)](ht
+tp://feedads.g.doubleclick.net/~a/nygtsiuss9pmvrz6092xgghnnkg/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/bt-i0ih2vw8)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/bt-i0ih2vw8/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: How to Read RSS Feeds in Emacs
+Date: Fri, 05 Nov 2010 17:36:14 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=79
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/JryfOLe_q6c/
+X-RSS-TAGS: Uncategorized
+
+emacs and rss2email user erik hetzner has written up a tutorial on how he
+integrated [rss feed reading into
+emacs](http://www.emacswiki.org/emacs/howtoreadfeedsinemacsviaemail) using
+rss2email.
+
+[![](http://feedads.g.doubleclick.net/~a/w185ejeikknpfrcwp9sv0gdrfjk/0/di)](ht
+tp://feedads.g.doubleclick.net/~a/w185ejeikknpfrcwp9sv0gdrfjk/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/w185ejeikknpfrcwp9sv0gdrfjk/1/di)](ht
+tp://feedads.g.doubleclick.net/~a/w185ejeikknpfrcwp9sv0gdrfjk/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/jryfole_q6c)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/jryfole_q6c/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Version 2.69 Released
+Date: Fri, 12 Nov 2010 18:45:08 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=85
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/ubaE55Le1OU/
+X-RSS-TAGS: Uncategorized
+
+version 2.69 of rss2email is now available for both
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.69.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.69.zip).
+
+changes from the previous version:
+
+  * added support for connecting to smtp server via ssl, see smtp_ssl option 
+  * improved backwards compatibility by fixing issue with listing feeds when run with older python versions 
+  * added selective feed email overrides through override_email and default_email options 
+  * added no_friendly_name to from from address only without the friendly name 
+  * added x-rss-url header in each message with the link to the original item 
+
+complete list in the official
+[changelog](http://www.allthingsrss.com/rss2email/changelog).
+
+[![](http://feedads.g.doubleclick.net/~a/ygs5ivjpi9xnnjtza1sftazptua/0/di)](ht
+tp://feedads.g.doubleclick.net/~a/ygs5ivjpi9xnnjtza1sftazptua/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/ygs5ivjpi9xnnjtza1sftazptua/1/di)](ht
+tp://feedads.g.doubleclick.net/~a/ygs5ivjpi9xnnjtza1sftazptua/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/ubae55le1ou)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/ubae55le1ou/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Minor Correction to v2.69 Packages
+Date: Fri, 10 Dec 2010 17:47:58 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=88
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/CiODBX5_NSk/
+X-RSS-TAGS: Uncategorized
+
+the v2.69 rss2email packages contain an example config.py file that might
+accidentally overwrite an existing config.py file. to keep this from happening
+i've updated both the
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.69.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.69.zip) by simply
+renaming the file to config.py.example.
+
+[![](http://feedads.g.doubleclick.net/~a/v9hd_j59x3sfwg3q2xbjlncdusa/0/di)](ht
+tp://feedads.g.doubleclick.net/~a/v9hd_j59x3sfwg3q2xbjlncdusa/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/v9hd_j59x3sfwg3q2xbjlncdusa/1/di)](ht
+tp://feedads.g.doubleclick.net/~a/v9hd_j59x3sfwg3q2xbjlncdusa/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/ciodbx5_nsk)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/ciodbx5_nsk/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Minor correction to the minor correction: v2.69a released
+Date: Mon, 13 Dec 2010 18:04:20 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=95
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/VgWvylH6fvk/
+X-RSS-TAGS: Uncategorized
+
+last week i made a [slight change to the v2.69 rss2email
+packages](http://www.allthingsrss.com/rss2email/2010/12/minor-correction-
+to-v2-69-packages/), which can cause suspicion that they have been tampered
+with. to mitigate this, i put the original v2.69 files back in place and
+renamed the updated package set to v2.69a.
+
+here is v2.69a:
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.69a.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.69a.zip)
+
+and here is the original v2.69:
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.69.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.69.zip)
+
+[![](http://feedads.g.doubleclick.net/~a/a817ydrxpe_g34wxu-
+sazq6uihm/0/di)](http://feedads.g.doubleclick.net/~a/a817ydrxpe_g34wxu-
+sazq6uihm/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/a817ydrxpe_g34wxu-
+sazq6uihm/1/di)](http://feedads.g.doubleclick.net/~a/a817ydrxpe_g34wxu-
+sazq6uihm/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/vgwvylh6fvk)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/vgwvylh6fvk/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Mac OS X and rss2email are Compatible
+Date: Fri, 17 Dec 2010 20:54:27 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=99
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/cILvxh4ziQg/
+X-RSS-TAGS: Uncategorized
+
+rss2email user jon thompson has reported that linux rss2email works well under
+mac os x. this is good news, but not to surprising since apple based os x on
+unix.
+
+technically the rss2email linux package usually works on other unix-derived
+oss, such as centos and bsd. they aren't officially supported, but we usually
+try resolve incompatibilities if possible.
+
+[![](http://feedads.g.doubleclick.net/~a/n8i-
+3iyxnst7ki6avoy7j2dfjk8/0/di)](http://feedads.g.doubleclick.net/~a/n8i-
+3iyxnst7ki6avoy7j2dfjk8/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/n8i-
+3iyxnst7ki6avoy7j2dfjk8/1/di)](http://feedads.g.doubleclick.net/~a/n8i-
+3iyxnst7ki6avoy7j2dfjk8/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/cilvxh4ziqg)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/cilvxh4ziqg/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Version 2.70 Released
+Date: Tue, 21 Dec 2010 20:00:49 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=106
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/0rUaRcCJ8dU/
+X-RSS-TAGS: Uncategorized
+
+version 2.70 of rss2email is now available for both
+[linux](http://www.allthingsrss.com/rss2email/rss2email-2.70.tar.gz) and
+[windows](http://www.allthingsrss.com/rss2email/rss2email-2.70.zip).
+
+changes from the previous version:
+
+  * improved handling of given feed email addresses to prevent mail servers rejecting poorly formed froms 
+  * added x-rss-tags header that lists any tags provided by an entry, which will be helpful in filtering incoming messages 
+
+complete list in the official
+[changelog](http://www.allthingsrss.com/rss2email/changelog).
+
+[![](http://feedads.g.doubleclick.net/~a/3-mtadqlwiwgd3bgvmqymi2xayg/0/di)](ht
+tp://feedads.g.doubleclick.net/~a/3-mtadqlwiwgd3bgvmqymi2xayg/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/3-mtadqlwiwgd3bgvmqymi2xayg/1/di)](ht
+tp://feedads.g.doubleclick.net/~a/3-mtadqlwiwgd3bgvmqymi2xayg/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/0ruarccj8du)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/0ruarccj8du/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Version 2.71 Release plus Other Major Updates
+Date: Fri, 04 Mar 2011 18:03:11 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=123
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/wsLSVDNzno0/
+X-RSS-TAGS: Uncategorized
+
+good news everyone! two important tools that rss2email depends on have
+recently received major upgrades:
+[feedparser](http://code.google.com/p/feedparser/) and
+[html2text](https://github.com/aaronsw/html2text). these should improve
+rss2email's ability to handle feeds with poorly formed html and other
+weirdness.
+
+the rss2email application itself also needed to be upgraded some to support
+these. changes in this version:
+
+  * upgraded to feedparser v5.01! (http://code.google.com/p/feedparser/) 
+  * upgraded to html2text v3.01! (https://github.com/aaronsw/html2text) 
+  * potentially safer method for writing feeds.dat on unix 
+  * handle via links with no title attribute 
+  * handle attributes more cleanly with override_email and default_email 
+
+[![](http://feedads.g.doubleclick.net/~a/mpc_o2acgpykdqhi-
+imaop4lbs0/0/di)](http://feedads.g.doubleclick.net/~a/mpc_o2acgpykdqhi-
+imaop4lbs0/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/mpc_o2acgpykdqhi-
+imaop4lbs0/1/di)](http://feedads.g.doubleclick.net/~a/mpc_o2acgpykdqhi-
+imaop4lbs0/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/wslsvdnzno0)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/wslsvdnzno0/
+
+SENT BY: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+From: "rss2email: Lindsey Smith" <user@rss2email.invalid>
+To: a@b.com
+Subject: Mac OS, rss2email and scheduling with launchd
+Date: Tue, 23 Aug 2011 15:57:37 -0000
+Message-ID: <...@dev.null.invalid>
+User-Agent: rss2email
+X-RSS-Feed: allthingsrss/feed.atom
+X-RSS-ID: http://www.allthingsrss.com/rss2email/?p=131
+X-RSS-URL: http://feedproxy.google.com/~r/allthingsrss/hJBr/~3/0hb7cT3sLUM/
+X-RSS-TAGS: Uncategorized
+
+just a little fyi if you encounter this: macrumors user durlecs was having a
+[problem scheduling rss2email with
+launchd](http://forums.macrumors.com/showthread.php?t=1216694), mac os's built
+in replacement for cron and other unix services. it looks like he/she got it
+working in the end by adding the path to python into the path environment
+variable.
+
+[![](http://feedads.g.doubleclick.net/~a/0q4e9-dkghhcjqmhuxc-
+_qjrgka/0/di)](http://feedads.g.doubleclick.net/~a/0q4e9-dkghhcjqmhuxc-
+_qjrgka/0/da)
+
+[![](http://feedads.g.doubleclick.net/~a/0q4e9-dkghhcjqmhuxc-
+_qjrgka/1/di)](http://feedads.g.doubleclick.net/~a/0q4e9-dkghhcjqmhuxc-
+_qjrgka/1/da)
+
+![](http://feeds.feedburner.com/~r/allthingsrss/hjbr/~4/0hb7ct3slum)
+
+
+
+url: http://feedproxy.google.com/~r/allthingsrss/hjbr/~3/0hb7ct3slum/