Changeset 28

Show
Ignore:
Timestamp:
10/13/09 18:32:35 (1 month ago)
Author:
oriol
Message:

beta1 of learn_recipients it can be a release candidate in next days

Location:
src/trunk/frontend/learn_recipients
Files:
1 added
2 modified
1 copied

Legend:

Unmodified
Added
Removed
  • src/trunk/frontend/learn_recipients/.settings/org.eclipse.core.resources.prefs

    r25 r28  
    1 #Mon Oct 05 16:30:05 CEST 2009 
     1#Tue Oct 13 18:32:30 CEST 2009 
    22eclipse.preferences.version=1 
    33encoding/learn_recipients.tac.py=iso-8859-15 
     4encoding/learn_recipients.tac.py.bak=iso-8859-15 
  • src/trunk/frontend/learn_recipients/learn_recipients.tac.py

    r27 r28  
    55# (cc) Oriol Rius, 20090716 
    66# 
    7 # Descripció: 
    8 #   Rep peticions de verificació d'existÚncia d'email des del postfix, el primer que fa és  
     7# Descripció: 
     8#   Rep peticions de verificació d'existÚncia d'email des del postfix, el primer que fa és  
    99#  comprovar si existeix la compte de correu que demana l'usuari a la bbdd, si existeix tornem un ok. 
    10 #   En cas contrari, demana al 'transport services' quin és el servidor SMTP que rep aquestes  
     10#   En cas contrari, demana al 'transport services' quin és el servidor SMTP que rep aquestes  
    1111#  peticions llavors es connecta al servidor i comprova si existeix la compte de correu. El resultat 
    12 #  el reporta a la connexió original que s'ha rebut. 
    13 #   Tal com esta configurat el postfix, només s'haurien de rebre validacions d'emails d'usuaris que 
     12#  el reporta a la connexió original que s'ha rebut. 
     13#   Tal com esta configurat el postfix, només s'haurien de rebre validacions d'emails d'usuaris que 
    1414#  pertanyen a dominis on es fa relay. 
    1515#   Amb aquest servei s'aconsegueix tenir un sistema de 'cache' dels usuaris locals. 
    1616#    
    1717# 
    18  
     18import sys  
     19sys.path.append('./') 
    1920from zope.interface import implements 
    2021from twisted.application import service 
    2122application = service.Application("SMTP Proxy") 
    2223from twisted.application import internet 
    23 from twisted.internet import protocol, defer 
     24from twisted.internet import protocol, defer, threads, reactor 
    2425from twisted.mail import smtp 
    25 import logging,tempfile,os,smtplib,popen2 
     26import logging,tempfile,os,smtplib2,popen2 
    2627import MySQLdb,time 
     28from twisted.internet.protocol import Protocol, Factory 
    2729 
    2830# Configuration 
    2931HOST='127.0.0.1' 
    30 PORT=25004 
     32PORT=25010 
    3133TTL=30*24*60*60 # 1month to expire 
    3234DSPAM="dspam" 
     
    3537bot_buffer='/tmp/buffer.bot' 
    3638DRY_MODE=False 
     39#control de threads 
     40fils = 0 
     41#control de conneccions 
     42connections = 0 
     43 
    3744 
    3845# Logs 
     
    6673    #    return True 
    6774    logging.debug("verify_user: "+HOST+":"+str(PORT)+" - "+DOMAIN+" -f:"+SUSER+"-d:"+DUSER) 
    68     s=smtplib.SMTP() 
    69     try: 
    70         resp=s.connect(HOST,PORT) 
    71     except: 
     75    intent=1 
     76    surt=False 
     77    while intent < 3 and surt is not True: 
     78        try: 
     79            s=smtplib2.SMTP() 
     80            resp=s.connect(HOST,PORT) 
     81            surt=True 
     82        except: 
     83            intent=intent+1 
     84            logging.error('verify_user: #'+str(intent)+' trying to connect to:'+HOST+":"+str(PORT)) 
     85            #time.sleep(0.5) 
     86    if surt is False: 
     87        logging.error('verify_user: cannot connect to:'+HOST+":"+str(PORT)) 
    7288        return False 
    7389    if (resp[0]!=220): 
     90        logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' no recieved 220 resp') 
    7491        return False 
    7592    s.set_debuglevel(0) 
     
    7794        resp=s.docmd("ehlo "+DOMAIN) 
    7895    except: 
     96        logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' error sending "ehlo" command') 
    7997        return False 
    8098    if (resp[0]!=250): 
     99        logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' error waiting 250 resp after "ehlo" command') 
    81100        return False 
    82101    try: 
    83102        resp=s.docmd("mail from:<"+SUSER+">") 
    84103    except: 
     104        logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' error sending "mail from" command')         
    85105        return False 
    86106    if (resp[0]!=250): 
     107        logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' error waiting 250 resp after "mail from" command') 
    87108        return False 
    88109    try: 
    89110        resp=s.docmd("rcpt to:<"+DUSER+">") 
    90111    except: 
     112        logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' error sending "rcpt to" command') 
    91113        return False 
    92114    logging.debug("debug_vrfy_sender:"+str(resp)) 
    93115    if (resp[0]!=250): 
     116        #logging.error('verify_user: after conntect to:'+HOST+":"+str(PORT)+' error waiting 250 resp "rcpt to" command') 
    94117        return False 
    95118    try: 
    96119        s.docmd("quit") 
    97120    except: 
    98         return False 
     121        pass 
    99122    return True 
    100123 
     
    137160    logging.info("---end") 
    138161 
    139 # SMTP server 
    140 class SmtpDelivery(object): 
    141     implements(smtp.IMessageDelivery) 
    142  
    143     def validateTo(self, user): 
    144         global cursor 
    145         user = str(user).strip("'") 
    146         # preguntem a la bbdd 
    147         marca_inici = time.time() 
    148         logging.info('*** verifying: '+str(user)+" ***") 
    149         query = "SELECT uid,ts,locked FROM dspam_virtual_uids WHERE username = '"+str(user)+"'" 
    150         logging.debug(query) 
    151         try: 
    152             cursor.execute (query) 
    153         except: 
    154             logging.error("query: "+str(query)) 
    155             bot("learn_recipients: error: query: "+str(query)) 
    156             logging.info('return '+str(user)+'  code=450') 
    157             calcul_temps(marca_inici)                 
    158             raise smtp.SMTPBadRcpt('code=450')             
    159         out = cursor.fetchall() 
    160         logging.debug(str(out)) 
    161         if len(out) > 0: 
    162             ts = out[0][1] 
    163             locked = out[0][2] 
    164             if ts == None: 
    165                 locked = True 
    166             if locked or time.mktime(ts.timetuple()) > time.time()-TTL: 
    167                 # correu existeix, validat! 
    168                 logging.info("Validate: "+str(user)+" Ok!") 
    169                 if out[0][2] == False: 
    170                     # actualitzem TS 
    171                     query = "UPDATE dspam_virtual_uids SET ts = now() WHERE uid = "+str(out[0][0]) 
    172                     logging.debug(query) 
    173                     if not DRY_MODE: cursor.execute (query) 
    174                 calcul_temps(marca_inici) 
    175                 logging.info('return '+str(user)+' code=250') 
    176                 return 
    177         # obtenim servidor smtp on hem de validar el correu 
    178         smtp_server = run_cmd("postmap -q "+str(user)+" tcp:91.121.104.91:25403") 
    179         logging.debug(smtp_server) 
    180         try: 
    181             # parsegem sortida 
    182             camps=smtp_server[0].split(':') 
    183             if camps[1][0] == '[': 
    184                 server=camps[1][1:-1] 
    185             else: 
    186                 server=camps[1] 
    187             port=camps[2][:-1] 
    188             logging.debug("Transport server: "+str(server)+":"+str(port)) 
    189         except: 
    190             if smtp_server == 'smtp': 
    191                 # borrem correu de la bbdd, no hi és?!?!?!? 
    192                 if len(out)>0: 
    193                     uid=out[0][0] 
    194                     borrar_email(uid,user,cursor) 
    195                 else: 
    196                     logging.error("Error: cannot delete from database: "+str(user)) 
    197                 logging.info('return '+str(user)+'  code=550') 
    198                 calcul_temps(marca_inici) 
    199                 raise smtp.SMTPBadRcpt('code=550') 
    200             else: 
    201                 # timeout o no s'ha pogut aconseguir la info 
    202                 logging.info('return '+str(user)+'  code=450') 
    203                 calcul_temps(marca_inici)                 
    204                 raise smtp.SMTPBadRcpt('code=450') 
    205         # preguntem al servidor smtp si existeix el correu 
    206         if verify_user(server,port,str(str(user).split('@')[1]),str(self.email_source),str(user)): 
    207             # afegim email a la bbdd o actualitzem ts 
    208             logging.debug('Update TS or Insert in database of: '+str(user)) 
    209             query = "UPDATE dspam_virtual_uids SET ts = now() WHERE username = '"+str(user)+"'" 
    210             logging.debug(query) 
    211             if not DRY_MODE:  
    212                 canviat=cursor.execute (query) 
    213                 if canviat == 0: 
    214                     # no existeix a la bbdd el donem d'alta 
    215                     query="INSERT INTO dspam_virtual_uids SET username='"+str(user)+"', ts=NOW()" 
    216                     try: 
    217                         canviat=cursor.execute (query) 
    218                     except: 
    219                         logging.error('ERROR: '+query) 
    220         else: 
    221             # borrem email de la bbdd 
     162 
     163def validTo(user): 
     164    global fils,connections 
     165    fils = fils + 1 
     166    conn = MySQLdb.connect ("87.98.228.217","dspam","ges2ges","dspam") 
     167    cursor = conn.cursor () 
     168    user = str(user).strip("'") 
     169    # preguntem a la bbdd 
     170    marca_inici = time.time() 
     171    logging.info('validTo: instanced in conn #'+str(connections)+' thread#'+str(fils)) 
     172    logging.info('*** verifying: '+str(user)+" ***") 
     173    query = "SELECT uid,ts,locked FROM dspam_virtual_uids WHERE username = '"+str(user)+"'" 
     174    logging.debug(query) 
     175    try: 
     176        cursor.execute (query) 
     177    except: 
     178        logging.error("query: "+str(query)) 
     179        bot("learn_recipients: error: query: "+str(query)) 
     180        logging.info('return '+str(user)+'  code=450') 
     181        calcul_temps(marca_inici)    
     182        conn.close()              
     183        return "450"             
     184    out = cursor.fetchall() 
     185    logging.debug(str(out)) 
     186    if len(out) > 0: 
     187        ts = out[0][1] 
     188        locked = out[0][2] 
     189        if ts == None: 
     190            locked = True 
     191        if locked or time.mktime(ts.timetuple()) > time.time()-TTL: 
     192            # correu existeix, validat! 
     193            logging.info("Validate: "+str(user)+" Ok!") 
     194            if out[0][2] == False: 
     195                # actualitzem TS 
     196                query = "UPDATE dspam_virtual_uids SET ts = now() WHERE uid = "+str(out[0][0]) 
     197                logging.debug(query) 
     198                if not DRY_MODE: cursor.execute (query) 
     199            calcul_temps(marca_inici) 
     200            logging.info('return '+str(user)+' code=250') 
     201            conn.close() 
     202            return "250" 
     203    # obtenim servidor smtp on hem de validar el correu 
     204    smtp_server = run_cmd("postmap -q "+str(user)+" tcp:91.121.104.91:25403") 
     205    logging.debug(smtp_server) 
     206    try: 
     207        # parsegem sortida 
     208        camps=smtp_server[0].split(':') 
     209        if camps[1][0] == '[': 
     210            server=camps[1][1:-1] 
     211        else: 
     212            server=camps[1] 
     213        port=camps[2][:-1] 
     214        logging.debug("Transport server: "+str(server)+":"+str(port)) 
     215    except: 
     216        if smtp_server == 'smtp': 
     217            # borrem correu de la bbdd, no hi és?!?!?!? 
    222218            if len(out)>0: 
    223                 uid=out[0][0]                 
     219                uid=out[0][0] 
    224220                borrar_email(uid,user,cursor) 
    225221            else: 
    226                 logging.debug("Not exist in recipient server: "+str(user)) 
     222                logging.error("Error: cannot delete from database: "+str(user)) 
     223            logging.info('return '+str(user)+'  code=550') 
    227224            calcul_temps(marca_inici) 
    228             logging.info('return '+str(user)+'  code=550')                 
    229             raise smtp.SMTPBadRcpt('code=550') 
     225            conn.close() 
     226            return "550" 
     227        else: 
     228            # timeout o no s'ha pogut aconseguir la info 
     229            logging.info('return '+str(user)+'  code=450') 
     230            calcul_temps(marca_inici)  
     231            conn.close()                
     232            return "450" 
     233    # preguntem al servidor smtp si existeix el correu 
     234    if verify_user(server,port,str(str(user).split('@')[1]),'verifysender@lana2.com',str(user)): 
     235        # afegim email a la bbdd o actualitzem ts 
     236        logging.debug('Update TS or Insert in database of: '+str(user)) 
     237        query = "UPDATE dspam_virtual_uids SET ts = now() WHERE username = '"+str(user)+"'" 
     238        logging.debug(query) 
     239        if not DRY_MODE:  
     240            canviat=cursor.execute (query) 
     241            if canviat == 0: 
     242                # no existeix a la bbdd el donem d'alta 
     243                query="INSERT INTO dspam_virtual_uids SET username='"+str(user)+"', ts=NOW()" 
     244                try: 
     245                    canviat=cursor.execute (query) 
     246                except: 
     247                    logging.error('ERROR:'+query) 
     248    else: 
     249        # borrem email de la bbdd 
     250        if len(out)>0: 
     251            uid=out[0][0]                 
     252            borrar_email(uid,user,cursor) 
     253        else: 
     254            logging.debug("Not exist in recipient server: "+str(user)) 
    230255        calcul_temps(marca_inici) 
    231         logging.info('*** return '+str(user)+' code=250 ***')            
    232         return 
    233  
    234     def validateFrom(self, helo, origin): 
    235         self.email_source = origin 
    236         return origin 
    237  
    238     def receivedHeader(self, helo, origin, recipients): 
    239         return '' 
    240  
    241 # SMTP factory 
    242 class SmtpDeliveryFactory(object): 
    243     implements(smtp.IMessageDeliveryFactory) 
    244  
    245     def getMessageDelivery(self): 
    246         return SmtpDelivery() 
    247  
    248  
    249 class ESMTPFactory(protocol.ServerFactory): 
    250     protocol = smtp.ESMTP 
    251  
    252     def buildProtocol(self, addr): 
    253         p = self.protocol() 
    254         p.deliveryFactory = SmtpDeliveryFactory() 
    255         p.factory = self 
    256         return p 
     256        logging.info('return '+str(user)+'  code=550')      
     257        conn.close()            
     258        return "550" 
     259    calcul_temps(marca_inici) 
     260    logging.info('*** return '+str(user)+' code=250 ***')    
     261    conn.close()         
     262    return "250" 
     263 
     264 
     265 
     266 
     267# myESTMP factory 
     268class myESTMP(Protocol):    
     269    def connectionMade(self): 
     270        global connections 
     271        connections = connections +1 
     272        self.transport.write("220 active_connections#"+str(connections)+" threads#"+str(fils)+"\n") 
     273     
     274    def dataReceived(self,dades): 
     275        #processar comanda 
     276        # usem la propietat 'wait' perquÚ no s'envii un resultat de comanda despres del rcpt 
     277        self.wait = False 
     278        for data in dades.split("\n"): 
     279            try: 
     280                cmd = data.split(' ') 
     281                cmd = cmd[0] 
     282            except: 
     283                try: 
     284                    cmd = data.split(':') 
     285                    cmd = cmd[0] 
     286                except: 
     287                    cmd = data 
     288            cmd=cmd.strip().lower() 
     289            if cmd is not '': 
     290                if cmd == 'rcpt': 
     291                    try: 
     292                        aux = data.split('<') 
     293                        aux = aux[1].split('>') 
     294                        email = aux[0] 
     295                    except: 
     296                        self._syntax_error() 
     297                        self._end() 
     298                    self.wait = True 
     299                    d = threads.deferToThread(validTo,email) 
     300                    d.addCallback(self._rcvd_cb) 
     301                    d.addErrback(self._rcvd_cb)                     
     302                elif cmd == 'rset': 
     303                    self._rset() 
     304                elif cmd == 'quit': 
     305                    self._quit() 
     306                else: 
     307                    self._c250() 
     308 
     309     
     310    def lostConnection(self,reason): 
     311        global connections  
     312        connections = connections -1 
     313         
     314    def _rcvd_cb(self,estat): 
     315        global fils 
     316        fils = fils -1 
     317        if estat == '250': 
     318            self._c250() 
     319        elif estat == '450': 
     320            self._c450() 
     321        else: 
     322            self._c550() 
     323        self.wait = False 
     324         
     325 
     326    def _rset(self): 
     327        if self.wait: 
     328            reactor.callLater(0.1,self._rset) 
     329        else: 
     330            self._c250() 
     331             
     332    def _quit(self): 
     333        if self.wait: 
     334            reactor.callLater(0.1,self._quit) 
     335        else: 
     336            self._end() 
     337             
     338    def _c250(self): 
     339        self.transport.write('250'+"\n")     
     340 
     341    def _c450(self): 
     342        self.transport.write('450'+"\n") 
     343 
     344    def _c550(self): 
     345        self.transport.write('550'+"\n") 
     346     
     347    def _c502(self): 
     348        self.transport.write('502'+"\n") 
     349     
     350    def _c501(self): 
     351        self.transport.write('501'+"\n")                 
     352         
     353    def _end(self): 
     354        self.transport.write('221'+"\n") 
     355        self.transport.loseConnection()        
     356        global connections  
     357        connections = connections -1          
     358     
     359 
     360 
     361 
     362class ESMTPFactory(Factory): 
     363    protocol = myESTMP 
    257364 
    258365 
    259366# connectem al servidor MySQL 
    260 conn = MySQLdb.connect ("87.98.228.217","dspam","ges2ges","dspam") 
    261 cursor = conn.cursor () 
     367#conn = MySQLdb.connect ("87.98.228.217","dspam","ges2ges","dspam") 
     368#cursor = conn.cursor () 
    262369# launch SMTP server 
    263370smtpServerService = internet.TCPServer(PORT, ESMTPFactory(), interface=HOST)