diff --git a/README.md b/README.md index cccd3ef..7cdc126 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ muttdown ======== -`muttdown` is a sendmail-replacement designed for use with the [mutt][] email client which will transparently compile annotated `text/plain` mail into `text/html` using the [Markdown][] standard. It will recursively walk the MIME tree and compile any `text/plain` or `text/markdown` part which begins with the sigil "!m" into Markdown, which it will insert alongside the original in a multipart/alternative container. +`muttdown` is a sendmail-replacement designed for use with the [mutt][] email client which will transparently compile annotated `text/plain` mail into `text/html` using the [Markdown][] standard. It will recursively walk the MIME tree and compile any `text/plain` or `text/markdown` part which begins with the sigil "!m" into Markdown, which it will insert alongside the original in a multipart/alternative container. If a part starts with the sigil '!p' it will simply enclose it in <pre> </pre> tags instead of +formatting it with markdown. It's also smart enough not to break `multipart/signed`. @@ -56,6 +57,16 @@ The `css_file` should be regular CSS styling blocks; we use [pynliner][] to inli Muttdown can also send its mail using the native `sendmail` if you have that set up (instead of doing SMTP itself). To do so, just leave the smtp options in the config file blank, set the `sendmail` option to the fully-qualified path to your `sendmail` binary, and run muttdown with the `-s` flag +If the `remove_sigil` configuration file option is true, the sigil will also be removed from the plaintext version of the message part. + +The `markdown_extensions` configuration file option can be set to a list of Python markdown extensions that will be enabled (e.g. `[markdown.extensions.extra,markdown.extensions.Admonition]`). + +The `utf8` option will assume that the message text is UTF8 and create +the HTML version appropriately. This is useful if you receive a lot +of e-mails (which you want to quote in replies) that include UTF-8 +characters but don't have the encoding set correctly. + + Installation ------------ Install muttdown with `pip install muttdown` or by downloading this package and running `python setup.py install`. You will need the [PyYAML][] and [Python-Markdown][] libraries, as specified in `requirements.txt`. diff --git a/muttdown/config.py b/muttdown/config.py index 6019677..e474692 100644 --- a/muttdown/config.py +++ b/muttdown/config.py @@ -63,6 +63,9 @@ class Config(object): 'smtp_timeout': 10, 'css_file': None, 'sendmail': '/usr/sbin/sendmail', + 'remove_sigil': False, + 'markdown_extensions' : [], + 'utf8': False, } def __init__(self): diff --git a/muttdown/main.py b/muttdown/main.py old mode 100644 new mode 100755 index 59858c1..42f720b --- a/muttdown/main.py +++ b/muttdown/main.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python2 from __future__ import print_function import argparse @@ -16,32 +17,54 @@ import markdown import pynliner -from . import config -from . import __version__ +try: + from . import config + from . import __version__ + __name__ = 'muttdown' +except ValueError: + import config + __version__ = 'testing' -__name__ = 'muttdown' +def convert_markdown(text,config): + return markdown.markdown(text,config.markdown_extensions,output_format="html5") +def convert_preformat(text,config): + import cgi + return '
\n' + cgi.escape(text) + '\n
\n' def convert_one(part, config): try: text = part.get_payload(None, True) - if not text.startswith('!m'): + + if text.startswith('!m'): + converter = convert_markdown + elif text.startswith('!p'): + converter = convert_preformat + else: return None - text = re.sub('\s*!m\s*', '', text, re.M) + text = re.sub('\s*![pm]\s*', '', text, count=1, flags=re.M) + if config.remove_sigil: + part.set_payload(text) + if config.utf8: + text = unicode(text,'utf8') if '\n-- \n' in text: pre_signature, signature = text.split('\n-- \n') - md = markdown.markdown(pre_signature, output_format="html5") + md = converter(pre_signature,config) md += '\n

--
' md += '
'.join(signature.split('\n')) md += '

' else: - md = markdown.markdown(text) + md = converter(text,config) if config.css: - md = '' + md + md = '\n' + '\n' + md + '\n\n' md = pynliner.fromString(md) - message = MIMEText(md, 'html') + if config.utf8: + message = MIMEText(md.encode('utf-8'), 'html', _charset='utf-8') + else: + message = MIMEText(md, 'html') return message - except Exception: + except Exception as e: + sys.stderr.write('muttdown: '+str(e)) return None @@ -116,7 +139,7 @@ def main(): parser = argparse.ArgumentParser(version='%s %s' % (__name__, __version__)) parser.add_argument( '-c', '--config_file', default=os.path.expanduser('~/.muttdown.yaml'), - type=argparse.FileType('r'), required=True, + type=argparse.FileType('r'), required=False, help='Path to YAML config file (default %(default)s)' ) parser.add_argument( @@ -153,6 +176,8 @@ def main(): proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, shell=False) proc.communicate(rebuilt.as_string()) + proc.wait() + sys.exit(proc.returncode) else: conn = smtp_connection(c)