def matchRules(self, ruleset, obj, suspect, attachmentname=None): if attachmentname is None: attachmentname = "" attachmentname = self.asciionly(attachmentname) if obj is None: self.logger.warning( "%s: message has unknown name or content-type attachment %s" % (suspect.id, attachmentname)) return ATTACHMENT_DUNNO # remove non ascii chars asciirep = self.asciionly(obj) displayname = attachmentname if asciirep == attachmentname: displayname = '' if ruleset is None: return ATTACHMENT_DUNNO for action, regex, description in ruleset: # database description may be unicode description = description.encode("utf-8", "ignore") prog = re.compile(regex, re.I) if self.extremeverbosity: self.logger.debug('Attachment %s Rule %s' % (obj, regex)) if isinstance(obj, bytes) and sys.version_info > (3,): obj = obj.decode('UTF-8', 'ignore') if prog.search(obj): self.logger.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s' % ( obj, regex, description, action)) suspect.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s' % ( obj, regex, description, action)) if action == 'deny': self.logger.info('suspect %s contains blocked attachment %s %s' % ( suspect.id, displayname, asciirep)) suspect.tags['blocked']['FiletypePlugin'] = True blockinfo = ("%s %s: %s" % (displayname, asciirep, description)).strip() suspect.tags['FiletypePlugin.errormessage'] = blockinfo if self.config.getboolean(self.section, 'sendbounce'): if suspect.is_spam() or suspect.is_virus(): self.logger.info( "backscatter prevention: not sending attachment block bounce to %s - the message is tagged spam or virus" % suspect.from_address) else: self.logger.info( "Sending attachment block bounce to %s" % suspect.from_address) bounce = Bounce(self.config) bounce.send_template_file( suspect.from_address, self.blockedfiletemplate, suspect, dict(blockinfo=blockinfo)) return ATTACHMENT_BLOCK if action == 'delete': self.logger.info( 'suspect %s contains blocked attachment %s %s -- SILENT DELETE! --' % (suspect.id, displayname, asciirep)) return ATTACHMENT_SILENTDELETE if action == 'allow': return ATTACHMENT_OK return ATTACHMENT_DUNNO
def test_bounce(self): """Test bounce message, especially the encoding""" suspect = Suspect('*****@*****.**', '*****@*****.**', '/dev/null') # include non-ascii charset unicode characters to make sure the encoding/decoding # works correctly displayname = u"((testing placeholder for displayname -> äää))" asciirep = u"((testing placeholder for asciirep -> üüü))" description = u"((testing placeholder for description -> ööö))" blockinfo = ("%s %s: %s" % (displayname, asciirep, description)).strip() blockedfiletemplate = os.path.join( *[CONFDIR, "templates", "blockedfile.tmpl.dist"]) bounce = Bounce(self.config) bounce.send_template_file(suspect.from_address, blockedfiletemplate, suspect, dict(blockinfo=blockinfo)) # might be needed to wait for a bit to make sure answer is available counter = 0 while self.smtp.suspect is None and counter < 20: counter = counter + 1 time.sleep(0.05) # sleep is needed to gotback = self.smtp.suspect self.assertFalse(gotback == None, "Did not get message from dummy smtp server") # get message received by dummy smtp server msg = gotback.get_message_rep() receivedMsg = msg.get_payload(decode='utf-8') # Build the message according to what Bounce is doing so it can be compared # to what was received from DummySMTPServer with open(blockedfiletemplate) as fp: templatecontent = fp.read() blockinfo = ("%s %s: %s" % (displayname, asciirep, description)).strip() message = apply_template(templatecontent, suspect, dict(blockinfo=blockinfo)) messageB = force_bString(message) # modify received message to add header parts from template messageToCompare = force_bString("To: " + msg['To'] + "\nSubject: " + msg['Subject'] + "\n\n") + force_bString(receivedMsg) # make sure comparison will not fail because of newlines # For example, Python 2.6 has only one "\n" at the end of the received message, whereas Python 2.7 and 3 have to messageToCompare = messageToCompare.replace(b"\r", b"\n").replace( b"\n\n", b"\n") messageB = messageB.replace(b"\r", b"\n").replace(b"\n\n", b"\n") self.assertEqual(messageB, messageToCompare)
def send_vacation_reply(self, suspect, vacation): """send the vacation reply""" # http://mg.pov.lt/blog/unicode-emails-in-python bounce = Bounce(self.config) self.logger.debug('generating vacation message from %s to %s' % ( suspect.to_address, suspect.from_address)) try: from email.mime.text import MIMEText from email.header import Header except ImportError, e: # python 2.4 from email.MIMEText import MIMEText from email.Header import Header
def send_vacation_reply(self, suspect, vacation): """send the vacation reply""" # http://mg.pov.lt/blog/unicode-emails-in-python bounce = Bounce(self.config) self.logger.debug('generating vacation message from %s to %s' % ( suspect.to_address, suspect.from_address)) # check subject subj = vacation.subject if subj is None or subj.strip() == '': self.logger.errror('Vacation has no subject, not sending message') return None # We must choose the body charset manually body = vacation.body if body is None: body = '' for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8': try: body.encode(body_charset) except UnicodeError: pass else: break msg = MIMEText(body.encode(body_charset), 'plain', body_charset) h = Header(vacation.subject, 'ISO-8859-1') msg['Subject'] = h msg['Precedence'] = 'bulk' msg['Auto-Submitted'] = 'auto-replied' msg['From'] = suspect.to_address msg['To'] = suspect.from_address msgcontent = msg.as_string() queueid = bounce.send_template_string( suspect.from_address, msgcontent, suspect, dict()) self.log_bounce(suspect, vacation) self.logger.info('%s sent autoresponder bounce to %s with queueid %s' % (suspect.id, suspect.from_address, queueid)) suspect.set_tag('Vacation.bounce.queueid', queueid) return msgcontent