Esempio n. 1
0
class POPChannel(asynchat.async_chat):
    def __init__(self, conn, quit_after_one):
        logger.debug(locals())
        self.quit_after_one = quit_after_one
        asynchat.async_chat.__init__(self, conn)
        self.__line = []
        self.push('+OK %s %s' % (socket.getfqdn(), __version__))
        self.set_terminator(TERMINATOR)
        self._activeDataChannel = None

    # Overrides base class for convenience
    def push(self, msg):
        logger.debug(locals())
        asynchat.async_chat.push(self, msg + TERMINATOR)

    # Implementation of base class abstract method
    def collect_incoming_data(self, data):
        logger.debug(locals())
        self.__line.append(data)

    # Implementation of base class abstract method
    def found_terminator(self):
        logger.debug(locals())
        line = ''.join(self.__line)
        self.__line = []
        if not line:
            self.push('500 Error: bad syntax')
            return
        method = None
        i = line.find(' ')
        if i < 0:
            command = line.upper()
            arg = None
        else:
            command = line[:i].upper()
            arg = line[i+1:].strip()
        print(' got: %s' % line)        
        method = getattr(self, 'pop_' + command, None)
        if not method:
            self.push('-ERR Error : command "%s" not implemented' % command)
            return
        method(arg)
        return

    def pop_UIDL(self, which=None):
        logger.debug(locals())
        """Return message digest (unique id) list.

        If 'which', result contains unique id for that message
        in the form 'response mesgnum uid', otherwise result is
        the list ['response', ['mesgnum uid', ...], octets]
        """
        return self.pop_LIST(arg=which)


    def pop_USER(self, user):
        logger.debug(locals())
        # Logs in any username.
        if not user:
            self.push('-ERR: Syntax: USER username')
        else:
            self.username = ''.join((USER_PREFIX,user)) # Store for later.
            logger.info("username=%s" % self.username)
            self.push('+OK Password required')

    def pop_PASS(self, password=''):
        logger.debug(locals())
        self.scraper = OutlookWebScraper(WEBMAIL_SERVER, self.username, password)
        try:
            self.scraper.login()
        except InvalidLogin:
            self.push('-ERR Login failed. (Wrong username/password?)')
        else:
            self.push('+OK User logged in')
            self.inbox_cache = self.scraper.inbox()
            self.msg_cache = [self.scraper.get_message(msg_id) for msg_id in self.inbox_cache]

    def pop_STAT(self, arg):
        logger.debug(locals())
        dropbox_size = sum([len(msg) for msg in self.msg_cache])
        self.push('+OK %d %d' % (len(self.inbox_cache), dropbox_size))

    def pop_NOOP(self, arg):
        self.push('+OK')

    def pop_LIST(self, arg):
        logger.debug(locals())
        if not arg:
            num_messages = len(self.inbox_cache)
            self.push('+OK')
            for i, msg in enumerate(self.msg_cache):
                self.push('%d %d' % (i+1, len(msg)))
            self.push(".")
        else:
            # TODO: Handle per-msg LIST commands
            raise NotImplementedError


    def pop_UIDL(self, arg):
        if not arg:
            num_messages = len(self.inbox_cache)
            self.push('+OK')
            for i, msg in enumerate(self.msg_cache):
                self.push('%d %s' % (i+1, re.search(r"Message-ID: <(.*?)>", msg, re.S | re.I).group(1)))
            self.push(".")
        else:
            found = False
            for i, msg in enumerate(self.msg_cache):
                if (i+1) == int(arg):
                    self.push('+OK %d %s' % (i+1, re.search(r"Message-ID: <(.*?)>", msg, re.S | re.I).group(1)))
                    found = True
            if not found:
                self.push('-ERR no such message, only %d messages in maildrop' % (len(self.inbox_cache)))
            #self.push(".")

    def pop_RETR(self, arg):
        logger.debug(locals())
        if not arg:
            self.push('-ERR: Syntax: RETR msg')
            print '-ERR: Syntax: RETR msg'
        else:
            # TODO: Check request is in range.
            msg_index = int(arg) - 1
            msg = self.msg_cache[msg_index]
            msg_id = self.inbox_cache[msg_index]
            msg = msg.lstrip() + TERMINATOR

            self.push('+OK')
            print '+OK (pop_RETR l_138)'

            for line in quote_dots(msg.split(TERMINATOR)):
                self.push(line)
            self.push('.')

            # Delete the message
            self.scraper.delete_message(msg_id)
            self.push('+OK')
