def envrcpt(self, to, *str): rcptinfo = to,Milter.dictfromlist(str) self.R.append(rcptinfo) self.log("to: ", parse_addr(to)[0]) a = 23 b = 42 addr = parse_addr(to)[0] euser = addr[0:2] ecsum = addr[2:4] eitext = addr[4:] edomain = parse_addr(to)[1] genitext = ''.join((euser, eitext, edomain)) gencsum = hashlib.sha512(genitext.encode('utf-8')).hexdigest() posa = int(a)-1 posb = int(b)-1 csuma = gencsum[posa:(posa+1)] csumb = gencsum[posb:(posb+1)] self.log(addr, euser, ecsum, eitext, edomain, genitext, gencsum, posa, posb, csuma, csumb) if(ecsum != "".join((csuma,csumb))): self.log("Computer sagt nein.") return Milter.REJECT self.log("Computer sagt ja.") return Milter.CONTINUE
def searchInRoundCube(fromAddress, recipients, debug, dbConnection): """Search for an address in the RoundCube database.""" try: # Nothing found if not dbConnection: GlobalLogQueue.put("Could not connect to the database") return [] sources = [] for rec in recipients: parts = parse_addr(rec[0]) uid = parts[0] # First, get all the address books from this user tablesCursor = dbConnection.cursor() abQuery = ("select cg.name from contacts as c" " left join contactgroupmembers as cgm" " on cgm.contact_id = c.contact_id" " left join contactgroups as cg" " on cg.contactgroup_id=cgm.contactgroup_id" " left join users as u" " on u.user_id = c.user_id" " where u.username='******' and " " c.words like '%{}%' and" " c.del = 0" .format(uid, fromAddress)) tablesCursor.execute(abQuery) abooks = tablesCursor.fetchall() # End to search in this recipient tablesCursor.close() # Store the address book name, or "default" when no name for abResult in abooks: # Get the first cell as a result abName = abResult[0] if abName: source = "Roundcube:{}".format(abName) else: source = "Roundcube:default" # Insert if not already inside. if not source in sources: sources.append(source) if debug: GlobalLogQueue.put("Searched address {} for user {}: {} result(s)".format( fromAddress, uid, len(sources))) # Make sure to not prevent the message to pass if something happen, # but log the error except Exception as error: GlobalLogQueue.put("Error when searching in address database: {}".format(error.message)) return sources
def envfrom(self, mailfrom, *str): self.recipients = [] # list of recipients self.messageToParse = StringIO.StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) self.messageToParse.write('From %s %s\n' % (self.canon_from, time.ctime())) return Milter.CONTINUE
def envfrom(self, fromAddress, *extra): self.mailFrom = '@'.join(parse_addr(fromAddress)) self.recipients = [] self.fromparms = Milter.dictfromlist(extra) # ESMTP parms self.user = self.getsymval('{auth_authen}') # authenticated user self.fp = StringIO.StringIO() return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.fromparms = Milter.param2dict(str) # ESMTP parms self.user = self.getsymval('{auth_authen}') # authenticated user self.canon_from = '@'.join(parse_addr(mailfrom)) self.R = [] self.fp = BytesIO() self.fp.write(b"From %s %s\n" % (codecs.encode(self.canon_from, 'utf-8'), codecs.encode(time.ctime(), 'utf-8'))) return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.F = mailfrom self.R = [] # list of recipients self.fromparms = Milter.dictfromlist(str) # ESMTP parms self.user = self.getsymval('{auth_authen}') # authenticated user self.fp = StringIO.StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) #self.fp.write('From %s %s\n' % (self.canon_from,time.ctime())) return Milter.CONTINUE
def envfrom(self, mail_from, *esmtp_params): self.log('debug', log_called(module_name=__name__, function_name='envfrom', params={ 'mail_from': str(mail_from) })) try: self.mail_from = parse_addr(mail_from)[0] except Exception: self.mail_from = str(mail_from) return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.F = mailfrom self.R = [] self.fromparms = Milter.dictfromlist(str) self.user = self.getsymval('{auth_authen}') self.fp = StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) self.fp.write('From %s %s\n' % (self.canon_from, time.ctime())) return Milter.CONTINUE
def envrcpt(self, to, *str): try: self.rcpts.add("@".join(parse_addr(to)).lower()) except Exception as e: self.logger.exception( f"an exception occured in envrcpt method: {e}") return Milter.TEMPFAIL return Milter.CONTINUE
def envfrom(self, mailfrom, *str): try: self.mailfrom = "@".join(parse_addr(mailfrom)).lower() self.rcpts = set() except Exception as e: self.logger.exception( f"an exception occured in envfrom method: {e}") return Milter.TEMPFAIL return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.log("mail from: %s - %s" % (mailfrom, str)) self.fromparms = Milter.dictfromlist(str) # NOTE: self.fp is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.fp = StringIO.StringIO() self.canon_from = "@".join(parse_addr(mailfrom)) self.fp.write("From %s %s\n" % (self.canon_from, time.ctime())) return Milter.CONTINUE
def envrcpt(self, mail_recip, *esmtp_params): self.log('debug', log_called(module_name=__name__, function_name='envrcpt', params={ 'mail_recip': str(mail_recip) })) try: recip = parse_addr(mail_recip)[0] except Exception: recip = str(mail_recip) self.recipients.append(recip) return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.mailfrom = mailfrom self.domains = [] t = parse_addr(mailfrom) if len(t) > 1: self.domains.append(t[1]) else: self.domains.append('local') self.internal = False return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.log("mail from: %s - %s" % (mailfrom, str)) self.fromparms = Milter.dictfromlist(str) # NOTE: self.fp is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.fp = StringIO.StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) self.fp.write('From %s %s\n' % (self.canon_from, time.ctime())) return Milter.CONTINUE
def envfrom(self, f, *str): self.log("mail from", f, str) self.new_headers = [] if not self.hello_name: self.log('REJECT: missing HELO') self.setreply('550', '5.7.1', "It's polite to say helo first.") return Milter.REJECT self.mailfrom = f t = parse_addr(f) if len(t) == 2: t[1] = t[1].lower() domain = t[1] else: domain = 'localhost.localdomain' self.canon_from = '@'.join(t) # Check SMTP AUTH, also available: # auth_authen authenticated user # auth_author (ESMTP AUTH= param) # auth_ssf (connection security, 0 = unencrypted) # auth_type (authentication method, CRAM-MD5, DIGEST-MD5, PLAIN, etc) # cipher_bits SSL encryption strength # cert_subject SSL cert subject # verify SSL cert verified self.user = self.getsymval('{auth_authen}') if self.user: # Very simple SMTP AUTH policy by default: # any successful authentication is considered INTERNAL # Detailed authorization policy is configured in the access file below. self.internal_connection = True self.log("SMTP AUTH:", self.user, self.getsymval('{auth_type}'), "sslbits =", self.getsymval('{cipher_bits}'), "ssf =", self.getsymval('{auth_ssf}'), "INTERNAL") # Restrict SMTP AUTH users to authorized domains authsend = '@'.join((self.user, domain)) with SPFPolicy(authsend, self.conf) as p: policy = p.getPolicy('smtp-auth:') if policy: if policy != 'OK': self.log("REJECT: SMTP user", self.user, "at", self.connectip, "not authorized for domain", domain) self.setreply( '550', '5.7.1', 'SMTP user %s is not authorized to send from domain %s.' % (self.user, domain)) return Milter.REJECT self.log("SMTP authorized user", self.user, "sending from domain", domain) if not (self.internal_connection or self.trusted_relay) and self.connectip: return self.check_spf() return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.F = mailfrom self.R = [] self.fromparms = Milter.dictfromlist(str) self.user = self.getsymval('{auth_authen}') self.fp = StringIO.StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) self.fp.write('From %s %s\n' % (self.canon_from, time.ctime())) return Milter.CONTINUE
def envfrom(self,f,*str): self.log("mail from",f,str) self.new_headers = [] if not self.hello_name: self.log('REJECT: missing HELO') self.setreply('550','5.7.1',"It's polite to say helo first.") return Milter.REJECT self.mailfrom = f t = parse_addr(f) if len(t) == 2: t[1] = t[1].lower() domain = t[1] else: domain = 'localhost.localdomain' self.canon_from = '@'.join(t) # Check SMTP AUTH, also available: # auth_authen authenticated user # auth_author (ESMTP AUTH= param) # auth_ssf (connection security, 0 = unencrypted) # auth_type (authentication method, CRAM-MD5, DIGEST-MD5, PLAIN, etc) # cipher_bits SSL encryption strength # cert_subject SSL cert subject # verify SSL cert verified self.user = self.getsymval('{auth_authen}') if self.user: # Very simple SMTP AUTH policy by default: # any successful authentication is considered INTERNAL # Detailed authorization policy is configured in the access file below. self.internal_connection = True self.log( "SMTP AUTH:",self.user, self.getsymval('{auth_type}'), "sslbits =",self.getsymval('{cipher_bits}'), "ssf =",self.getsymval('{auth_ssf}'), "INTERNAL" ) # Restrict SMTP AUTH users to authorized domains authsend = '@'.join((self.user,domain)) with SPFPolicy(authsend,self.conf) as p: policy = p.getPolicy('smtp-auth:') if policy: if policy != 'OK': self.log("REJECT: SMTP user",self.user, "at",self.connectip,"not authorized for domain",domain) self.setreply('550','5.7.1', 'SMTP user %s is not authorized to send from domain %s.' % (self.user,domain) ) return Milter.REJECT self.log("SMTP authorized user",self.user,"sending from domain",domain) if not (self.internal_connection or self.trusted_relay) and self.connectip: return self.check_spf() return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.log("mail from: %s - %s" % (mailfrom, str)) self.fromparms = Milter.dictfromlist(str) # NOTE: self.fp is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.fp = BytesIO() self.canon_from = "@".join(parse_addr(mailfrom)) from_txt = "From %s %s\n" % (self.canon_from, time.ctime()) self.fp.write(from_txt.encode("utf-8")) return Milter.CONTINUE
def searchInSOGo(fromAddress, recipients, debug, dbConnection): """Search for an address in the SOGo database.""" try: # Nothing found if not dbConnection: GlobalLogQueue.put("Could not connect to the database") return [] sources = [] for rec in recipients: parts = parse_addr(rec[0]) uid = parts[0] # First, get all the address books from this user tablesCursor = dbConnection.cursor() abQuery = ("select c_foldername, regexp_replace(c_location, '.*/sogo', 'sogo')" " from sogo_folder_info where" " c_folder_type='Contact' and c_location like '%sogo{}%';".format(uid)) tablesCursor.execute(abQuery) tables = tablesCursor.fetchall() # End to search in this address book tablesCursor.close() # For each table, run a query to check if the address is inside for tableInfo in tables: abName = tableInfo[0] tableName = tableInfo[1] cursor = dbConnection.cursor() countQuery = "select count(*) from {} where c_content LIKE '%EMAIL%:{}%';".format(tableName, fromAddress) if debug: GlobalLogQueue.put("Searching in table {} ({})".format(tableName, abName)) cursor.execute(countQuery) result = cursor.fetchone() cursor.close() # Store the address book sources when found if int(result[0]) > 0: sources.append('SOGo:{}'.format(abName)) if debug: GlobalLogQueue.put("Searched address {} for user {}: {} result(s)".format( fromAddress, uid, len(sources))) # Make sure to not prevent the message to pass if something happen, # but log the error except Exception as error: GlobalLogQueue.put("Error when searching in address database: {}".format(error.message)) return sources
def envfrom(self, mailfrom, *str): self.F = mailfrom self.R = [] # list of recipients self.fromparms = Milter.dictfromlist(str) # ESMTP parms self.user = self.getsymval('{auth_authen}') # authenticated user self.log("mail from:", mailfrom, *str) # NOTE: self.fp is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.fp = StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) self.fp.write('From %s %s\n' % (self.canon_from,time.ctime())) return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.F = mailfrom self.R = [] # list of recipients self.fromparms = Milter.dictfromlist(str) # ESMTP parms self.user = self.getsymval('{auth_authen}') # authenticated user self.log("mail from:", mailfrom, *str) # NOTE: self.fp is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.fp = BytesIO() self.canon_from = '@'.join(parse_addr(mailfrom)) #self.fp.write('From %s %s\n' % (self.canon_from,time.ctime())) return Milter.CONTINUE
def envfrom(self, f, *str): self.log("mail from", f, str) self.mailfrom = f t = parse_addr(f) if len(t) == 2: t[1] = t[1].lower() self.canon_from = '@'.join(t) self.srsrcpt = [] self.nosrsrcpt = [] self.redirect_list = [] self.discard_list = [] self.is_bounce = (f == '<>' or t[0].lower() in self.conf.banned_users) self.data_allowed = True return Milter.CONTINUE
def envrcpt(self, to, *str): self.R.append(to) t = parse_addr(to) if len(t) > 1: self.domains.append(t[1]) else: self.domains.append('local') if are_mixed(self.domains): # FIXME: log recipients collected in self.mailfrom and self.R self.setreply('550','5.7.1','Mixing internal and external TLDs') return Milter.REJECT return Milter.CONTINUE
def envrcpt(self, to, *params): conf = self.conf t = parse_addr(to) if len(t) == 2: t[1] = t[1].lower() user, domain = t if self.is_bounce and domain in conf.srs_domain: # require valid signed recipient oldaddr = '@'.join(t) try: if conf.ses: ses = self.conf.ses newaddr = ses.verify(oldaddr) else: newaddr = oldaddr, if len(newaddr) > 1: newaddr = newaddr[0] self.log("ses rcpt:", newaddr) else: srs = self.conf.srs newaddr = srs.reverse(oldaddr) self.log("srs rcpt:", newaddr) self.del_recipient(to) self.add_recipient('<%s>' % newaddr, params) except: # no valid SRS signature if not (self.internal_connection or self.trusted_relay): # reject specific recipients with bad sig if self.srsre.match(oldaddr): self.log("REJECT: srs spoofed:", oldaddr) self.setreply('550', '5.7.1', 'Invalid SRS signature') return Milter.REJECT if oldaddr.startswith('SES='): self.log("REJECT: ses spoofed:", oldaddr) self.setreply('550', '5.7.1', 'Invalid SES signature') return Milter.REJECT # reject message for any missing sig self.data_allowed = not conf.srs_reject_spoofed else: # sign "outgoing" from if domain in self.conf.nosrsdomain: self.nosrsrcpt.append(to) else: self.srsrcpt.append(to) else: # no SRS for unqualified recipients self.nosrsrcpt.append(to) return Milter.CONTINUE
def envfrom(self, f, *str): if milterconfig.get('Syslog') and milterconfig.get('debugLevel') >= 2: syslog.syslog("mail from: {0} {1}".format(f, str)) self.fp = io.BytesIO() self.mailfrom = f t = parse_addr(f) if len(t) == 2: t[1] = t[1].lower() self.mailfromdom = t[1] self.canon_from = '@'.join(t) self.has_dkim = 0 self.author = None self.arheaders = [] self.arresults = [] return Milter.CONTINUE
def envfrom(self, mailfrom, *rest): ''' Mail From - Called at the beginning of each message within a connection :param mailfrom: :param str: :return: Milter.CONTINUE ''' self.message = io.BytesIO() # NOTE: self.message is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.canon_from = '@'.join(parse_addr(mailfrom)) self.message.write('From %s %s\n' % (self.canon_from, time.ctime())) logging.debug('[%d] Mail From %s %s\n' % (self.id, self.canon_from, time.ctime())) logging.debug('[%d] mailfrom=%r, rest=%r' % (self.id, mailfrom, rest)) return Milter.CONTINUE
def envfrom(self, mailfrom, *rest): ''' Mail From - Called at the beginning of each message within a connection :param mailfrom: :param str: :return: Milter.CONTINUE ''' self.message = io.BytesIO() # NOTE: self.message is only an *internal* copy of message data. You # must use addheader, chgheader, replacebody to change the message # on the MTA. self.canon_from = '@'.join(parse_addr(mailfrom)) self.message.write('From %s %s\n' % (self.canon_from, time.ctime())) log.debug('[%d] Mail From %s %s\n' % (self.id, self.canon_from, time.ctime())) log.debug('[%d] mailfrom=%r, rest=%r' % (self.id, mailfrom, rest)) return Milter.CONTINUE
def searchInSQLite(fromAddress, recipients, debug): """Search for an address in a local sqlite database. Only email hashes are stored (sha256)""" sources = [] try: import sqlite3 import hashlib query = 'select source,abook from addresses where uid="{0}" and email_hash="{1}"' sqliteDatabase = configParser.get('sqlite', 'path') db = sqlite3.connect(sqliteDatabase) # Check if the email address is in the user's address book cursor = db.cursor() # get the from email address signature emailHash = hashlib.sha256(fromAddress).hexdigest() for rec in recipients: parts = parse_addr(rec[0]) uid = parts[0] cursor.execute(query.format(uid, emailHash)) # Store the address book sources when found for row in cursor: sources.append('{0}:{1}'.format(row[0], row[1])) if debug: GlobalLogQueue.put("Searched address hash {} for user {}: {} result(s)".format( emailHash, uid, len(sources))) # Make sure to not prevent the message to pass if something happen, # but log the error except Exception as error: GlobalLogQueue.put("Error when searching in address database: {}".format(error.message)) # Cleanup: close the db connection if needed finally: if db: db.close() return sources
def envrcpt(self, to, *str): self.recipients.add("@".join(parse_addr(to)).lower()) return Milter.CONTINUE
def envfrom(self, mailfrom, *str): self.mailfrom = "@".join(parse_addr(mailfrom)).lower() self.recipients = set() return Milter.CONTINUE
def envfrom(self, mailfrom, *str): user_from, domain_from = parse_addr(mailfrom) user_from = user_from.split("+", 1)[0] mail_from = "@".join((user_from, domain_from)) self.mail.append("From %s %s\n" % (mail_from, time.ctime())) return Milter.CONTINUE
def envrcpt(self, to, *str): if not self.to: self.to = "@".join(parse_addr(to)) return Milter.CONTINUE else: return Milter.TEMPFAIL
def envfrom(self, mailfrom, *str): self.messageToParse = StringIO.StringIO() self.canon_from = '@'.join(parse_addr(mailfrom)) self.messageToParse.write('From %s %s\n' % (self.canon_from, time.ctime())) return Milter.CONTINUE