Some code style cleanup

darcs-hash:20070530062134-86b55-2670bdf7b6eebb7ad8014db9629a6e3ee36ac00c.gz
This commit is contained in:
David Rousselie
2007-05-30 08:21:34 +02:00
parent 16de054616
commit e2b74fbde4
3 changed files with 254 additions and 206 deletions

View File

@@ -2,24 +2,24 @@
## ##
## component.py ## component.py
## Login : David Rousselie <dax@happycoders.org> ## Login : David Rousselie <dax@happycoders.org>
## Started on Fri Jan 7 11:06:42 2005 ## Started on Fri Jan 7 11:06:42 2005
## $Id: component.py,v 1.12 2005/09/18 20:24:07 dax Exp $ ## $Id: component.py,v 1.12 2005/09/18 20:24:07 dax Exp $
## ##
## Copyright (C) 2005 ## Copyright (C) 2005
## This program is free software; you can redistribute it and/or modify ## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by ## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or ## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version. ## (at your option) any later version.
## ##
## This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details. ## GNU General Public License for more details.
## ##
## You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
## ##
import logging import logging
import re import re
@@ -30,10 +30,13 @@ from sqlobject import *
from pyxmpp.message import Message from pyxmpp.message import Message
from jcl.model.account import Account, PresenceAccount from jcl.model.account import Account, PresenceAccount
from jcl.jabber.component import Handler, DefaultSubscribeHandler, DefaultUnsubscribeHandler, DefaultPresenceHandler from jcl.jabber.component import Handler, DefaultSubscribeHandler, \
from jcl.jabber.feeder import FeederComponent, Feeder, MessageSender, HeadlineSender DefaultUnsubscribeHandler, DefaultPresenceHandler
from jcl.jabber.feeder import FeederComponent, Feeder, MessageSender, \
HeadlineSender
from jmc.model.account import MailAccount, IMAPAccount, POP3Account, SMTPAccount from jmc.model.account import MailAccount, IMAPAccount, POP3Account, \
SMTPAccount
from jmc.lang import Lang from jmc.lang import Lang
class MailComponent(FeederComponent): class MailComponent(FeederComponent):
@@ -47,19 +50,22 @@ class MailComponent(FeederComponent):
db_connection_str, db_connection_str,
lang = Lang()): lang = Lang()):
"""Use FeederComponent behavior and setup feeder and sender """Use FeederComponent behavior and setup feeder and sender
attributes attributes.
""" """
FeederComponent.__init__(self, \ FeederComponent.__init__(self,
jid, \ jid,
secret, \ secret,
server, \ server,
port, \ port,
db_connection_str, db_connection_str,
lang = lang) lang=lang)
self.feeder = MailFeeder(self) self.feeder = MailFeeder(self)
self.sender = MailSender(self) self.sender = MailSender(self)
self.account_manager.account_classes = (IMAPAccount, POP3Account, SMTPAccount) self.account_manager.account_classes = (IMAPAccount,
self.msg_handlers += [SendMailMessageHandler(), RootSendMailMessageHandler()] POP3Account,
SMTPAccount)
self.msg_handlers += [SendMailMessageHandler(),
RootSendMailMessageHandler()]
self.subscribe_handlers += [MailSubscribeHandler()] self.subscribe_handlers += [MailSubscribeHandler()]
self.unsubscribe_handlers += [MailUnsubscribeHandler()] self.unsubscribe_handlers += [MailUnsubscribeHandler()]
self.available_handlers += [DefaultPresenceHandler()] self.available_handlers += [DefaultPresenceHandler()]
@@ -76,11 +82,15 @@ class MailFeeder(Feeder):
def initialize_live_email(self, _account): def initialize_live_email(self, _account):
"""For live email checking account, mark emails received while """For live email checking account, mark emails received while
offline as read. offline as read.
Return a boolean to continue mail checking or not (if waiting for password)""" Return a boolean to continue mail checking or not
(if waiting for password).
"""
if _account.password is None: if _account.password is None:
if not _account.waiting_password_reply: if not _account.waiting_password_reply:
self.component.send_stanzas(self.component.account_manager.ask_password(_account, \ account_manager = self.component.account_manager
_account.default_lang_class)) self.component.send_stanzas(\
account_manager.ask_password(_account,
_account.default_lang_class))
return False return False
try: try:
_account.connect() _account.connect()
@@ -101,7 +111,8 @@ class MailFeeder(Feeder):
def feed(self, _account): def feed(self, _account):
"""Check for new emails for given MailAccount and return a list of """Check for new emails for given MailAccount and return a list of
those emails or a summary""" those emails or a summary.
"""
self.__logger.debug("MailFeeder.feed") self.__logger.debug("MailFeeder.feed")
result = [] result = []
if _account.first_check and _account.live_email_only: if _account.first_check and _account.live_email_only:
@@ -115,21 +126,25 @@ class MailFeeder(Feeder):
if action != PresenceAccount.DO_NOTHING: if action != PresenceAccount.DO_NOTHING:
try: try:
if _account.password is None: if _account.password is None:
self.component.send_stanzas(self.component.account_manager.ask_password(_account, \ account_manager = self.component.account_manager
_account.default_lang_class)) self.component.send_stanzas(\
account_manager.ask_password(_account,
_account.default_lang_class))
return result return result
self.__logger.debug("Checking " + _account.name) self.__logger.debug("Checking " + _account.name)
self.__logger.debug("\t" + _account.login \ self.__logger.debug("\t" + _account.login \
+ "@" + _account.host) + "@" + _account.host)
_account.connect() _account.connect()
mail_list = _account.get_mail_list() mail_list = _account.get_mail_list()
default_lang_class = _account.default_lang_class
if action == MailAccount.RETRIEVE: if action == MailAccount.RETRIEVE:
# TODO : use generator (yield) # TODO : use generator (yield)
mail_index = _account.get_next_mail_index(mail_list) mail_index = _account.get_next_mail_index(mail_list)
while mail_index is not None: while mail_index is not None:
(body, email_from) = _account.get_mail(mail_index) (body, email_from) = _account.get_mail(mail_index)
result.append((_account.default_lang_class.new_mail_subject % (email_from), \ result.append((default_lang_class.new_mail_subject\
body)) % (email_from),
body))
mail_index = _account.get_next_mail_index(mail_list) mail_index = _account.get_next_mail_index(mail_list)
elif action == MailAccount.DIGEST: elif action == MailAccount.DIGEST:
body = "" body = ""
@@ -138,15 +153,17 @@ class MailFeeder(Feeder):
while mail_index is not None: while mail_index is not None:
(tmp_body, from_email) = \ (tmp_body, from_email) = \
_account.get_mail_summary(mail_index) _account.get_mail_summary(mail_index)
body += tmp_body + "\n----------------------------------\n" body += tmp_body
body += "\n----------------------------------\n"
mail_index = _account.get_next_mail_index(mail_list) mail_index = _account.get_next_mail_index(mail_list)
new_mail_count += 1 new_mail_count += 1
if body != "": if body != "":
result.append((_account.default_lang_class.new_digest_subject % (new_mail_count), \ result.append((default_lang_class.new_digest_subject\
body)) % (new_mail_count),
body))
else: else:
raise Exception("Unkown action: " + str(action) raise Exception("Unkown action: " + str(action) \
+ "\nPlease reconfigure account.") + "\nPlease reconfigure account.")
_account.disconnect() _account.disconnect()
_account.in_error = False _account.in_error = False
self.__logger.debug("\nCHECK_MAIL ends " + _account.jid) self.__logger.debug("\nCHECK_MAIL ends " + _account.jid)
@@ -162,7 +179,7 @@ class MailFeeder(Feeder):
class MailSender(MessageSender, HeadlineSender): class MailSender(MessageSender, HeadlineSender):
"""Send emails messages to jabber users""" """Send emails messages to jabber users"""
def send(self, to_account, subject, body): def send(self, to_account, subject, body):
"""Send given emails (in data) as Jabber messages""" """Send given emails (in data) as Jabber messages"""
if to_account.action == MailAccount.RETRIEVE: if to_account.action == MailAccount.RETRIEVE:
@@ -185,17 +202,19 @@ class MailHandler(Handler):
if accounts.count() == 0: if accounts.count() == 0:
raise Exception() raise Exception()
else: else:
default_account = accounts.newClause(SMTPAccount.q.default_account == True) default_account = accounts.newClause(\
SMTPAccount.q.default_account == True)
if default_account.count() > 0: if default_account.count() > 0:
return default_account return default_account
else: else:
return accounts return accounts
return None return None
class SendMailMessageHandler(MailHandler): class SendMailMessageHandler(MailHandler):
def __init__(self): def __init__(self):
MailHandler.__init__(self) MailHandler.__init__(self)
self.__logger = logging.getLogger("jmc.jabber.component.SendMailMessageHandler") self.__logger = logging.getLogger(\
"jmc.jabber.component.SendMailMessageHandler")
def send_mail_result(self, message, lang, to_email): def send_mail_result(self, message, lang, to_email):
return [Message(from_jid=message.get_to(), return [Message(from_jid=message.get_to(),
@@ -206,23 +225,27 @@ class SendMailMessageHandler(MailHandler):
def handle(self, message, lang, accounts): def handle(self, message, lang, accounts):
to_node = message.get_to().node to_node = message.get_to().node
to_email = to_node.replace('%', '@', 1) to_email = to_node.replace('%', '@', 1)
accounts[0].send_email(to_email, message.get_subject(), message.get_body()) accounts[0].send_email(to_email,
message.get_subject(),
message.get_body())
return self.send_mail_result(message, lang, to_email) return self.send_mail_result(message, lang, to_email)
class RootSendMailMessageHandler(SendMailMessageHandler): class RootSendMailMessageHandler(SendMailMessageHandler):
def __init__(self): def __init__(self):
SendMailMessageHandler.__init__(self) SendMailMessageHandler.__init__(self)
self.to_regexp = re.compile("^\s*(to|TO)\s*:\s*(?P<to_email>.*)") self.to_regexp = re.compile("^\s*(to|TO)\s*:\s*(?P<to_email>.*)")
self.__logger = logging.getLogger("jmc.jabber.component.RootSendMailMessageHandler") self.__logger = logging.getLogger(\
"jmc.jabber.component.RootSendMailMessageHandler")
def filter(self, message): def filter(self, message):
name = message.get_to().node name = message.get_to().node
bare_from_jid = unicode(message.get_from().bare()) bare_from_jid = unicode(message.get_from().bare())
accounts = Account.select(\ accounts = Account.select(\
AND(Account.q.name == name, \ AND(Account.q.name == name,
Account.q.user_jid == bare_from_jid)) Account.q.user_jid == bare_from_jid))
if accounts.count() != 1: if accounts.count() != 1:
self.__logger.error("Account " + name + " for user " + bare_from_jid + " must be uniq") self.__logger.error("Account " + name + " for user " + \
bare_from_jid + " must be uniq")
return accounts return accounts
def handle(self, message, lang, accounts): def handle(self, message, lang, accounts):
@@ -239,7 +262,8 @@ class RootSendMailMessageHandler(SendMailMessageHandler):
message_body.append(line) message_body.append(line)
message_body.extend(lines) message_body.extend(lines)
if to_email is not None: if to_email is not None:
accounts[0].send_email(to_email, message.get_subject(), "".join(message_body)) accounts[0].send_email(to_email, message.get_subject(),
"\n".join(message_body))
return self.send_mail_result(message, lang, to_email) return self.send_mail_result(message, lang, to_email)
else: else:
return [Message(from_jid=message.get_to(), return [Message(from_jid=message.get_to(),
@@ -267,7 +291,7 @@ class MailUnsubscribeHandler(DefaultUnsubscribeHandler, MailHandler):
def __init__(self): def __init__(self):
DefaultUnsubscribeHandler.__init__(self) DefaultUnsubscribeHandler.__init__(self)
MailHandler.__init__(self) MailHandler.__init__(self)
def filter(self, stanza): def filter(self, stanza):
return MailHandler.filter(self, stanza) return MailHandler.filter(self, stanza)

View File

@@ -560,48 +560,45 @@ class RootSendMailMessageHandler_TestCase(unittest.TestCase):
def test_filter(self): def test_filter(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = SMTPAccount(user_jid = "user1@test.com", \ account11 = SMTPAccount(user_jid="user1@test.com",
name = "account11", \ name="account11",
jid = "account11@jcl.test.com") jid="account11@jcl.test.com")
account12 = SMTPAccount(user_jid = "user1@test.com", \ account12 = SMTPAccount(user_jid="user1@test.com",
name = "account12", \ name="account12",
jid = "account12@jcl.test.com") jid="account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \ message = Message(from_jid="user1@test.com",
to_jid = "account11@jcl.test.com", \ to_jid="account11@jcl.test.com",
stanza_type = "normal", \ body="message")
body = "message")
accounts = self.handler.filter(message) accounts = self.handler.filter(message)
self.assertEquals(accounts.count(), 1) self.assertEquals(accounts.count(), 1)
del account.hub.threadConnection del account.hub.threadConnection
def test_filter_wrong_dest(self): def test_filter_wrong_dest(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = SMTPAccount(user_jid = "user1@test.com", \ account11 = SMTPAccount(user_jid="user1@test.com",
name = "account11", \ name="account11",
jid = "account11@jcl.test.com") jid="account11@jcl.test.com")
account12 = SMTPAccount(user_jid = "user1@test.com", \ account12 = SMTPAccount(user_jid="user1@test.com",
name = "account12", \ name="account12",
jid = "account12@jcl.test.com") jid="account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \ message = Message(from_jid="user1@test.com",
to_jid = "user2%test.com@jcl.test.com", \ to_jid="user2%test.com@jcl.test.com",
stanza_type = "normal", \ body="message")
body = "message")
accounts = self.handler.filter(message) accounts = self.handler.filter(message)
self.assertEquals(accounts.count(), 0) self.assertEquals(accounts.count(), 0)
del account.hub.threadConnection del account.hub.threadConnection
def test_filter_wrong_user(self): def test_filter_wrong_user(self):
account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL) account.hub.threadConnection = connectionForURI('sqlite://' + DB_URL)
account11 = SMTPAccount(user_jid = "user1@test.com", \ account11 = SMTPAccount(user_jid="user1@test.com",
name = "account11", \ name="account11",
jid = "account11@jcl.test.com") jid="account11@jcl.test.com")
account12 = SMTPAccount(user_jid = "user1@test.com", \ account12 = SMTPAccount(user_jid="user1@test.com",
name = "account12", \ name="account12",
jid = "account12@jcl.test.com") jid="account12@jcl.test.com")
message = Message(from_jid = "user2@test.com", \ message = Message(from_jid="user2@test.com",
to_jid = "account11@jcl.test.com", \ to_jid="account11@jcl.test.com",
stanza_type = "normal", \ body="message")
body = "message")
accounts = self.handler.filter(message) accounts = self.handler.filter(message)
self.assertEquals(accounts.count(), 0) self.assertEquals(accounts.count(), 0)
del account.hub.threadConnection del account.hub.threadConnection
@@ -611,7 +608,7 @@ class RootSendMailMessageHandler_TestCase(unittest.TestCase):
to_jid="jcl.test.com", to_jid="jcl.test.com",
subject="message subject", subject="message subject",
body="to: user@test.com\n" \ body="to: user@test.com\n" \
"message body") "message body\nother line")
class MockSMTPAccount(object): class MockSMTPAccount(object):
def send_email(self, to_email, subject, body): def send_email(self, to_email, subject, body):
self.to_email = to_email self.to_email = to_email
@@ -621,7 +618,7 @@ class RootSendMailMessageHandler_TestCase(unittest.TestCase):
result = self.handler.handle(message, Lang.en, accounts) result = self.handler.handle(message, Lang.en, accounts)
self.assertEquals(accounts[0].to_email, "user@test.com") self.assertEquals(accounts[0].to_email, "user@test.com")
self.assertEquals(accounts[0].subject, "message subject") self.assertEquals(accounts[0].subject, "message subject")
self.assertEquals(accounts[0].body, "message body") self.assertEquals(accounts[0].body, "message body\nother line")
self.assertEquals(len(result), 1) self.assertEquals(len(result), 1)
self.assertEquals(result[0].get_type(), None) self.assertEquals(result[0].get_type(), None)
self.assertEquals(result[0].get_from(), "jcl.test.com") self.assertEquals(result[0].get_from(), "jcl.test.com")
@@ -683,7 +680,6 @@ class MailHandler_TestCase(unittest.TestCase):
jid = "account12@jcl.test.com") jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \ message = Message(from_jid = "user1@test.com", \
to_jid = "user2%test.com@jcl.test.com", \ to_jid = "user2%test.com@jcl.test.com", \
stanza_type = "normal", \
body = "message") body = "message")
accounts = self.handler.filter(message) accounts = self.handler.filter(message)
self.assertNotEquals(accounts, None) self.assertNotEquals(accounts, None)
@@ -701,7 +697,6 @@ class MailHandler_TestCase(unittest.TestCase):
jid = "account12@jcl.test.com") jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \ message = Message(from_jid = "user1@test.com", \
to_jid = "user2%test.com@jcl.test.com", \ to_jid = "user2%test.com@jcl.test.com", \
stanza_type = "normal", \
body = "message") body = "message")
accounts = self.handler.filter(message) accounts = self.handler.filter(message)
self.assertNotEquals(accounts, None) self.assertNotEquals(accounts, None)
@@ -719,7 +714,6 @@ class MailHandler_TestCase(unittest.TestCase):
jid = "account12@jcl.test.com") jid = "account12@jcl.test.com")
message = Message(from_jid = "user1@test.com", \ message = Message(from_jid = "user1@test.com", \
to_jid = "user2test.com@jcl.test.com", \ to_jid = "user2test.com@jcl.test.com", \
stanza_type = "normal", \
body = "message") body = "message")
accounts = self.handler.filter(message) accounts = self.handler.filter(message)
self.assertEquals(accounts, None) self.assertEquals(accounts, None)
@@ -735,7 +729,6 @@ class MailHandler_TestCase(unittest.TestCase):
jid = "account12@jcl.test.com") jid = "account12@jcl.test.com")
message = Message(from_jid = "user3@test.com", \ message = Message(from_jid = "user3@test.com", \
to_jid = "user2%test.com@jcl.test.com", \ to_jid = "user2%test.com@jcl.test.com", \
stanza_type = "normal", \
body = "message") body = "message")
try: try:
accounts = self.handler.filter(message) accounts = self.handler.filter(message)

View File

@@ -44,7 +44,7 @@ POP3_TIMEOUT = 10
## All MY* classes are implemented to add a timeout (settimeout) ## All MY* classes are implemented to add a timeout (settimeout)
## while connecting ## while connecting
class MYIMAP4(imaplib.IMAP4): class MYIMAP4(imaplib.IMAP4):
def open(self, host = '', port = imaplib.IMAP4_PORT): def open(self, host='', port=imaplib.IMAP4_PORT):
"""Setup connection to remote server on "host:port" """Setup connection to remote server on "host:port"
(default: localhost:standard IMAP4 port). (default: localhost:standard IMAP4 port).
This connection will be used by the routines: This connection will be used by the routines:
@@ -59,7 +59,7 @@ class MYIMAP4(imaplib.IMAP4):
self.file = self.sock.makefile('rb') self.file = self.sock.makefile('rb')
class MYIMAP4_SSL(imaplib.IMAP4_SSL): class MYIMAP4_SSL(imaplib.IMAP4_SSL):
def open(self, host = '', port = imaplib.IMAP4_SSL_PORT): def open(self, host='', port=imaplib.IMAP4_SSL_PORT):
"""Setup connection to remote server on "host:port". """Setup connection to remote server on "host:port".
(default: localhost:standard IMAP4 SSL port). (default: localhost:standard IMAP4 SSL port).
This connection will be used by the routines: This connection will be used by the routines:
@@ -74,12 +74,15 @@ class MYIMAP4_SSL(imaplib.IMAP4_SSL):
self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile)
class MYPOP3(poplib.POP3): class MYPOP3(poplib.POP3):
def __init__(self, host, port = poplib.POP3_PORT): def __init__(self, host, port=poplib.POP3_PORT):
self.host = host self.host = host
self.port = port self.port = port
msg = "getaddrinfo returns an empty list" msg = "getaddrinfo returns an empty list"
self.sock = None self.sock = None
for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): for res in socket.getaddrinfo(self.host,
self.port,
0,
socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res af, socktype, proto, canonname, sa = res
try: try:
self.sock = socket.socket(af, socktype, proto) self.sock = socket.socket(af, socktype, proto)
@@ -99,7 +102,8 @@ class MYPOP3(poplib.POP3):
self.welcome = self._getresp() self.welcome = self._getresp()
class MYPOP3_SSL(poplib.POP3_SSL): class MYPOP3_SSL(poplib.POP3_SSL):
def __init__(self, host, port = poplib.POP3_SSL_PORT, keyfile = None, certfile = None): def __init__(self, host, port=poplib.POP3_SSL_PORT, keyfile=None,
certfile=None):
self.host = host self.host = host
self.port = port self.port = port
self.keyfile = keyfile self.keyfile = keyfile
@@ -107,7 +111,8 @@ class MYPOP3_SSL(poplib.POP3_SSL):
self.buffer = "" self.buffer = ""
msg = "getaddrinfo returns an empty list" msg = "getaddrinfo returns an empty list"
self.sock = None self.sock = None
for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): for res in socket.getaddrinfo(self.host, self.port, 0,
socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res af, socktype, proto, canonname, sa = res
try: try:
self.sock = socket.socket(af, socktype, proto) self.sock = socket.socket(af, socktype, proto)
@@ -129,28 +134,29 @@ class MYPOP3_SSL(poplib.POP3_SSL):
class MailAccount(PresenceAccount): class MailAccount(PresenceAccount):
""" Wrapper to mail connection and action. """ Wrapper to mail connection and action.
Abstract class, do not represent real mail connection type""" Abstract class, do not represent real mail connection type.
"""
# Define constants # Define constants
DIGEST = 1 DIGEST = 1
RETRIEVE = 2 RETRIEVE = 2
default_encoding = "utf-8" default_encoding = "utf-8"
possibles_actions = [PresenceAccount.DO_NOTHING, \ possibles_actions = [PresenceAccount.DO_NOTHING,
DIGEST, \ DIGEST,
RETRIEVE] RETRIEVE]
login = StringCol(default = "") login = StringCol(default="")
password = StringCol(default = None) password = StringCol(default=None)
host = StringCol(default = "localhost") host = StringCol(default="localhost")
port = IntCol(default = 110) port = IntCol(default=110)
ssl = BoolCol(default = False) ssl = BoolCol(default=False)
interval = IntCol(default = 5) interval = IntCol(default=5)
store_password = BoolCol(default = True) store_password = BoolCol(default=True)
live_email_only = BoolCol(default = False) live_email_only = BoolCol(default=False)
lastcheck = IntCol(default = 0) lastcheck = IntCol(default=0)
waiting_password_reply = BoolCol(default = False) waiting_password_reply = BoolCol(default=False)
first_check = BoolCol(default = True) first_check = BoolCol(default=True)
def _init(self, *args, **kw): def _init(self, *args, **kw):
"""MailAccount init """MailAccount init
@@ -161,7 +167,7 @@ class MailAccount(PresenceAccount):
self.connected = False self.connected = False
self.default_lang_class = Lang.en self.default_lang_class = Lang.en
def _get_register_fields(cls, real_class = None): def _get_register_fields(cls, real_class=None):
"""See Account._get_register_fields """See Account._get_register_fields
""" """
def password_post_func(password, default_func): def password_post_func(password, default_func):
@@ -172,29 +178,31 @@ class MailAccount(PresenceAccount):
if real_class is None: if real_class is None:
real_class = cls real_class = cls
return PresenceAccount.get_register_fields(real_class) + \ return PresenceAccount.get_register_fields(real_class) + \
[("login", "text-single", None, \ [("login", "text-single", None,
lambda field_value, default_func: account.mandatory_field(field_value), \ lambda field_value, default_func: \
lambda : ""), \ account.mandatory_field(field_value),
("password", "text-private", None, password_post_func, \ lambda : ""),
lambda : ""), \ ("password", "text-private", None, password_post_func,
("host", "text-single", None, \ lambda : ""),
lambda field_value, default_func: account.mandatory_field(field_value), \ ("host", "text-single", None,
lambda : ""), \ lambda field_value, default_func: \
("port", "text-single", None, \ account.mandatory_field(field_value),
account.int_post_func, \ lambda : ""),
lambda : real_class.get_default_port()), \ ("port", "text-single", None,
("ssl", "boolean", None, \ account.int_post_func,
account.default_post_func, \ lambda : real_class.get_default_port()),
lambda : False), \ ("ssl", "boolean", None,
("store_password", "boolean", None, \ account.default_post_func,
account.default_post_func, \ lambda : False),
lambda : True), \ ("store_password", "boolean", None,
("live_email_only", "boolean", None, \ account.default_post_func,
account.default_post_func, \ lambda : True),
lambda : False), \ ("live_email_only", "boolean", None,
("interval", "text-single", None, \ account.default_post_func,
account.int_post_func, \ lambda : False),
lambda : 5)] ("interval", "text-single", None,
account.int_post_func,
lambda : 5)]
get_register_fields = classmethod(_get_register_fields) get_register_fields = classmethod(_get_register_fields)
@@ -205,17 +213,17 @@ class MailAccount(PresenceAccount):
def _get_presence_actions_fields(cls): def _get_presence_actions_fields(cls):
"""See PresenceAccount._get_presence_actions_fields """See PresenceAccount._get_presence_actions_fields
""" """
return {'chat_action': (cls.possibles_actions, \ return {'chat_action': (cls.possibles_actions,
MailAccount.RETRIEVE), \ MailAccount.RETRIEVE),
'online_action': (cls.possibles_actions, \ 'online_action': (cls.possibles_actions,
MailAccount.RETRIEVE), \ MailAccount.RETRIEVE),
'away_action': (cls.possibles_actions, \ 'away_action': (cls.possibles_actions,
MailAccount.DIGEST), \ MailAccount.DIGEST),
'xa_action': (cls.possibles_actions, \ 'xa_action': (cls.possibles_actions,
MailAccount.DIGEST), \ MailAccount.DIGEST),
'dnd_action': (cls.possibles_actions, \ 'dnd_action': (cls.possibles_actions,
MailAccount.DIGEST), \ MailAccount.DIGEST),
'offline_action': (cls.possibles_actions, \ 'offline_action': (cls.possibles_actions,
PresenceAccount.DO_NOTHING)} PresenceAccount.DO_NOTHING)}
get_presence_actions_fields = classmethod(_get_presence_actions_fields) get_presence_actions_fields = classmethod(_get_presence_actions_fields)
@@ -223,25 +231,27 @@ class MailAccount(PresenceAccount):
def get_decoded_part(self, part, charset_hint): def get_decoded_part(self, part, charset_hint):
content_charset = part.get_content_charset() content_charset = part.get_content_charset()
result = u"" result = u""
payload = part.get_payload(decode=True)
try: try:
if content_charset: if content_charset:
result = unicode(part.get_payload(decode=True).decode(content_charset)) result = unicode(payload.decode(content_charset))
else: else:
result = unicode(part.get_payload(decode=True).decode(MailAccount.default_encoding)) result = unicode(payload.decode(MailAccount.default_encoding))
except Exception, e: except Exception, e:
try: try:
result = unicode(part.get_payload(decode=True)) result = unicode(payload)
except Exception, e: except Exception, e:
try: try:
result = unicode(part.get_payload(decode=True).decode("iso-8859-1")) result = unicode(payload.decode("iso-8859-1"))
except Exception, e: except Exception, e:
if charset_hint is not None: if charset_hint is not None:
try: try:
result = unicode(part.get_payload(decode=True).decode(charset_hint)) result = unicode(payload.decode(charset_hint))
except Exception, e: except Exception, e:
type, value, stack = sys.exc_info() type, value, stack = sys.exc_info()
print >>sys.stderr, "".join(traceback.format_exception print >>sys.stderr, \
(type, value, stack, 5)) "".join(traceback.format_exception
(type, value, stack, 5))
return result return result
@@ -254,19 +264,23 @@ class MailAccount(PresenceAccount):
try: try:
if from_decoded[i][1]: if from_decoded[i][1]:
charset_hint = from_decoded[i][1] charset_hint = from_decoded[i][1]
email_from += unicode(from_decoded[i][0].decode(from_decoded[i][1])) email_from += unicode(from_decoded[i][0].decode(\
from_decoded[i][1]))
else: else:
email_from += unicode(from_decoded[i][0].decode(MailAccount.default_encoding)) email_from += unicode(from_decoded[i][0].decode(\
MailAccount.default_encoding))
except Exception,e: except Exception,e:
try: try:
email_from += unicode(from_decoded[i][0]) email_from += unicode(from_decoded[i][0])
except Exception, e: except Exception, e:
try: try:
email_from += unicode(from_decoded[i][0].decode("iso-8859-1")) email_from += unicode(from_decoded[i][0].decode(\
"iso-8859-1"))
except Exception, e: except Exception, e:
type, value, stack = sys.exc_info() type, value, stack = sys.exc_info()
print >>sys.stderr, "".join(traceback.format_exception print >>sys.stderr, \
(type, value, stack, 5)) "".join(traceback.format_exception
(type, value, stack, 5))
result += email_from + u"\n" result += email_from + u"\n"
subject_decoded = email.Header.decode_header(email_msg["Subject"]) subject_decoded = email.Header.decode_header(email_msg["Subject"])
@@ -275,29 +289,35 @@ class MailAccount(PresenceAccount):
try: try:
if subject_decoded[i][1]: if subject_decoded[i][1]:
charset_hint = subject_decoded[i][1] charset_hint = subject_decoded[i][1]
result += unicode(subject_decoded[i][0].decode(subject_decoded[i][1])) result += unicode(subject_decoded[i][0].decode(\
subject_decoded[i][1]))
else: else:
result += unicode(subject_decoded[i][0].decode(MailAccount.default_encoding)) result += unicode(subject_decoded[i][0].decode(\
MailAccount.default_encoding))
except Exception,e: except Exception,e:
try: try:
result += unicode(subject_decoded[i][0]) result += unicode(subject_decoded[i][0])
except Exception, e: except Exception, e:
try: try:
result += unicode(subject_decoded[i][0].decode("iso-8859-1")) result += unicode(subject_decoded[i][0].decode(\
"iso-8859-1"))
except Exception, e: except Exception, e:
if charset_hint is not None: if charset_hint is not None:
try: try:
result += unicode(subject_decoded[i][0].decode(charset_hint)) result += unicode(subject_decoded[i][0].decode(\
charset_hint))
except Exception, e: except Exception, e:
type, value, stack = sys.exc_info() type, value, stack = sys.exc_info()
print >>sys.stderr, "".join(traceback.format_exception print >>sys.stderr, \
(type, value, stack, 5)) "".join(traceback.format_exception
(type, value, stack, 5))
result += u"\n\n" result += u"\n\n"
if include_body: if include_body:
action = { action = {
"text/plain" : lambda part: self.get_decoded_part(part, charset_hint), "text/plain" : lambda part: \
self.get_decoded_part(part, charset_hint),
"text/html" : lambda part: "\n<<<HTML part skipped>>>\n" "text/html" : lambda part: "\n<<<HTML part skipped>>>\n"
} }
for part in email_msg.walk(): for part in email_msg.walk():
@@ -339,9 +359,9 @@ class MailAccount(PresenceAccount):
raise NotImplementedError raise NotImplementedError
class IMAPAccount(MailAccount): class IMAPAccount(MailAccount):
mailbox = StringCol(default = "INBOX") mailbox = StringCol(default="INBOX")
def _get_register_fields(cls, real_class = None): def _get_register_fields(cls, real_class=None):
"""See Account._get_register_fields """See Account._get_register_fields
""" """
def password_post_func(password): def password_post_func(password):
@@ -352,9 +372,9 @@ class IMAPAccount(MailAccount):
if real_class is None: if real_class is None:
real_class = cls real_class = cls
return MailAccount.get_register_fields(real_class) + \ return MailAccount.get_register_fields(real_class) + \
[("mailbox", "text-single", None, \ [("mailbox", "text-single", None,
account.default_post_func, \ account.default_post_func,
lambda : "INBOX")] lambda : "INBOX")]
get_register_fields = classmethod(_get_register_fields) get_register_fields = classmethod(_get_register_fields)
@@ -377,10 +397,10 @@ class IMAPAccount(MailAccount):
return MailAccount.get_status(self) + "/" + self.mailbox return MailAccount.get_status(self) + "/" + self.mailbox
def connect(self): def connect(self):
self.__logger.debug("Connecting to IMAP server " \ self.__logger.debug("Connecting to IMAP server "
+ self.login + "@" + self.host + ":" + str(self.port) \ + self.login + "@" + self.host + ":" + str(self.port)
+ " (" + self.mailbox + "). SSL=" \ + " (" + self.mailbox + "). SSL="
+ str(self.ssl)) + str(self.ssl))
if self.ssl: if self.ssl:
self.connection = MYIMAP4_SSL(self.host, self.port) self.connection = MYIMAP4_SSL(self.host, self.port)
else: else:
@@ -389,8 +409,8 @@ class IMAPAccount(MailAccount):
self.connected = True self.connected = True
def disconnect(self): def disconnect(self):
self.__logger.debug("Disconnecting from IMAP server " \ self.__logger.debug("Disconnecting from IMAP server "
+ self.host) + self.host)
self.connection.logout() self.connection.logout()
self.connected = False self.connected = False
@@ -407,7 +427,8 @@ class IMAPAccount(MailAccount):
typ, data = self.connection.select(self.mailbox, True) typ, data = self.connection.select(self.mailbox, True)
typ, data = self.connection.fetch(index, '(RFC822)') typ, data = self.connection.fetch(index, '(RFC822)')
if typ == 'OK': if typ == 'OK':
return self.format_message(email.message_from_string(data[0][1])) return self.format_message(\
email.message_from_string(data[0][1]))
return u"Error while fetching mail " + str(index) return u"Error while fetching mail " + str(index)
def get_mail_summary(self, index): def get_mail_summary(self, index):
@@ -415,7 +436,8 @@ class IMAPAccount(MailAccount):
typ, data = self.connection.select(self.mailbox, True) typ, data = self.connection.select(self.mailbox, True)
typ, data = self.connection.fetch(index, '(RFC822)') typ, data = self.connection.fetch(index, '(RFC822)')
if typ == 'OK': if typ == 'OK':
return self.format_message_summary(email.message_from_string(data[0][1])) return self.format_message_summary(\
email.message_from_string(data[0][1]))
return u"Error while fetching mail " + str(index) return u"Error while fetching mail " + str(index)
def get_next_mail_index(self, mail_list): def get_next_mail_index(self, mail_list):
@@ -430,8 +452,8 @@ class IMAPAccount(MailAccount):
type = property(get_type) type = property(get_type)
class POP3Account(MailAccount): class POP3Account(MailAccount):
nb_mail = IntCol(default = 0) nb_mail = IntCol(default=0)
lastmail = IntCol(default = 0) lastmail = IntCol(default=0)
def _init(self, *args, **kw): def _init(self, *args, **kw):
MailAccount._init(self, *args, **kw) MailAccount._init(self, *args, **kw)
@@ -451,9 +473,9 @@ class POP3Account(MailAccount):
type = property(get_type) type = property(get_type)
def connect(self): def connect(self):
self.__logger.debug("Connecting to POP3 server " \ self.__logger.debug("Connecting to POP3 server "
+ self.login + "@" + self.host + ":" + str(self.port)\ + self.login + "@" + self.host + ":" +
+ ". SSL=" + str(self.ssl)) str(self.port) + ". SSL=" + str(self.ssl))
if self.ssl: if self.ssl:
self.connection = MYPOP3_SSL(self.host, self.port) self.connection = MYPOP3_SSL(self.host, self.port)
else: else:
@@ -467,7 +489,7 @@ class POP3Account(MailAccount):
def disconnect(self): def disconnect(self):
self.__logger.debug("Disconnecting from POP3 server " \ self.__logger.debug("Disconnecting from POP3 server "
+ self.host) + self.host)
self.connection.quit() self.connection.quit()
self.connected = False self.connected = False
@@ -486,7 +508,8 @@ class POP3Account(MailAccount):
except: except:
pass pass
if ret[0:3] == '+OK': if ret[0:3] == '+OK':
return self.format_message(email.message_from_string('\n'.join(data))) return self.format_message(email.message_from_string(\
'\n'.join(data)))
return u"Error while fetching mail " + str(index) return u"Error while fetching mail " + str(index)
def get_mail_summary(self, index): def get_mail_summary(self, index):
@@ -497,7 +520,8 @@ class POP3Account(MailAccount):
except: except:
pass pass
if ret[0:3] == '+OK': if ret[0:3] == '+OK':
return self.format_message_summary(email.message_from_string('\n'.join(data))) return self.format_message_summary(email.message_from_string(\
'\n'.join(data)))
return u"Error while fetching mail " + str(index) return u"Error while fetching mail " + str(index)
def get_next_mail_index(self, mail_list): def get_next_mail_index(self, mail_list):
@@ -520,15 +544,15 @@ class POP3Account(MailAccount):
class SMTPAccount(Account): class SMTPAccount(Account):
"""Send email account""" """Send email account"""
login = StringCol(default = "") login = StringCol(default="")
password = StringCol(default = None) password = StringCol(default=None)
host = StringCol(default = "localhost") host = StringCol(default="localhost")
port = IntCol(default = 110) port = IntCol(default=110)
ssl = BoolCol(default = False) ssl = BoolCol(default=False)
store_password = BoolCol(default = True) store_password = BoolCol(default=True)
waiting_password_reply = BoolCol(default = False) waiting_password_reply = BoolCol(default=False)
default_from = StringCol(default = "nobody@localhost") default_from = StringCol(default="nobody@localhost")
default_account = BoolCol(default = False) default_account = BoolCol(default=False)
def _init(self, *args, **kw): def _init(self, *args, **kw):
"""SMTPAccount init """SMTPAccount init
@@ -536,7 +560,7 @@ class SMTPAccount(Account):
Account._init(self, *args, **kw) Account._init(self, *args, **kw)
self.__logger = logging.getLogger("jmc.model.account.SMTPAccount") self.__logger = logging.getLogger("jmc.model.account.SMTPAccount")
def _get_register_fields(cls, real_class = None): def _get_register_fields(cls, real_class=None):
"""See Account._get_register_fields """See Account._get_register_fields
""" """
def password_post_func(password, default_func): def password_post_func(password, default_func):
@@ -547,28 +571,35 @@ class SMTPAccount(Account):
if real_class is None: if real_class is None:
real_class = cls real_class = cls
return Account.get_register_fields(real_class) + \ return Account.get_register_fields(real_class) + \
[("login", "text-single", None, \ [("login", "text-single", None,
lambda field_value, default_func: account.mandatory_field(field_value), \ lambda field_value, default_func: \
lambda : ""), \ account.mandatory_field(field_value),
("password", "text-private", None, password_post_func, \ lambda : ""),
lambda : ""), \ ("password", "text-private", None, password_post_func,
("host", "text-single", None, \ lambda : ""),
lambda field_value, default_func: account.mandatory_field(field_value), \ ("host", "text-single", None,
lambda : ""), \ lambda field_value, default_func: \
("port", "text-single", None, \ account.mandatory_field(field_value),
account.int_post_func, \ lambda : ""),
lambda : real_class.get_default_port()), \ ("port", "text-single", None,
("ssl", "boolean", None, \ account.int_post_func,
account.default_post_func, \ lambda : real_class.get_default_port()),
lambda : False), \ ("ssl", "boolean", None,
("default_from", "text-single", None, \ account.default_post_func,
lambda field_value, default_func: account.mandatory_field(field_value), \ lambda : False),
lambda : ""), \ ("default_from", "text-single", None,
("store_password", "boolean", None, \ lambda field_value, default_func: \
account.default_post_func, \ account.mandatory_field(field_value),
lambda : True)] lambda : ""),
("store_password", "boolean", None,
account.default_post_func,
lambda : True)]
get_register_fields = classmethod(_get_register_fields) get_register_fields = classmethod(_get_register_fields)
def send_email(self, to_email, subject, body): def send_email(self, to_email, subject, body):
pass self.__logger.debug("Sending email:\n"
"From: " + self.default_from + "\n" +
"To: " + to_email + "\n" +
"Subject: " + subject + "\n\n" +
body)