Changeset 93

Show
Ignore:
Timestamp:
06/18/07 18:58:13 (2 years ago)
Author:
David Rousselie <dax@happycoders.org>
Message:

SMTP send_email real implementation

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/jmc/jabber/component.py

    r91 r93  
    244244        to_node = message.get_to().node 
    245245        to_email = to_node.replace('%', '@', 1) 
    246         accounts[0].send_email(to_email, 
    247                                message.get_subject(), 
    248                                message.get_body()) 
     246        accounts[0].send_email(\ 
     247            accounts[0].create_email(accounts[0].default_from, 
     248                                     to_email, 
     249                                     message.get_subject(), 
     250                                     message.get_body())) 
    249251        return self.send_mail_result(message, lang_class, to_email) 
    250252 
     
    254256    def __init__(self): 
    255257        SendMailMessageHandler.__init__(self) 
    256         self.to_regexp = re.compile("^\s*(to|TO)\s*:\s*(?P<to_email>.*)") 
     258        self.to_regexp = re.compile("^\s*(to|TO|To)\s*:\s*(?P<to_email>.*)") 
    257259        self.__logger = logging.getLogger(\ 
    258260            "jmc.jabber.component.RootSendMailMessageHandler") 
     
    286288        message_body.extend(lines) 
    287289        if to_email is not None: 
    288             accounts[0].send_email(to_email, message.get_subject(), 
    289                                    "\n".join(message_body)) 
     290            accounts[0].send_email(\ 
     291                accounts[0].create_email(accounts[0].default_from, 
     292                                         to_email, 
     293                                         message.get_subject(), 
     294                                         "\n".join(message_body))) 
    290295            return self.send_mail_result(message, lang_class, to_email) 
    291296        else: 
  • src/jmc/jabber/tests/component.py

    r91 r93  
    143143        MockMailAccount._init(self) 
    144144 
     145class MockSMTPAccount(object): 
     146    def __init__(self): 
     147        self.default_from = "user1@test.com" 
     148       
     149    def create_email(self, from_email, to_email, subject, body): 
     150        return (from_email, to_email, subject, body) 
     151              
     152    def send_email(self, email): 
     153        self.email = email 
     154 
    145155class MailComponent_TestCase(unittest.TestCase): 
    146156    def setUp(self): 
     
    526536                          subject="message subject", 
    527537                          body="message body") 
    528         class MockSMTPAccount(object): 
    529             def send_email(self, to_email, subject, body): 
    530                 self.to_email = to_email 
    531                 self.subject = subject 
    532                 self.body = body 
    533538        accounts = [MockSMTPAccount()] 
    534539        result = self.handler.handle(message, Lang.en, accounts) 
    535         self.assertEquals(accounts[0].to_email, "user@test.com") 
    536         self.assertEquals(accounts[0].subject, "message subject") 
    537         self.assertEquals(accounts[0].body, "message body") 
     540        self.assertEquals(accounts[0].email[1], "user@test.com") 
     541        self.assertEquals(accounts[0].email[2], "message subject") 
     542        self.assertEquals(accounts[0].email[3], "message body") 
    538543        self.assertEquals(len(result), 1) 
    539544        self.assertEquals(result[0].stanza_type, "message") 
     
    633638                          body="to: user@test.com\n" \ 
    634639                             "message body\nother line") 
    635         class MockSMTPAccount(object): 
    636             def send_email(self, to_email, subject, body): 
    637                 self.to_email = to_email 
    638                 self.subject = subject 
    639                 self.body = body 
    640640        accounts = [MockSMTPAccount()] 
    641641        result = self.handler.handle(message, Lang.en, accounts) 
    642         self.assertEquals(accounts[0].to_email, "user@test.com") 
    643         self.assertEquals(accounts[0].subject, "message subject") 
    644         self.assertEquals(accounts[0].body, "message body\nother line") 
     642        self.assertEquals(accounts[0].email[1], "user@test.com") 
     643        self.assertEquals(accounts[0].email[2], "message subject") 
     644        self.assertEquals(accounts[0].email[3], 
     645                          "message body\nother line") 
    645646        self.assertEquals(len(result), 1) 
    646647        self.assertEquals(result[0].get_type(), None) 
     
    657658                          subject="message subject", 
    658659                          body="message body") 
    659         class MockSMTPAccount(object): 
    660             def send_email(self, to_email, subject, body): 
    661                 self.to_email = to_email 
    662                 self.subject = subject 
    663                 self.body = body 
    664660        accounts = [MockSMTPAccount()] 
    665661        result = self.handler.handle(message, Lang.en, accounts) 
  • src/jmc/model/account.py

    r92 r93  
    55## Started on  Fri Jan 19 18:21:44 2007 David Rousselie 
    66## $Id$ 
    7 ##  
     7## 
    88## Copyright (C) 2007 David Rousselie 
    99## This program is free software; you can redistribute it and/or modify 
     
    1111## the Free Software Foundation; either version 2 of the License, or 
    1212## (at your option) any later version. 
    13 ##  
     13## 
    1414## This program is distributed in the hope that it will be useful, 
    1515## but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1616## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1717## GNU General Public License for more details. 
    18 ##  
     18## 
    1919## You should have received a copy of the GNU General Public License 
    2020## along with this program; if not, write to the Free Software 
     
    2525import logging 
    2626import email 
    27 import email.Header 
     27from email.Header import Header 
     28from email.MIMEText import MIMEText 
     29from email.MIMEMultipart import MIMEMultipart 
    2830import traceback 
    2931 
     
    3133import imaplib 
    3234import socket 
     35import smtplib 
    3336 
    3437from sqlobject.inheritance import InheritableSQLObject 
     
    8184        msg = "getaddrinfo returns an empty list" 
    8285        self.sock = None 
    83         for res in socket.getaddrinfo(self.host,  
    84                                       self.port,  
    85                                       0,  
     86        for res in socket.getaddrinfo(self.host, 
     87                                      self.port, 
     88                                      0, 
    8689                                      socket.SOCK_STREAM): 
    8790            af, socktype, proto, canonname, sa = res 
     
    104107 
    105108class MYPOP3_SSL(poplib.POP3_SSL): 
    106     def __init__(self, host, port=poplib.POP3_SSL_PORT, keyfile=None,  
     109    def __init__(self, host, port=poplib.POP3_SSL_PORT, keyfile=None, 
    107110                 certfile=None): 
    108111        self.host = host 
     
    113116        msg = "getaddrinfo returns an empty list" 
    114117        self.sock = None 
    115         for res in socket.getaddrinfo(self.host, self.port, 0,  
     118        for res in socket.getaddrinfo(self.host, self.port, 0, 
    116119                                      socket.SOCK_STREAM): 
    117120            af, socktype, proto, canonname, sa = res 
     
    155158    store_password = BoolCol(default=True) 
    156159    live_email_only = BoolCol(default=False) 
    157      
     160 
    158161    lastcheck = IntCol(default=0) 
    159162    waiting_password_reply = BoolCol(default=False) 
    160163    first_check = BoolCol(default=True) 
    161      
     164 
    162165    def _init(self, *args, **kw): 
    163166        """MailAccount init 
     
    168171        self.connected = False 
    169172        self.default_lang_class = Lang.en 
    170      
     173 
    171174    def _get_register_fields(cls, real_class=None): 
    172175        """See Account._get_register_fields 
     
    205208              account.int_post_func, 
    206209              lambda bare_from_jid: 5)] 
    207      
     210 
    208211    get_register_fields = classmethod(_get_register_fields) 
    209212 
     
    211214        return 42 
    212215    get_default_port = classmethod(_get_default_port) 
    213      
     216 
    214217    def _get_presence_actions_fields(cls): 
    215218        """See PresenceAccount._get_presence_actions_fields 
     
    227230                'offline_action': (cls.possibles_actions, 
    228231                                   PresenceAccount.DO_NOTHING)} 
    229      
     232 
    230233    get_presence_actions_fields = classmethod(_get_presence_actions_fields) 
    231234 
     
    256259 
    257260        return result 
    258              
     261 
    259262    def format_message(self, email_msg, include_body = True): 
    260263        from_decoded = email.Header.decode_header(email_msg["From"]) 
     
    313316                                    "".join(traceback.format_exception 
    314317                                            (type, value, stack, 5)) 
    315                                  
     318 
    316319        result += u"\n\n" 
    317320 
     
    330333    def format_message_summary(self, email_msg): 
    331334        return self.format_message(email_msg, False) 
    332          
     335 
    333336    def get_status_msg(self): 
    334337        return self.get_type() + "://" + self.login + "@" + self.host + ":" + \ 
     
    372375              account.default_post_func, 
    373376              lambda bare_from_jid: "INBOX")] 
    374      
     377 
    375378    get_register_fields = classmethod(_get_register_fields) 
    376379 
     
    378381        """Return default IMAP server port""" 
    379382        return 143 
    380      
     383 
    381384    get_default_port = classmethod(_get_default_port) 
    382385 
     
    389392            return "imaps" 
    390393        return "imap" 
    391              
     394 
    392395    def get_status(self): 
    393396        return MailAccount.get_status(self) + "/" + self.mailbox 
     
    427430                email.message_from_string(data[0][1])) 
    428431        return u"Error while fetching mail " + str(index) 
    429          
     432 
    430433    def get_mail_summary(self, index): 
    431434        self.__logger.debug("Getting mail summary " + str(index)) 
     
    445448    def mark_all_as_read(self): 
    446449        self.get_mail_list() 
    447      
     450 
    448451    type = property(get_type) 
    449452 
     
    451454    nb_mail = IntCol(default=0) 
    452455    lastmail = IntCol(default=0) 
    453      
     456 
    454457    def _init(self, *args, **kw): 
    455458        MailAccount._init(self, *args, **kw) 
     
    459462        """Return default POP3 server port""" 
    460463        return 110 
    461      
     464 
    462465    get_default_port = classmethod(_get_default_port) 
    463466 
     
    471474    def connect(self): 
    472475        self.__logger.debug("Connecting to POP3 server " 
    473                             + self.login + "@" + self.host + ":" +  
     476                            + self.login + "@" + self.host + ":" + 
    474477                            str(self.port) + ". SSL=" + str(self.ssl)) 
    475478        if self.ssl: 
     
    483486          self.connection.pass_(self.password) 
    484487        self.connected = True 
    485          
     488 
    486489 
    487490    def disconnect(self): 
     
    494497        self.__logger.debug("Getting mail list") 
    495498        count, size = self.connection.stat() 
    496         self.nb_mail = count  
     499        self.nb_mail = count 
    497500        return [str(i) for i in range(1, count + 1)] 
    498501 
     
    536539        self.get_mail_list() 
    537540        self.lastmail = self.nb_mail 
    538          
     541 
    539542 
    540543class SMTPAccount(Account): 
     
    560563        """Return default SMTP server port""" 
    561564        return 25 
    562      
     565 
    563566    get_default_port = classmethod(_get_default_port) 
    564567 
     
    629632              default_account_post_func, 
    630633              default_account_default_func)] 
    631      
     634 
    632635    get_register_fields = classmethod(_get_register_fields) 
    633636 
    634     def send_email(self, to_email, subject, body): 
     637    def create_email(self, from_email, to_email, subject, body): 
     638        """Create new email""" 
     639        email = MIMEText(body) 
     640        email['Subject'] = Header(str(subject)) 
     641        email['From'] = Header(str(from_email)) 
     642        email['To'] = Header(str(to_email)) 
     643        return email 
     644 
     645    def __say_hello(self, connection): 
     646        if not (200 <= connection.ehlo()[0] <= 299): 
     647            (code, resp) = connection.helo() 
     648            if not (200 <= code <= 299): 
     649                raise SMTPHeloError(code, resp) 
     650 
     651    def send_email(self, email): 
     652        """Send email according to current account parameters""" 
    635653        self.__logger.debug("Sending email:\n" 
    636                             "From: " + self.default_from + "\n" + 
    637                             "To: " + to_email + "\n" + 
    638                             "Subject: " + subject + "\n\n" + 
    639                             body) 
     654                            + str(email)) 
     655        smtp_connection = smtplib.SMTP() 
     656        if self.__logger.getEffectiveLevel() == logging.DEBUG: 
     657            smtp_connection.set_debuglevel(1) 
     658        smtp_connection.connect(self.host, self.port) 
     659        self.__say_hello(smtp_connection) 
     660        if self.tls: 
     661            smtp_connection.starttls() 
     662            self.__say_hello(smtp_connection) 
     663        if self.login is not None and len(self.login) > 0: 
     664            auth_methods = smtp_connection.esmtp_features["auth"].split() 
     665            auth_methods.reverse() 
     666            current_error = None 
     667            for auth_method in auth_methods: 
     668                self.__logger.debug("Trying to authenticate using " 
     669                                    + auth_method + " method") 
     670                smtp_connection.esmtp_features["auth"] = auth_method 
     671                try: 
     672                    smtp_connection.login(self.login, self.password) 
     673                    current_error = None 
     674                    self.__logger.debug("Successfuly to authenticate using " 
     675                                        + auth_method + " method") 
     676                    break 
     677                except smtplib.SMTPAuthenticationError, error: 
     678                    self.__logger.debug("Failed to authenticate using " 
     679                                        + auth_method + " method") 
     680                    current_error = error 
     681            if current_error is not None: 
     682                raise current_error 
     683        smtp_connection.sendmail(str(email['From']), str(email['To']), 
     684                                 email.as_string()) 
     685        smtp_connection.quit() 
  • src/jmc/model/tests/account.py

    r88 r93  
    55## Started on  Wed Feb 14 08:23:17 2007 David Rousselie 
    66## $Id$ 
    7 ##  
     7## 
    88## Copyright (C) 2007 David Rousselie 
    99## This program is free software; you can redistribute it and/or modify 
     
    1111## the Free Software Foundation; either version 2 of the License, or 
    1212## (at your option) any later version. 
    13 ##  
     13## 
    1414## This program is distributed in the hope that it will be useful, 
    1515## but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1616## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1717## GNU General Public License for more details. 
    18 ##  
     18## 
    1919## You should have received a copy of the GNU General Public License 
    2020## along with this program; if not, write to the Free Software 
     
    169169        del account.hub.threadConnection 
    170170        self.account_class = POP3Account 
    171          
     171 
    172172    def tearDown(self): 
    173173        account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url) 
     
    211211 
    212212    test_connection = make_test() 
    213      
     213 
    214214    test_get_mail_list = \ 
    215215        make_test(["+OK 2 20\r\n"], \ 
     
    341341            self.failUnless(self.server.verify_queries()) 
    342342        return inner 
    343              
     343 
    344344    test_connection = make_test() 
    345345 
     
    434434        self.assertTrue(value) 
    435435        del account.hub.threadConnection 
    436          
     436 
    437437    def test_default_account_post_func_true(self): 
    438438        account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url) 
     
    467467        del account.hub.threadConnection 
    468468 
     469    def test_create_email(self): 
     470        account.hub.threadConnection = connectionForURI('sqlite://' + self.db_url) 
     471        account11 = SMTPAccount(user_jid="user1@test.com", 
     472                                name="account11", 
     473                                jid="account11@jmc.test.com") 
     474        del account.hub.threadConnection 
     475        email = account11.create_email("from@test.com", 
     476                                       "to@test.com", 
     477                                       "subject", 
     478                                       "body") 
     479        self.assertEqual(email['From'], "from@test.com") 
     480        self.assertEqual(email['To'], "to@test.com") 
     481        self.assertEqual(email['Subject'], "subject") 
     482        self.assertEqual(email.get_payload(), "body") 
     483 
     484    def make_test(self, responses=None, queries=None, core=None): 
     485        def inner(): 
     486            self.server = server.DummyServer("localhost", 1025) 
     487            thread.start_new_thread(self.server.serve, ()) 
     488            self.server.responses = [] 
     489            if responses: 
     490                self.server.responses += responses 
     491            self.server.responses += ["221 localhost closing connection\r\n"] 
     492            self.server.queries = [] 
     493            if queries: 
     494                self.server.queries += queries 
     495            self.server.queries += ["quit\r\n"] 
     496            if core: 
     497                account.hub.threadConnection = connectionForURI('sqlite://' 
     498                                                                + self.db_url) 
     499                core(self) 
     500                del account.hub.threadConnection 
     501            self.failUnless(self.server.verify_queries()) 
     502        return inner 
     503 
     504    def test_send_email_esmtp_no_auth(self): 
     505       account.hub.threadConnection = connectionForURI('sqlite://' 
     506                                                       + self.db_url) 
     507       smtp_account = SMTPAccount(user_jid="user1@test.com", 
     508                                  name="account11", 
     509                                  jid="account11@jmc.test.com") 
     510       smtp_account.host = "localhost" 
     511       smtp_account.port = 1025 
     512       del account.hub.threadConnection 
     513       email = smtp_account.create_email("from@test.com", 
     514                                         "to@test.com", 
     515                                         "subject", 
     516                                         "body") 
     517       test_func = self.make_test(["220 localhost ESMTP\r\n", 
     518                                   "250-localhost Hello 127.0.0.1\r\n" 
     519                                   + "250-SIZE 52428800\r\n" 
     520                                   + "250-PIPELINING\r\n" 
     521                                   + "250 HELP\r\n", 
     522                                   "250 OK\r\n", 
     523                                   "250 Accepted\r\n", 
     524                                   "354 Enter message\r\n", 
     525                                   None, None, None, None, 
     526                                   None, None, None, None, 
     527                                   "250 OK\r\n"], 
     528                                  ["ehlo \[127.0.0.1\]\r\n", 
     529                                   "mail FROM:<" + str(email['From']) + ">.*", 
     530                                   "rcpt TO:<" + str(email['To']) + ">\r\n", 
     531                                   "data\r\n"] + 
     532                                   email.as_string().split("\n") + [".\r\n"], 
     533                                  lambda self: \ 
     534                                  smtp_account.send_email(email)) 
     535       test_func() 
     536 
     537    def test_send_email_no_auth(self): 
     538       account.hub.threadConnection = connectionForURI('sqlite://' 
     539                                                       + self.db_url) 
     540       smtp_account = SMTPAccount(user_jid="user1@test.com", 
     541                                  name="account11", 
     542                                  jid="account11@jmc.test.com") 
     543       smtp_account.host = "localhost" 
     544       smtp_account.port = 1025 
     545       del account.hub.threadConnection 
     546       email = smtp_account.create_email("from@test.com", 
     547                                         "to@test.com", 
     548                                         "subject", 
     549                                         "body") 
     550       test_func = self.make_test(["220 localhost SMTP\r\n", 
     551                                   "504 ESMTP not supported\r\n", 
     552                                   "250-localhost Hello 127.0.0.1\r\n" 
     553                                   + "250-SIZE 52428800\r\n" 
     554                                   + "250-PIPELINING\r\n" 
     555                                   + "250 HELP\r\n", 
     556                                   "250 OK\r\n", 
     557                                   "250 Accepted\r\n", 
     558                                   "354 Enter message\r\n", 
     559                                   None, None, None, None, 
     560                                   None, None, None, None, 
     561                                   "250 OK\r\n"], 
     562                                  ["ehlo \[127.0.0.1\]\r\n", 
     563                                   "helo \[127.0.0.1\]\r\n", 
     564                                   "mail FROM:<" + str(email['From']) + ">.*", 
     565                                   "rcpt TO:<" + str(email['To']) + ">\r\n", 
     566                                   "data\r\n"] + 
     567                                   email.as_string().split("\n") + [".\r\n"], 
     568                                  lambda self: \ 
     569                                  smtp_account.send_email(email)) 
     570       test_func() 
     571 
     572    def test_send_email_esmtp_auth(self): 
     573       account.hub.threadConnection = connectionForURI('sqlite://' 
     574                                                       + self.db_url) 
     575       smtp_account = SMTPAccount(user_jid="user1@test.com", 
     576                                  name="account11", 
     577                                  jid="account11@jmc.test.com") 
     578       smtp_account.host = "localhost" 
     579       smtp_account.port = 1025 
     580       smtp_account.login = "user" 
     581       smtp_account.password = "pass" 
     582       del account.hub.threadConnection 
     583       email = smtp_account.create_email("from@test.com", 
     584                                         "to@test.com", 
     585                                         "subject", 
     586                                         "body") 
     587       test_func = self.make_test(["220 localhost ESMTP\r\n", 
     588                                   "250-localhost Hello 127.0.0.1\r\n" 
     589                                   + "250-SIZE 52428800\r\n" 
     590                                   + "250-AUTH PLAIN LOGIN CRAM-MD5\r\n" 
     591                                   + "250-PIPELINING\r\n" 
     592                                   + "250 HELP\r\n", 
     593                                   "334 ZGF4IDNmNDM2NzY0YzBhNjgyMTQ1MzhhZGNiMjE2YTYxZjRm\r\n", 
     594                                   "235 Authentication succeeded\r\n", 
     595                                   "250 OK\r\n", 
     596                                   "250 Accepted\r\n", 
     597                                   "354 Enter message\r\n", 
     598                                   None, None, None, None, 
     599                                   None, None, None, None, 
     600                                   "250 OK\r\n"], 
     601                                  ["ehlo \[127.0.0.1\]\r\n", 
     602                                   "AUTH CRAM-MD5\r\n", 
     603                                   ".*\r\n", 
     604                                   "mail FROM:<" + str(email['From']) + ">.*", 
     605                                   "rcpt TO:<" + str(email['To']) + ">\r\n", 
     606                                   "data\r\n"] + 
     607                                   email.as_string().split("\n") + [".\r\n"], 
     608                                  lambda self: \ 
     609                                  smtp_account.send_email(email)) 
     610       test_func() 
     611 
     612    def test_send_email_esmtp_auth_method2(self): 
     613       account.hub.threadConnection = connectionForURI('sqlite://' 
     614                                                       + self.db_url) 
     615       smtp_account = SMTPAccount(user_jid="user1@test.com", 
     616                                  name="account11", 
     617                                  jid="account11@jmc.test.com") 
     618       smtp_account.host = "localhost" 
     619       smtp_account.port = 1025 
     620       smtp_account.login = "user" 
     621       smtp_account.password = "pass" 
     622       del account.hub.threadConnection 
     623       email = smtp_account.create_email("from@test.com", 
     624                                         "to@test.com", 
     625                                         "subject", 
     626                                         "body") 
     627       test_func = self.make_test(["220 localhost ESMTP\r\n", 
     628                                   "250-localhost Hello 127.0.0.1\r\n" 
     629                                   + "250-SIZE 52428800\r\n" 
     630                                   + "250-AUTH PLAIN LOGIN CRAM-MD5\r\n" 
     631                                   + "250-PIPELINING\r\n" 
     632                                   + "250 HELP\r\n", 
     633                                   "334 ZGF4IDNmNDM2NzY0YzBhNjgyMTQ1MzhhZGNiMjE2YTYxZjRm\r\n", 
     634                                   "535 Incorrect Authentication data\r\n", 
     635                                   "334 asd235r4\r\n", 
     636                                   "235 Authentication succeeded\r\n", 
     637                                   "250 OK\r\n", 
     638                                   "250 Accepted\r\n", 
     639                                   "354 Enter message\r\n", 
     640                                   None, None, None, None, 
     641                                   None, None, None, None, 
     642                                   "250 OK\r\n"], 
     643                                  ["ehlo \[127.0.0.1\]\r\n", 
     644                                   "AUTH CRAM-MD5\r\n", 
     645                                   ".*\r\n", 
     646                                   "AUTH LOGIN .*\r\n", 
     647                                   ".*\r\n", 
     648                                   "mail FROM:<" + str(email['From']) + ">.*", 
     649                                   "rcpt TO:<" + str(email['To']) + ">\r\n", 
     650                                   "data\r\n"] + 
     651                                   email.as_string().split("\n") + [".\r\n"], 
     652                                  lambda self: \ 
     653                                  smtp_account.send_email(email)) 
     654       test_func() 
     655 
     656 
    469657def suite(): 
    470658    suite = unittest.TestSuite() 
  • src/jmc/model/tests/server.py

    r68 r93  
    22## dummy_server.py 
    33## Login : David Rousselie <david.rousselie@happycoders.org> 
    4 ## Started on  Fri May 13 12:53:17 2005  
     4## Started on  Fri May 13 12:53:17 2005 
    55## $Id: dummy_server.py,v 1.1 2005/07/11 20:39:31 dax Exp $ 
    6 ##  
    7 ## Copyright (C) 2005  
     6## 
     7## Copyright (C) 2005 
    88## This program is free software; you can redistribute it and/or modify 
    99## it under the terms of the GNU General Public License as published by 
    1010## the Free Software Foundation; either version 2 of the License, or 
    1111## (at your option) any later version. 
    12 ##  
     12## 
    1313## This program is distributed in the hope that it will be useful, 
    1414## but WITHOUT ANY WARRANTY; without even the implied warranty of 
    1515## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1616## GNU General Public License for more details. 
    17 ##  
     17## 
    1818## You should have received a copy of the GNU General Public License 
    1919## along with this program; if not, write to the Free Software 
     
    7676        self.queries = None 
    7777        self.real_queries = [] 
    78          
     78 
    7979    def serve(self): 
    8080        conn = None 
     
    151151                    except: 
    152152                        type, value, stack = sys.exc_info() 
    153                         print "".join (traceback.format_exception  
     153                        print "".join (traceback.format_exception 
    154154                                       (type, value, stack, 5)) 
    155155                        raise 
     
    176176        except: 
    177177            type, value, stack = sys.exc_info() 
    178             print "".join (traceback.format_exception  
     178            print "".join (traceback.format_exception 
    179179                           (type, value, stack, 5)) 
    180180            raise 
     
    206206if __name__ == '__main__': 
    207207    test() 
    208      
    209  
     208 
     209