#            self.push(".")

    def pop_QUIT(self, arg):
        logger.debug(locals())
        self.push('+OK Goodbye')
        self.close_when_done()
        if self.quit_after_one:
            # This SystemExit gets propogated to handle_error(),
            # which stops the program. Slightly hackish.
            raise SystemExit

    def handle_error(self):
        logger.debug(locals())
        if self.quit_after_one:
            sys.exit(0) # Exit.
        else:
            asynchat.async_chat.handle_error(self)
Esempio n. 2
0
class POPChannel(asynchat.async_chat):
	def __init__(self, conn, options):
		self.webmail_server = options.webmail_server
		self.unread_messages = options.unread is True
		asynchat.async_chat.__init__(self, conn)
		self.__line = []
		self.push('+OK %s %s' % (socket.getfqdn(), __version__))
		self.set_terminator(TERMINATOR)
		self._activeDataChannel = None

	# Overrides base class for convenience
	def push(self, msg):
		#print msg
		asynchat.async_chat.push(self, msg + TERMINATOR)

	# Implementation of base class abstract method
	def collect_incoming_data(self, data):
		self.__line.append(data)

	# Implementation of base class abstract method
	def found_terminator(self):
		line = ''.join(self.__line)
		self.__line = []
		if not line:
			self.push('500 Error: bad syntax')
			return
		method = None
		i = line.find(' ')
		if i < 0:
			command = line.upper()
			arg = None
		else:
			command = line[:i].upper()
			arg = line[i+1:].strip()
		method = getattr(self, 'pop_' + command, None)
		if not method:
			self.push('-ERR Error : command "%s" not implemented' % command)
			return
		method(arg)
		return

	def pop_USER(self, user):
		# Logs in any username.
		if not user:
			self.push('-ERR: Syntax: USER username')
		else:
			self.username = user # Store for later.
			self.push('+OK Password required')

	def pop_PASS(self, password=''):
		self.scraper = OutlookWebScraper(self.webmail_server, self.username, password)
		try:
			self.scraper.login()
		except InvalidLogin:
			self.push('-ERR Login failed. (Wrong username/password?)')
		else:
			self.push('+OK User logged in')
			self.inbox_cache = self.scraper.inbox(self.unread_messages)
			self.msg_cache = [self.scraper.get_message(msg_id) for msg_id in self.inbox_cache]

	def pop_STAT(self, arg):
		dropbox_size = sum([len(msg) for msg in self.msg_cache])
		self.push('+OK %d %d' % (len(self.inbox_cache), dropbox_size))

	def pop_UIDL(self, arg):
		if not arg:
			self.push('+OK')
			for i, msg in enumerate(self.msg_cache):
				self.push('%d %d' % (i+1, i+1))
			self.push(".")
		else:
			self.push('+OK %s %s' % (arg, arg))

	def pop_LIST(self, arg):
		if not arg:
			self.push('+OK')
			for i, msg in enumerate(self.msg_cache):
				self.push('%d %d' % (i+1, len(msg)))
			self.push(".")
		else:
			# TODO: Handle per-msg LIST commands
			raise NotImplementedError

	def pop_RETR(self, arg):
		if not arg:
			self.push('-ERR: Syntax: RETR msg')
		else:
			# TODO: Check request is in range.
			msg_index = int(arg) - 1
			msg_id = self.inbox_cache[msg_index]
			msg = self.msg_cache[msg_index]
			msg = msg.lstrip() + TERMINATOR

			self.push('+OK')

			for line in quote_dots(msg.split(TERMINATOR)):
				self.push(line)
			self.push('.')

			# Delete the message
			self.scraper.delete_message(msg_id)

	def pop_TOP(self, arg):
		if not arg:
			self.push('-ERR: Syntax: TOP msg')
		else:
			# TODO: Check request is in range.
			msg_index = int(arg.split(' ')[0]) - 1
			msg = self.msg_cache[msg_index]
			msg = msg.split('\r\n\r\n')[0]
			msg = msg.lstrip() + TERMINATOR

			self.push('+OK')

			for line in quote_dots(msg.split(TERMINATOR)):
				self.push(line)
			self.push('.')

	def pop_QUIT(self, arg):
		self.push('+OK Goodbye')
		self.close_when_done()

	def handle_error(self):
		asynchat.async_chat.handle_error(self)
Esempio n. 3
0
class POPChannel(asynchat.async_chat):
    def __init__(self, conn, options):
        self.webmail_server = options.webmail_server
        self.unread_messages = options.unread is True
        asynchat.async_chat.__init__(self, conn)
        self.__line = []
        self.push('+OK %s %s' % (socket.getfqdn(), __version__))
        self.set_terminator(TERMINATOR)
        self._activeDataChannel = None

    # Overrides base class for convenience
    def push(self, msg):
        #print msg
        asynchat.async_chat.push(self, msg + TERMINATOR)

    # Implementation of base class abstract method
    def collect_incoming_data(self, data):
        self.__line.append(data)

    # Implementation of base class abstract method
    def found_terminator(self):
        line = ''.join(self.__line)
        self.__line = []
        if not line:
            self.push('500 Error: bad syntax')
            return
        method = None
        i = line.find(' ')
        if i < 0:
            command = line.upper()
            arg = None
        else:
            command = line[:i].upper()
            arg = line[i + 1:].strip()
        method = getattr(self, 'pop_' + command, None)
        if not method:
            self.push('-ERR Error : command "%s" not implemented' % command)
            return
        method(arg)
        return

    def pop_USER(self, user):
        # Logs in any username.
        if not user:
            self.push('-ERR: Syntax: USER username')
        else:
            self.username = user  # Store for later.
            self.push('+OK Password required')

    def pop_PASS(self, password=''):
        self.scraper = OutlookWebScraper(self.webmail_server, self.username,
                                         password)
        try:
            self.scraper.login()
        except InvalidLogin:
            self.push('-ERR Login failed. (Wrong username/password?)')
        else:
            self.push('+OK User logged in')
            self.inbox_cache = self.scraper.inbox(self.unread_messages)
            self.msg_cache = [
                self.scraper.get_message(msg_id) for msg_id in self.inbox_cache
            ]

    def pop_STAT(self, arg):
        dropbox_size = sum([len(msg) for msg in self.msg_cache])
        self.push('+OK %d %d' % (len(self.inbox_cache), dropbox_size))

    def pop_UIDL(self, arg):
        if not arg:
            self.push('+OK')
            for i, msg in enumerate(self.msg_cache):
                self.push('%d %d' % (i + 1, i + 1))
            self.push(".")
        else:
            self.push('+OK %s %s' % (arg, arg))

    def pop_LIST(self, arg):
        if not arg:
            self.push('+OK')
            for i, msg in enumerate(self.msg_cache):
                self.push('%d %d' % (i + 1, len(msg)))
            self.push(".")
        else:
            # TODO: Handle per-msg LIST commands
            raise NotImplementedError

    def pop_RETR(self, arg):
        if not arg:
            self.push('-ERR: Syntax: RETR msg')
        else:
            # TODO: Check request is in range.
            msg_index = int(arg) - 1
            msg_id = self.inbox_cache[msg_index]
            msg = self.msg_cache[msg_index]
            msg = msg.lstrip() + TERMINATOR

            self.push('+OK')

            for line in quote_dots(msg.split(TERMINATOR)):
                self.push(line)
            self.push('.')

            # Delete the message
            self.scraper.delete_message(msg_id)

    def pop_TOP(self, arg):
        if not arg:
            self.push('-ERR: Syntax: TOP msg')
        else:
            # TODO: Check request is in range.
            msg_index = int(arg.split(' ')[0]) - 1
            msg = self.msg_cache[msg_index]
            msg = msg.split('\r\n\r\n')[0]
            msg = msg.lstrip() + TERMINATOR

            self.push('+OK')

            for line in quote_dots(msg.split(TERMINATOR)):
                self.push(line)
            self.push('.')

    def pop_QUIT(self, arg):
        self.push('+OK Goodbye')
        self.close_when_done()

    def handle_error(self):
        asynchat.async_chat.handle_error(self)
