Skip to content

Instantly share code, notes, and snippets.

@boris-arzur
Last active August 29, 2015 14:19
Show Gist options
  • Save boris-arzur/431a47a162de77228f1f to your computer and use it in GitHub Desktop.
Save boris-arzur/431a47a162de77228f1f to your computer and use it in GitHub Desktop.
read maildir from interactive ipython notebook
%%file /ipy/mailcheck.py
import mailbox
import email.utils
import email.header
import email.iterators
from IPython.html.widgets import interact, interactive, fixed
from IPython.html import widgets
from IPython.display import display
def decode_(packed_stff):
bits, charset = email.header.decode_header(packed_stff)[0]
if charset is None:
return str(packed_stff)
return str(bits, charset)
def get_charset(message, default="ascii"):
gcc = message.get_content_charset()
if gcc: return gcc
gc = message.get_charset()
if gc: return gc
return default
def unicode_me(part, charset):
return str(part.get_payload(decode=True), charset)
def get_parts_for_type(message, message_charset, type_):
prefered_parts = tuple(email.iterators.typed_subpart_iterator(message, 'text', type_))
charsets = [get_charset(part, message_charset) for part in prefered_parts]
unicoded = [unicode_me(part, charset) for part, charset in zip(prefered_parts, charsets)]
return u"\n".join(unicoded).strip()
def get_body(message):
message_charset = get_charset(message)
if message.is_multipart():
text_plain = get_parts_for_type(message, message_charset, 'plain')
if len(text_plain) > 0: return text_plain
return get_parts_for_type(message, message_charset, 'html')
else:
return unicode_me(message, message_charset).strip()
def get_date_as_timestamp(message):
return email.utils.parsedate(message['date'])
def list_mail(maildir, size):
md = mailbox.Maildir(maildir)
from_message_id_to_timestamp = lambda mid: get_date_as_timestamp(md.get_message(mid))
sorted_by_date = sorted(md.keys(), key=from_message_id_to_timestamp)
mails = []
descr_to_mid = {}
for mid in sorted_by_date[-size:]:
_mail = md.get_message(mid)
# Here I want to columnize the output, but {:10s} formatter dont work,
# spaces are collapsed, and keys lost in 'options' {text: lid}
descr_line = "{} from:{} subject:{}".format(
_mail['date'],
email.utils.parseaddr(_mail['from'])[-1],
decode_(_mail['subject'])
)
mails.append(descr_line)
descr_to_mid[descr_line] = mid
return md, mails, descr_to_mid
class tleilaxu_select:
def __init__(self, maildir, max_size):
self.size = 5
self.max_size = max_size
self.maildir = maildir
self.select = widgets.Select(options=[], width=900)
self.refresh()
self.interactive = interactive(self.show, mail=self.select)
def resize(self, size):
if self.max_size == size:
# biggest size setting shows all
size = -1
self.size = size
self.refresh()
def refresh(self, *args):
md, mails, descr_to_mid = list_mail(self.maildir, self.size)
self.md = md
self.select.options = [] # flush
self.select.options = mails # and show
self.descr_to_mid = descr_to_mid
def show(self, mail):
mid = self.descr_to_mid[mail]
_mail = self.md.get_message(mid)
print(_mail['date'], email.utils.parseaddr(_mail['from']))
email.iterators._structure(_mail)
print(decode_(_mail['subject']))
print(get_body(_mail))
def make_button(self):
button = widgets.ButtonWidget(description="Refresh !")
button.on_click(self.refresh)
return button
def make_slider(self):
slider = interactive(self.resize, size=(0, self.max_size));
return slider
def make_control_panel(self):
button = self.make_button()
slider = self.make_slider()
main_container = widgets.HBox(children=[button, slider])
return main_container
def run(**kwargs):
select = tleilaxu_select(**kwargs)
control_panel = select.make_control_panel()
display(control_panel)
display(select.interactive)
# use it in an ipython 3.1 notebook, the cell content in my case is 'import mailcheck; mailcheck.run(maildir='/home/boris/Maildir', max_size=20)'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment