Commits

Manuel de la Pena committed bfa92d2

Initial imap implementation.

Comments (0)

Files changed (3)

conversa/daemon/mail.py

-# Copyright (c) 2012 Conversa and other contributors,
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-# 
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-"""Main module of conversa."""

conversa/daemon/mail/__init__.py

+# Copyright (c) 2012 Conversa and other contributors,
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"""Mail implementations."""
+
+from conversa import accounts
+from conversa.daemon.mail.imap4 import Imap4
+

conversa/daemon/mail/imap4.py

+# Copyright (c) 2012 Conversa and other contributors,
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"""Imap4 mail implementation."""
+
+from twisted.mail import imap4
+from twisted.internet import defer, reactor, ssl, protocol
+from twisted.protocols.tls import TLSMemoryBIOFactory
+
+from conversa import accounts
+
+USERNAME = '...'
+PASSWORD = '...'
+
+# Gmail specific:
+SERVER = 'imap.gmail.com'
+PORT = 993
+# Gmail requires you connect via SSL, so
+#we pass the follow object to 'someclient.connectSSL':
+contextFactory = ssl.ClientContextFactory()
+
+
+class NotConnectedError(Exception):
+    """Raised when the client is not connected."""
+
+
+class Imap4(object):
+    """Represents an imap4 account."""
+
+    def __init__(self, server_info):
+        """Create a new instance."""
+        self.proto = None
+        self.server_info = server_info
+
+    def _store_protocol(self, proto):
+        """Callback to store the connection protocol."""
+        self.proto = proto
+        return True
+
+    def _login(self, proto):
+        """Try to loging and store the proto."""
+        return proto
+
+    def connect(self):
+        """Connect to the email account."""
+        client = protocol.ClientCreator(reactor, imap4.IMAP4Client)
+        d = None
+        # decide which type of connection to use
+        if (self.server_info.security == accounts.SECURITY_SSL
+                or self.server_info.security == accounts.SECURITY_TLS):
+            d = client.connectSSL(self.server_info.address,
+                    self.server_info.port, ssl.ClientContextFactory())
+        else:
+            # no security
+            d = client.connectTCP(self.server_info.address,
+                    self.server_info.port)
+
+        d.addCallback(self._login)  # try to login with the creds
+        d.addCallback(self._store_protocol)  # store the proto if we got in
+        return d
+
+    def mailboxes(self):
+        """Return the mailboxes."""
+        if self.proto is None:
+            # we are not connected!!
+            return defer.fail(NotConnectedError('Client is not connected'))
+        return self.proto.list('','*')
+
+def mailboxes(list):
+    print list
+    for flags,sep,mbox in list:
+        print mbox
+
+def loggedin(res, proto):
+    d = proto.list('','*')
+    d.addCallback(mailboxes)
+    return d
+
+def connected(proto):
+    print "connected", proto
+    d = proto.login(USERNAME, PASSWORD)
+    d.addCallback(loggedin, proto)
+    d.addErrback(failed)
+    return d
+
+def failed(f):
+    print "failed", f
+    return f
+
+def done(_):
+    reactor.callLater(0, reactor.stop)
+
+def main():
+    c = protocol.ClientCreator(reactor, imap4.IMAP4Client)
+    d = c.connectSSL(SERVER, PORT, contextFactory)
+    d.addCallbacks(connected, failed)
+    d.addBoth(done)
+
+reactor.callLater(0, main)
+reactor.run()