def test_insert_exception_header_no_separator(self): try: raise Exception("Test") except Exception: pass msg, details = insert_exception_header(malformed1) self._verify_details(details) self._verify_exception_header(msg, details)
def test_insert_exception_header(self): try: raise Exception("Test") except Exception: pass msg, details = insert_exception_header(good1) self._verify_details(details) self._verify_exception_header(msg, details)
def get_full_message(self): """Retrieve the RFC822 message from the IMAP server and return a new IMAPMessage object that has the same details as this message, but also has the substance.""" if self.got_substance: return self assert self.id, "Cannot get substance of message without an id" assert self.uid, "Cannot get substance of message without an UID" assert self.imap_server, "Cannot do anything without IMAP connection" try: self.imap_server.SelectFolder(self.folder.name) except BadIMAPResponseError: self.could_not_retrieve = True print >> sys.stderr, "Could not select folder %s for message " \ "%s (uid %s)" % (self.folder.name, self.id, self.uid) return self try: response = self.imap_server.uid("FETCH", self.uid, self.rfc822_command) except MemoryError: self.could_not_retrieve = True print >> sys.stderr, "MemoryError with message %s (uid %s)" % \ (self.id, self.uid) return self command = "uid fetch %s" % (self.uid,) response_data = self.imap_server.check_response(command, response) data = self.imap_server.extract_fetch_data(response_data) rfc822_data = None for msg_data in data.itervalues(): if self.rfc822_key in msg_data: rfc822_data = msg_data[self.rfc822_key] break if rfc822_data is None: raise BadIMAPResponseError("FETCH response", response_data) try: new_msg = email.message_from_string(rfc822_data, IMAPMessage) except: self.invalid = True text, details = message.insert_exception_header( rfc822_data, self.id) self.invalid_content = text self.got_substance = True print >> sys.stderr, details return self new_msg.folder = self.folder new_msg.previous_folder = self.previous_folder new_msg.rfc822_command = self.rfc822_command new_msg.rfc822_key = self.rfc822_key new_msg.imap_server = self.imap_server new_msg.uid = self.uid new_msg.setId(self.id) new_msg.got_substance = True if not new_msg.has_key(options["Headers", "mailid_header_name"]): new_msg[options["Headers", "mailid_header_name"]] = self.id if options["globals", "verbose"]: sys.stdout.write(chr(8) + "*") return new_msg
def test_insert_exception_header_no_separator(self): # Cause an exception to insert. try: raise Exception("Test") except Exception: pass msg, details = insert_exception_header(malformed1) self._verify_details(details) self._verify_exception_header(msg, details)
def test_insert_exception_header_and_id(self): try: raise Exception("Test") except Exception: pass id = "Message ID" msg, details = insert_exception_header(good1, id) self._verify_details(details) self._verify_exception_header(msg, details) msg = email.message_from_string(msg) headerName = options["Headers", "mailid_header_name"] header = email.Header.Header(id, header_name=headerName) self.assertEqual(msg[headerName], str(header).replace('\n', '\r\n'))
def onRetr(self, command, args, response): """Classifies the message. If the result is ham, then simply pass it through. If the result is an unsure or spam, move it to the appropriate IMAP folder.""" if re.search(r'\n\r?\n', response): terminatingDotPresent = (response[-4:] == '\n.\r\n') if terminatingDotPresent: response = response[:-3] ok, messageText = response.split('\n', 1) try: msg = email.message_from_string(messageText, _class=message.SBHeaderMessage) (prob, clues) = state.bayes.spamprob(msg.tokenize(), evidence=True) msg.addSBHeaders(prob, clues) if (command == 'RETR' or (command == 'TOP' and len(args) == 2 and args[1] == '99999999')): cls = msg.GetClassification() dest_folder = None if cls == options["Headers", "header_ham_string"]: state.numHams += 1 headers = [] for name, value in msg.items(): header = "%s: %s" % (name, value) headers.append(re.sub(r'\r?\n', '\r\n', header)) body = re.split(r'\n\r?\n', messageText, 1)[1] messageText = "\r\n".join(headers) + "\r\n\r\n" + body elif prob > options["Categorization", "spam_cutoff"]: dest_folder = self.spam_folder state.numSpams += 1 else: dest_folder = self.unsure_folder state.numUnsure += 1 if dest_folder: msg = StringIO.StringIO(msg.as_string()) date = imaplib.Time2Internaldate(time.time())[1:-1] dest_folder.addMessage(msg, (), date) messageText = self.intercept_message % (prob,) except: messageText, details = \ message.insert_exception_header(messageText) print >> sys.stderr, details retval = ok + "\n" + messageText if terminatingDotPresent: retval += '.\r\n' return retval else: return response
def test_insert_exception_header_and_id(self): # Cause an exception to insert. try: raise Exception("Test") except Exception: pass id = "Message ID" msg, details = insert_exception_header(good1, id) self._verify_details(details) self._verify_exception_header(msg, details) # Check that ID header is inserted. msg = email.message_from_string(msg) headerName = options["Headers", "mailid_header_name"] header = email.Header.Header(id, header_name=headerName) self.assertEqual(msg[headerName], str(header).replace('\n', '\r\n'))
def test_insert_exception_header_and_id(self): # Cause an exception to insert. try: raise Exception("Test") except Exception: pass id = "Message ID" msg, details = insert_exception_header(good1, id) self._verify_details(details) self._verify_exception_header(msg, details) # Check that ID header is inserted. msg = email.message_from_string(msg) headerName = options["Headers", "mailid_header_name"] header = email.Header.Header(id, header_name=headerName) self.assertEqual(msg[headerName], str(header).replace("\n", "\r\n"))
def onRetr(self, command, args, response): """Classifies the message. If the result is ham, then simply pass it through. If the result is an unsure or spam, move it to the appropriate IMAP folder.""" # XXX This is all almost from sb_server! We could just # XXX extract that out into a function and call it here. # Use '\n\r?\n' to detect the end of the headers in case of # broken emails that don't use the proper line separators. if re.search(r'\n\r?\n', response): # Remove the trailing .\r\n before passing to the email parser. # Thanks to Scott Schlesier for this fix. terminatingDotPresent = (response[-4:] == '\n.\r\n') if terminatingDotPresent: response = response[:-3] # Break off the first line, which will be '+OK'. ok, messageText = response.split('\n', 1) try: msg = email.message_from_string(messageText, _class=message.SBHeaderMessage) # Now find the spam disposition and add the header. (prob, clues) = state.bayes.spamprob(msg.tokenize(), evidence=True) # Note that the X-SpamBayes-MailID header will be worthless # because we don't know the message id at this point. It's # not necessary for anything anyway, so just don't set the # [Headers] add_unique_id option. msg.addSBHeaders(prob, clues) # Check for "RETR" or "TOP N 99999999" - fetchmail without # the 'fetchall' option uses the latter to retrieve messages. if (command == 'RETR' or (command == 'TOP' and len(args) == 2 and args[1] == '99999999')): cls = msg.GetClassification() dest_folder = None if cls == options["Headers", "header_ham_string"]: state.numHams += 1 headers = [] for name, value in msg.items(): header = "%s: %s" % (name, value) headers.append(re.sub(r'\r?\n', '\r\n', header)) body = re.split(r'\n\r?\n', messageText, 1)[1] messageText = "\r\n".join(headers) + "\r\n\r\n" + body elif prob > options["Categorization", "spam_cutoff"]: dest_folder = self.spam_folder state.numSpams += 1 else: dest_folder = self.unsure_folder state.numUnsure += 1 if dest_folder: msg = StringIO.StringIO(msg.as_string()) date = imaplib.Time2Internaldate(time.time())[1:-1] dest_folder.addMessage(msg, (), date) # We have to return something, because the client # is expecting us to. We return a short message # indicating that a message was intercepted. messageText = self.intercept_message % (prob, ) except: messageText, details = \ message.insert_exception_header(messageText) # Print the exception and a traceback. print >> sys.stderr, details retval = ok + "\n" + messageText if terminatingDotPresent: retval += '.\r\n' return retval else: # Must be an error response. return response
def onRetr(self, command, args, response): """Classifies the message. If the result is ham, then simply pass it through. If the result is an unsure or spam, move it to the appropriate IMAP folder.""" # XXX This is all almost from sb_server! We could just # XXX extract that out into a function and call it here. # Use '\n\r?\n' to detect the end of the headers in case of # broken emails that don't use the proper line separators. if re.search(r'\n\r?\n', response): # Remove the trailing .\r\n before passing to the email parser. # Thanks to Scott Schlesier for this fix. terminatingDotPresent = (response[-4:] == '\n.\r\n') if terminatingDotPresent: response = response[:-3] # Break off the first line, which will be '+OK'. ok, messageText = response.split('\n', 1) try: msg = email.message_from_string(messageText, _class=message.SBHeaderMessage) # Now find the spam disposition and add the header. (prob, clues) = state.bayes.spamprob(msg.tokenize(), evidence=True) # Note that the X-SpamBayes-MailID header will be worthless # because we don't know the message id at this point. It's # not necessary for anything anyway, so just don't set the # [Headers] add_unique_id option. msg.addSBHeaders(prob, clues) # Check for "RETR" or "TOP N 99999999" - fetchmail without # the 'fetchall' option uses the latter to retrieve messages. if (command == 'RETR' or (command == 'TOP' and len(args) == 2 and args[1] == '99999999')): cls = msg.GetClassification() dest_folder = None if cls == options["Headers", "header_ham_string"]: state.numHams += 1 headers = [] for name, value in msg.items(): header = "%s: %s" % (name, value) headers.append(re.sub(r'\r?\n', '\r\n', header)) body = re.split(r'\n\r?\n', messageText, 1)[1] messageText = "\r\n".join(headers) + "\r\n\r\n" + body elif prob > options["Categorization", "spam_cutoff"]: dest_folder = self.spam_folder state.numSpams += 1 else: dest_folder = self.unsure_folder state.numUnsure += 1 if dest_folder: msg = StringIO.StringIO(msg.as_string()) date = imaplib.Time2Internaldate(time.time())[1:-1] dest_folder.addMessage(msg, (), date) # We have to return something, because the client # is expecting us to. We return a short message # indicating that a message was intercepted. messageText = self.intercept_message % (prob,) except: messageText, details = \ message.insert_exception_header(messageText) # Print the exception and a traceback. print >> sys.stderr, details retval = ok + "\n" + messageText if terminatingDotPresent: retval += '.\r\n' return retval else: # Must be an error response. return response