Esempio n. 4
0
class POPChannel(asynchat.async_chat):
    def __init__(self, conn, quit_after_one):
        logger.debug(locals())
        self.quit_after_one = quit_after_one
        asynchat.async_chat.__init__(self, conn)
        self.__line = []
        self.push('+OK %s %s' % (socket.getfqdn(), __version__))
        self.set_terminator(TERMINATOR)
        self._activeDataChannel = None

    # Overrides base class for convenience
    def push(self, msg):
        logger.debug(locals())
        asynchat.async_chat.push(self, msg + TERMINATOR)

    # Implementation of base class abstract method
    def collect_incoming_data(self, data):
        logger.debug(locals())
        self.__line.append(data)

    # Implementation of base class abstract method
    def found_terminator(self):
        logger.debug(locals())
        line = ''.join(self.__line)
        self.__line = []
        if not line:
            self.push('500 Error: bad syntax')
            return
        method = None
        i = line.find(' ')
        if i < 0:
            command = line.upper()
            arg = None
        else:
            command = line[:i].upper()
            arg = line[i + 1:].strip()
        print(' got: %s' % line)
        method = getattr(self, 'pop_' + command, None)
        if not method:
            self.push('-ERR Error : command "%s" not implemented' % command)
            return
        method(arg)
        return

    def pop_UIDL(self, which=None):
        logger.debug(locals())
        """Return message digest (unique id) list.

        If 'which', result contains unique id for that message
        in the form 'response mesgnum uid', otherwise result is
        the list ['response', ['mesgnum uid', ...], octets]
        """
        return self.pop_LIST(arg=which)

    def pop_USER(self, user):
        logger.debug(locals())
        # Logs in any username.
        if not user:
            self.push('-ERR: Syntax: USER username')
        else:
            self.username = ''.join((USER_PREFIX, user))  # Store for later.
            logger.info("username=%s" % self.username)
            self.push('+OK Password required')

    def pop_PASS(self, password=''):
        logger.debug(locals())
        self.scraper = OutlookWebScraper(WEBMAIL_SERVER, self.username,
                                         password)
        try:
            self.scraper.login()
        except InvalidLogin:
            self.push('-ERR Login failed. (Wrong username/password?)')
        else:
            self.push('+OK User logged in')
            self.inbox_cache = self.scraper.inbox()
            self.msg_cache = [
                self.scraper.get_message(msg_id) for msg_id in self.inbox_cache
            ]

    def pop_STAT(self, arg):
        logger.debug(locals())
        dropbox_size = sum([len(msg) for msg in self.msg_cache])
        self.push('+OK %d %d' % (len(self.inbox_cache), dropbox_size))

    def pop_NOOP(self, arg):
        self.push('+OK')

    def pop_LIST(self, arg):
        logger.debug(locals())
        if not arg:
            num_messages = len(self.inbox_cache)
            self.push('+OK')
            for i, msg in enumerate(self.msg_cache):
                self.push('%d %d' % (i + 1, len(msg)))
            self.push(".")
        else:
            # TODO: Handle per-msg LIST commands
            raise NotImplementedError

    def pop_UIDL(self, arg):
        if not arg:
            num_messages = len(self.inbox_cache)
            self.push('+OK')
            for i, msg in enumerate(self.msg_cache):
                self.push(
                    '%d %s' %
                    (i + 1, re.search(r"Message-ID: <(.*?)>", msg,
                                      re.S | re.I).group(1)))
            self.push(".")
        else:
            found = False
            for i, msg in enumerate(self.msg_cache):
                if (i + 1) == int(arg):
                    self.push('+OK %d %s' %
                              (i + 1,
                               re.search(r"Message-ID: <(.*?)>", msg,
                                         re.S | re.I).group(1)))
                    found = True
            if not found:
                self.push(
                    '-ERR no such message, only %d messages in maildrop' %
                    (len(self.inbox_cache)))
            #self.push(".")

    def pop_RETR(self, arg):
        logger.debug(locals())
        if not arg:
            self.push('-ERR: Syntax: RETR msg')
            print '-ERR: Syntax: RETR msg'
        else:
            # TODO: Check request is in range.
            msg_index = int(arg) - 1
            msg = self.msg_cache[msg_index]
            msg_id = self.inbox_cache[msg_index]
            msg = msg.lstrip() + TERMINATOR

            self.push('+OK')
            print '+OK (pop_RETR l_138)'

            for line in quote_dots(msg.split(TERMINATOR)):
                self.push(line)
            self.push('.')

            # Delete the message
            self.scraper.delete_message(msg_id)
            self.push('+OK')


#            self.push(".")

    def pop_QUIT(self, arg):
        logger.debug(locals())
        self.push('+OK Goodbye')
        self.close_when_done()
        if self.quit_after_one:
            # This SystemExit gets propogated to handle_error(),
            # which stops the program. Slightly hackish.
            raise SystemExit

    def handle_error(self):
        logger.debug(locals())
        if self.quit_after_one:
            sys.exit(0)  # Exit.
        else:
            asynchat.async_chat.handle_error(self)