| 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 | |
| | 163 | def 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?!?!?!? |
| 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)) |
| 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 |
| | 268 | class 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 | |
| | 362 | class ESMTPFactory(Factory): |
| | 363 | protocol = myESTMP |