diff --git a/modules/mailinator/__init__.py b/modules/mailinator/__init__.py new file mode 100644 index 00000000..1c40f994 --- /dev/null +++ b/modules/mailinator/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Vincent A +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from .backend import MailinatorBackend + + +__all__ = ['MailinatorBackend'] diff --git a/modules/mailinator/backend.py b/modules/mailinator/backend.py new file mode 100644 index 00000000..09f93970 --- /dev/null +++ b/modules/mailinator/backend.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Vincent A +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.backend import BaseBackend, BackendConfig +from weboob.capabilities.messages import ICapMessages, Thread, Message +from weboob.tools.value import Value + +from .browser import MailinatorBrowser + + +__all__ = ['MailinatorBackend'] + + +# There is only one thread per inbox, and the thread id is the inbox name +# TODO but this can lead to bans if there are too many messages... +class MailinatorBackend(BaseBackend, ICapMessages): + NAME = 'mailinator' + DESCRIPTION = u'mailinator temp mailbox' + MAINTAINER = u'Vincent A' + EMAIL = 'dev@indigo.re' + LICENSE = 'AGPLv3+' + VERSION = '0.i' + + BROWSER = MailinatorBrowser + + CONFIG = BackendConfig(Value('inbox', label='Inbox', default='')) + + def iter_threads(self): + inbox = self.config['inbox'].get() + if not inbox: + raise NotImplementedError() + else: + return [self.get_thread(inbox)] + + def get_thread(self, _id): + t = Thread(_id) + t.title = 'Mail for %s' % _id + t.flags = t.IS_DISCUSSION + + first = True + for d in self.browser.get_mails(_id): + m = self.make_message(d, t) + if not m.content: + m.content = self.browser.get_mail_content(m.id) + + if first: + first = False + t.root = m + else: + m.parent = t.root + m.parent.children.append(m) + + return t + + def make_message(self, d, thread): + m = Message(thread, d['id']) + m.children = [] + m.sender = d['from'] + m.flags = 0 + if not d.get('read', True): + m.flags = m.IS_UNREAD + m.title = d['subject'] + m.date = d['datetime'] + m.receivers = [d['to']] + return m diff --git a/modules/mailinator/browser.py b/modules/mailinator/browser.py new file mode 100644 index 00000000..97429f36 --- /dev/null +++ b/modules/mailinator/browser.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Vincent A +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.browser import BaseBrowser, BrowserBanned +from weboob.tools.date import datetime +from weboob.tools.parsers.jsonparser import json +import lxml.html +import time + + +__all__ = ['MailinatorBrowser'] + + +class MailinatorBrowser(BaseBrowser): + PROTOCOL = 'http' + DOMAIN = 'mailinator.com' + ENCODING = 'utf-8' + + def __init__(self, *args, **kw): + kw['parser'] = 'raw' + BaseBrowser.__init__(self, *args, **kw) + + def _get_unicode(self, url): + return self.get_document(self.openurl(url)).decode(self.ENCODING, 'replace') + + def _get_json(self, url): + j = json.loads(self._get_unicode(url)) + if 'rate' in j: + # shit, we've been banned... + raise BrowserBanned('Flood - Banned for today') + return j + + def get_mails(self, boxid, after=None): + box = self._get_json('http://mailinator.com/useit?box=%s&time=%s' % (boxid, millis())) + address = box['address'] + + mails = self._get_json('http://mailinator.com/grab?inbox=%s&address=%s' % (boxid, address)) + for mail in mails['maildir']: + d = {'id': mail['id'], 'from': mail['fromfull'], 'to': mail['to'], 'from_name': mail['from'], 'datetime': frommillis(mail['time']), 'subject': mail['subject'], 'read': mail['been_read'], 'box': (boxid, address)} + yield d + + def get_mail_content(self, mailid): + frame = self._get_unicode('http://mailinator.com/rendermail.jsp?msgid=%s&time=%s' % (mailid, millis())).strip() + if not len(frame): + # likely we're banned + return '' + doc = lxml.html.fromstring(frame) + divs = doc.cssselect('.mailview') + return divs[0].text_content().strip() + +def millis(): + return int(time.time() * 1000) + +def frommillis(millis): + return datetime.fromtimestamp(millis / 1000) diff --git a/modules/mailinator/favicon.png b/modules/mailinator/favicon.png new file mode 100644 index 00000000..f143c391 Binary files /dev/null and b/modules/mailinator/favicon.png differ diff --git a/modules/mailinator/test.py b/modules/mailinator/test.py new file mode 100644 index 00000000..a8c2079a --- /dev/null +++ b/modules/mailinator/test.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +# Copyright(C) 2013 Vincent A +# +# This file is part of weboob. +# +# weboob is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# weboob is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with weboob. If not, see . + + +from weboob.tools.test import BackendTest + + +class MailinatorTest(BackendTest): + BACKEND = 'mailinator' + + def test_mailinator(self): + t = self.backend.get_thread('qwerty') + assert t + assert t.root + assert t.root.title + assert t.root.date + assert t.root.sender + assert t.root.receivers +