Beispiel #1
0
    def __init__(self,
                 host,
                 user=None,
                 password=None,
                 auth_type='password',
                 use_ssl=True,
                 port=None,
                 debug=False,
                 conn_cls=None,
                 session=None):
        """Initialize a Mailbox instance."""
        Mailbox.__init__(self, '/')
        self.host = host
        self.user = user
        self.password = password
        self.auth_type = auth_type
        self.use_ssl = use_ssl
        self.port = port
        self.debug = debug
        self.conn_cls = conn_cls
        self.session = session

        self._lock = MboxRLock()
        self._pop3 = None
        self._connect()
 def fetch_mailboxes(self):
     response, mailbox_list = self.imap.list()
     if response == 'OK':
         for mailbox in mailbox_list:
             mailbox_name = mailbox.split('"/"')[-1].replace('"', '').strip()
             mailbox = Mailbox(self)
             mailbox.external_name = mailbox_name
             self.mailboxes[mailbox_name] = mailbox
Beispiel #3
0
 def __init__(self, statsFilename="loggerStats.json"):
     """ Initializes object
         resultsFilename:    name of file that will be used as internal container for current results
     """
     self.mailbox = Mailbox()
     self.unreadEmailsNumber = 0
     self.threads = [threading.Thread(target=self.__samplingThread)]
     self.statsFilename = statsFilename
     self.__getPreviousStateFromFile()
Beispiel #4
0
 def __init__(self, host, port, vk, sk):
     threading.Thread.__init__(self)
     self.messages = Messages()
     self.mailbox = Mailbox(host, port, timeout=None)
     self.vk = vk
     self.sk = sk
     self.session = None
     self.number = None
     self.number_of_players = None
     self.players = {}
Beispiel #5
0
 def fetch_mailboxes(self):
     response, mailbox_list = self.imap.list()
     if response == 'OK':
         for mailbox_str in mailbox_list:
             mailbox = Mailbox(self)
             mailbox.parse(mailbox_str)
             self.mailboxes[mailbox.external_name] = mailbox
             if mailbox.gmail_special:
                 self.gmail_special_mailboxes[mailbox.gmail_special] = mailbox
     else:
         print mailbox_list
Beispiel #6
0
 def fetch_mailboxes(self):
     response, mailbox_list = self.imap.list()
     if response == 'OK':
         for mailbox_str in mailbox_list:
             mailbox = Mailbox(self)
             mailbox.parse(mailbox_str)
             self.mailboxes[mailbox.external_name] = mailbox
             if mailbox.gmail_special:
                 self.gmail_special_mailboxes[
                     mailbox.gmail_special] = mailbox
     else:
         print mailbox_list
Beispiel #7
0
 def fetch_mailboxes(self):
     response, mailbox_list = self.imap.list()
     if response == 'OK':
         for mailbox in mailbox_list:
             mailbox_name = mailbox.split('"/"')[-1].replace('"', '').strip()
             mailbox = Mailbox(self)
             mailbox.external_name = mailbox_name
             if mailbox_name.split('/')[0] !='[Gmail]':
                 label = Label(self)
                 label.label_tree = mailbox_name
                 self.labels[mailbox_name] = label
             self.mailboxes[mailbox_name] = mailbox
    def __init__(self, httpPort):
        super().__init__()
        self.mailbox = Mailbox.create_mailbox()
        self.messageRouterMailboxes = []  # Contains all message routers in system
        self.userToRouterMailbox = {}  # Maps a user name to residing message router. Used for private messages
        self.userToWebSocketConnection = {}  # Holds local web sockets connections
        self.pendingUserLoginToWebSocketConnection = {}  # Holds connections for users that are requesting login at user registry
        self.clientMessageHandlers = {
            MessageType.LOGIN: self.login_handler,
            MessageType.LOGOUT: self.logout_handler,
            MessageType.PUBLIC_MESSAGE: self.public_message_handler,
            MessageType.PRIVATE_MESSAGE: self.private_message_handler,
            MessageType.LIST_ALL_USERS: self.list_all_users_handler
        }
        self.serverMessageHandlers = {
            MessageType.USER_REGISTRY_NEW_USER: self.user_registry_new_user_handler,
            MessageType.USER_REGISTRY_REMOVE_USER: self.user_registry_remove_user_handler,
            MessageType.NEW_USER: self.new_user_handler,
            MessageType.REMOVE_USER: self.remove_user_handler,
            MessageType.NEW_MESSAGE_ROUTER: self.new_message_router_handler,
            MessageType.FORWARD_PUBLIC_MESSAGE_TO_ALL_CLIENTS: self.forward_public_message_to_all_clients_handler,
            MessageType.FORWARD_PRIVATE_MESSAGE_TO_CLIENT: self.forward_private_message_to_client
        }

        self.userRegistryMailbox = self.mailbox.get_mailbox_proxy('user_registry')
        self.loadBalancerMailbox = self.mailbox.get_mailbox_proxy('load_balancer')

        # Notify load balancer about this message router
        msg = self.mailbox.create_message(MessageType.REGISTER_CHAT_SERVER, httpPort)
        self.loadBalancerMailbox.put(msg)
Beispiel #9
0
    def __init__(self, host,
                 user=None, password=None, use_ssl=True, port=None,
                 debug=False, conn_cls=None):
        """Initialize a Mailbox instance."""
        Mailbox.__init__(self, '/')
        self.host = host
        self.user = user
        self.password = password
        self.use_ssl = use_ssl
        self.port = port
        self.debug = debug
        self.conn_cls = conn_cls

        self._lock = MboxRLock()
        self._pop3 = None
        self._connect()
Beispiel #10
0
    def __init__(self, path, factory=None, create=True, fakeSpec=None, folderName="/"):
        Mailbox.__init__(self, path, factory, create)

        try:
            import fakeSpec
            self._messages = fakeSpec.fakeMailBuilder()
        except ImportError:
            self._messages = {}
            for i in range(10):
                m = Message()
                m.set_payload("Fake message " + str(i))
                self._messages[i] = m

        self.iterkeys = self._messages.iterkeys
        self.has_key = self._messages.has_key
        self.__len__ = self._messages.__len__
Beispiel #11
0
    def create_mailbox(self, mailbox_name):
        mailbox = self.mailboxes.get(mailbox_name)
        if not mailbox:
            self.imap.create(mailbox_name)
            mailbox = Mailbox(self, mailbox_name)
            self.mailboxes[mailbox_name] = mailbox

        return mailbox
Beispiel #12
0
    def read(self, item: Item, box: mailbox.Mailbox) -> bool:

        fs_info = Path(item.data.filename)
        item.size = fs_info.stat().st_size

        mbx = mailbox.mbox(item.data.filename)
        mbx.lock()

        max_count = len(mbx)

        progress = pmlib.log.progress(max_count)

        count = "{0:d}".format(max_count).rjust(6, " ")
        size = convert_bytes(item.size)

        pmlib.log.inform(
            item.parent.name,
            "{0:s} mails for {1:s} ({2:s})".format(count, item.name, size))

        n = 0
        for msg in mbx:
            try:
                box.add(msg)
            except UnicodeEncodeError as e:
                text = self._store_fault(item, n, msg)
                item.add_error(n, text, e)
                item.report.failure += 1
            else:
                item.report.success += 1

            box.flush()
            progress.inc()
            n += 1
            item.report.count = n

        pmlib.log.clear()

        for _error in item.report.error:
            pmlib.log.error(_error.text)

        mbx.unlock()
        return True
Beispiel #13
0
    def __init__(self, name):
        self.name = name
        self.clientKey = None
        self.serverHost = None
        self.serverPort = None

        self.messageCallback = None
        self.requestCallback = None
        self.errorCallback = None

        self.writer = None
        self.reader = None

        self.socket = None

        self.mailbox = Mailbox(name)

        self.reqSeq = 0
        self.reqLock = thread.allocate_lock()

        self.connected = False
 def __init__(self):
     super().__init__()
     self.serverList = []
     self.serverListLock = threading.Lock()
     self.mailbox = Mailbox.create_mailbox('load_balancer')
Beispiel #15
0
def test_mailbox():
    connection = MockConnection()
    name = None
    mailbox = Mailbox(connection, name)
    assert mailbox.get_message(1)
Beispiel #16
0
class Logger:
    delayIntervals = {
        "ten_seconds": 10,
        "one_min": 60,
        "five_minutes": 300,
        "ten_minutes": 600
    }
    stateLabels = ["unread_emails"]

    def main(self):
        """ Executes main functionality of logger app
        """
        self.startSamplingForEmails()

    def notify(self, notifyData):
        """ Executes pop up notify with given data 
            notifyData: (string) data to show for user
        """
        subprocess.run(["notify", notifyData])

    def startSamplingForEmails(self):
        """ Starts polling for data 
        """
        for thread in self.threads:
            thread.start()

    def __init__(self, statsFilename="loggerStats.json"):
        """ Initializes object
            resultsFilename:    name of file that will be used as internal container for current results
        """
        self.mailbox = Mailbox()
        self.unreadEmailsNumber = 0
        self.threads = [threading.Thread(target=self.__samplingThread)]
        self.statsFilename = statsFilename
        self.__getPreviousStateFromFile()

    def __samplingThread(self):
        """ Thread polling for data from mailbox 
        """
        while True:
            time.sleep(Logger.delayIntervals["ten_seconds"])
            currentUnreadEmailsNr = self.mailbox.getUnreadMessagesNumber()

            if self.unreadEmailsNumber != currentUnreadEmailsNr:
                self.unreadEmailsNumber = currentUnreadEmailsNr
                self.__saveCurrentStateToFile()
                self.notify("new e-mail has benn received!")

    def __getPreviousStateFromFile(self):
        """ Gets current stats associated with unread data etc. from file 
        """
        readState = None

        if os.path.exists(self.statsFilename):
            with open(self.statsFilename, mode='r') as statsFile:
                readState = json.load(statsFile)

        if None != readState:
            self.unreadEmailsNumber = readState["unread_emails"]

    def __saveCurrentStateToFile(self):
        """ Saves current stats associated with unread data etc. into file 
        """
        currentState = {"unread_emails": self.unreadEmailsNumber}

        with open(self.statsFilename, mode='w') as statsFile:
            json.dump(currentState, statsFile)
Beispiel #17
0
 def __init__(self, path, folder, mailStorage):
     """Initialize a Maildir instance."""
     Mailbox.__init__(self, path, None, False)
     self.folder = folder
     self.mailStorage = mailStorage
Beispiel #18
0
    def _initMailboxList(self, init=0):

        "Initialize mailboxes list if needed or requested (init=1)"

        if init or not self.mailboxes:
            self.mailboxes = Mailbox()
Beispiel #19
0
class IMAP4:

    """
    IMAP4: Implements one IMAP (remote or local) connection

    Server replies other than OK will generate exceptions.
    Data returned by the server is parsed into python data structures
    (tuples and dictionaries) as described for each method.

    implemented methods:
        Mailbox methods:
            list( getStatus=0, update=0 )
            lsub( getStatus=0, update=0 )
            (messages, unread, recent) = status( mailbox )
            (messages, unread, recent) = select( mailbox )
            create( base, name )
            delete( mailbox )
            expunge( mailbox )
            subscribe( mailbox )
            unsubscribe( mailbox )
            rename( oldmailbox, newbase, newname )
            select( mailbox )
            getSelected( leafOnly = 0 )
        Message methods:
            search(**criteria) (can do sorting if IMAP supports it)
            msgStructure( messageID )
            msgCopy( message, new_mailbox )
            msgMove( message, new_mailbox )
            msgDelete( message )
            realDelete( message )
            msgStore( mailbox, rfc822message )
            msgRetrieve( message, [part, encoding] )
            msgFlag( message, set )
    """

    def __init__(self, type=LOCAL,
                  maildir="",
                  host="", username="", password=""):

        """
        Open connection to IMAP server.

        Specify maildir if type is imap4rev1.LOCAL
        or host, [username] and password if type is imap4rev1.REMOTE
        (if username is not provided email will be used instead)
        """

        if type == LOCAL:
            self.type = LOCAL
            self.imap = myimaplib.IMAP4(maildir=maildir)

        else:
            self.type = REMOTE
            self.imap = myimaplib.IMAP4(host=host)
            self.imap.login(username, password)

        self.mailboxes = None
        self.inbox = "INBOX"
        self.delimiter = None  # hierarchy delimiter, set below
        self.delimiter_incr = 3  # how many chars does its representation take

        self.selected = ""  # selected mailbox
        self.message_set = None  # message set gotten from a search
        self.header_set = None  # expanded header list for above message set
        self.getStatus = 0  # collect message counts by default ? no.
        self.getSubscribed = 0  # get subscribed mailboxes as well

        # Identify hierarchy delimiter used by server

        result = self.imap.list('""', '""')
        result = self._checkStatus(result)
        self._parseMailboxResponse(result[0])  # will update delimiter

        # Cached message structure
        self.lastUID = None
        self.lastStructure = None


    def close(self):

        "Close IMAP connection. You shouldn't use this object after this."

        try:
            if self.imap:
                self.imap.logout()  # an implicit close() happens if needed
        except AttributeError: pass
        self.imap = None


    def __del__(self):
        self.close()


    ###########################################################################
    # MAILBOX-RELATED METHODS
    ###########################################################################
    # non-existent mailboxes should be ignored if they're 'subscribed'

    def list(self, getSubscribed=None, getStatus=None,
              update=0, noData=0):

        """
        Retrieve mailbox hierarchy from server

        See Mailbox.makeDict() for format of returned data
        getStatus=1 retrieves/updates status info on each mailbox (slower!)
        getSubscribed=1 updates the 'subscribed' field in list (i.e. LIST+LSUB)
        Set update=1 to force requerying server (or you might get cached data)
        noData=1 just updates internal list, does not return anything
        """

        # Simplified list() always searches from the top level

        self._initMailboxList(update)

        # Save value of getStatus/getSubscribed so future list updates
        # (after a rename, delete, etc) will update the info the same way
        # we will keep the value that returns the larger set
        if getStatus and self.getStatus < getStatus:
            self.getStatus = getStatus

        if getSubscribed and self.getSubscribed < getSubscribed:
            self.getSubscribed = getSubscribed

        if not self.mailboxes.getName() or update:

            result = self.imap.list()
            result = self._checkStatus(result)
            self._updateMailboxList(result, 0)

            if self.getSubscribed:
                result = self.imap.lsub()
                result = self._checkStatus(result)
                self._updateMailboxList(result, 1)

            # Update root inbox (namespace)
            self.inbox = self.mailboxes.getName()

            # Fix root inbox if not subscribed
            # if not self.mailboxes.subscribed:
            #     self.subscribe(self.inbox)

        if noData:
            return None
        else:
            return self.mailboxes.makeDict()


    def lsub(self, getStatus=None, update=0, noData=0):
        "Get list of subscribed mailboxes"

        return self.list(getSubscribed=1, getStatus=getStatus,
                          update=update, noData=noData)


    def status(self, mailbox):

        """
        Check status of mailbox (total messages, unseen messages etc)

        Returns (messages, unseen, recent) and updates mailboxes structure
        NOTE: Message count may look wrong if there are \\Deleted messages
        Don't call status() on mailboxes with the NOSELECT flag set.
        """

        count = unseen = recent = 0

        result = self.imap.status(mailbox, "(MESSAGES RECENT UNSEEN)")
        result = self._checkStatus(result)[0]

        # parse result. Example: '"INBOX" (MESSAGES 9 UNSEEN 6)'

        # rindex because the mailbox name may contain "(" as well
        index = rindex(result, "(")
        result = split(result[index + 1:-1])

        key = None
        for item in result:
            if not key:
                key = upper(item)
            else:
                if key == "MESSAGES": count = int(item)
                elif key == "UNSEEN": unseen = int(item)
                elif key == "RECENT": recent = int(item)
                key = None

        if self.mailboxes:
            self.mailboxes.add(self._makeTuple(mailbox), name=mailbox,
                                count=count, unseen=unseen, recent=recent)
        return (count, unseen, recent)


    def select(self, mailbox=""):

        "select specified mailbox, returns its status() "
        "mailbox is in IMAP format i.e. INBOX.Trash"

        self.lastUID = None  # reset cache

        if len(mailbox) == 0:
            mailbox = self.inbox

        result = self.imap.select(mailbox)
        result = self._checkStatus(result)
        self.selected = mailbox
        self.message_set = None  # message set gotten from a search
        self.header_set = None  # expanded header list for above message set
        # count = int(result[0])

        # The server returns the status on SELECT, but somehow the imaplib
        # manages to ignore it, so we need this extra STATUS
        return self.status(mailbox)


    def getSelected(self, leafOnly=0):
        m = self.selected
        if leafOnly:
            return self._makeTuple(m)[-1]
        else:
            return m


    def create(self, base, name=None):

        """
        Create a new mailbox and returns its IMAP name
        If name is not specified then the 'base' mailbox is created

        Example: create( 'INBOX.Received' , 'Old' ) -> 'INBOX.Received.Old'
                 create( 'INBOX.Sent' )             -> 'INBOX.Sent'
        """

        # Create the entire path if needed

        self.list(noData=1)

        mailboxT = self._makeTuple(base)
        if name:
            mailboxT.append(name)

        base = mailboxT[0]
        baseT = [base]

        for name in mailboxT[1:]:
            baseT.append(name)
            base = base + self.delimiter + name
            mailbox = self.mailboxes.getLeaf(baseT)
            if not mailbox:
                # Need to create folder at this level
                # Make sure the name itself contains only allowed characters
                if not RE_MAILBOX.search(name):
                    raise argumentError("Invalid mailbox name " + name)

                result = self.imap.create('"' + base + '"')
                result = self._checkStatus(result)

                self.mailboxes.add(baseT, name=base)

            elif mailbox.flags.has_key("NOSELECT"):
                raise argumentError("Folder %s does not exist!" % base)

        return base


    def delete(self, mailbox):

        """
        Delete an existing mailbox

        Removes all messages in mailbox. Does NOT remove subfolders.
        We require that the mailbox does not have children to avoid problems.
        """

        self.list(noData=1)
        mailboxT = self._makeTuple(mailbox)
        mbox_obj = self.mailboxes.getLeaf(mailboxT)

        if mbox_obj:
            if mbox_obj.children:
                raise argumentError("Mailbox " + mailbox + " has subfolders.")

            self.imap.delete(mailbox)  # ignore error
            self.mailboxes.remove(mailboxT)

        else:
            raise argumentError("Nonexistent mailbox " + mailbox)


    def expunge(self, mailbox):

        "Delete all messages marked as \\Deleted from the mailbox"

        if not self.selected == mailbox:
            self.select(mailbox)

        result = self.imap.expunge()
        result = self._checkStatus(result)

        # result is a "list" of expunged messages


    def subscribe(self, mailbox):

        "Mark mailbox as 'subscribed'"

        # We impose the limitation that we can only do it to existing mailboxes

        self.list(noData=1)

        if not self.mailboxes.getLeaf(self._makeTuple(mailbox)):
            raise argumentError("Nonexistent mailbox: " + mailbox)

        result = self.imap.subscribe(mailbox)
        self._checkStatus(result)

        # Record the modification in self.mailboxes
        self.mailboxes.add(self._makeTuple(mailbox), subscribed=1)


    def unsubscribe(self, mailbox):

        "Unmark subscribed mailbox"

        self.list(noData=1)

        result = self.imap.unsubscribe(mailbox)
        self._checkStatus(result)

        # Record the modification in self.mailboxes
        self.mailboxes.add(self._makeTuple(mailbox), subscribed=0)


    def rename(self, oldmailbox, newbase=None, newname=None):

        """
        Move existing mailbox to new folder, or rename mailbox.

        Returns new imap name.
        Examples:
        rename( 'INBOX.Received', 'INBOX.Old' )        -> 'INBOX.Old.Received'
        rename( 'INBOX.Received', 'INBOX.Old', 'New' ) -> 'INBOX.Old.New'
        rename( 'INBOX.Received', newname = 'New' )    -> 'INBOX.New'
        NOTE: All 'subfolders' are also moved/rename together with their parent
        """

        # Extract the folder name from oldmailbox
        oldmailboxT = self._makeTuple(oldmailbox)
        name = oldmailboxT[-1]

        self.list(getSubscribed=1, noData=1)
        try:
            children = self.mailboxes.getLeaf(oldmailboxT).hasChildren()
        except AttributeError:
            raise argumentError("Nonexistent mailbox: " + oldmailbox)

        if not newbase:
            newbaseT = oldmailboxT[:-1]
        else:
            # Make sure the folder where we want to attach this exists
            newbaseT = self._makeTuple(newbase)
            if not self.mailboxes.getLeaf(newbaseT):
                raise argumentError("Nonexistent mailbox: " + newbase)

        if not newname:
            newname = name

        if not RE_MAILBOX.search(newname) or self.delimiter in newname:
            raise argumentError("Invalid mailbox name " + newname)

        newnameT = newbaseT + [newname]

        if self.mailboxes.getLeaf(newnameT):
            raise argumentError("Mailbox already exists: " + newname)

        newname = join(newnameT, self.delimiter)

        # NOTE: courier-imap seems to interpret mailbox names differently
        # in that you can RENAME "mailbox." and it will rename its children
        # but not the mailbox (use RENAME mailbox for that).

        result = self.imap.rename(oldmailbox, newname)
        # hmm, imapd seems to return OK unless the target already exists
        self._checkStatus(result)
        if self.mailboxes.getLeaf(oldmailboxT).subscribed:
            self.mailboxes.copy(oldmailboxT, newnameT, newname)
            self.unsubscribe(oldmailbox)
            self.subscribe(newname)
        self.status(newname)

        if children:
            # Since IMAP RENAME does NOT affect children names we need to
            # recursively rename/move all children now
            for child in children.keys():
                src = oldmailbox + self.delimiter + child
                self.rename(src, newname, str(child))

        self.mailboxes.remove(oldmailboxT)
        # self.list(update=1)

        return newname


    ###########################################################################
    # MESSAGE-RELATED METHODS
    ###########################################################################
    # WARNING: they all REQUIRE a mailbox already select()-ed
    # All these methods work with UIDs to keep references valid over different
    # sessions (they don't, however, check UIDVALIDITY)


    def search(self, search=None, **criteria):

        """
        Search for messages in current mailbox

        Returns a tuple with message headers (see the headers() method
        elsewhere for the format of the header set).

        Don't specify any criteria to get a listing of all messages.
        This does not implement all the search options in IMAP4rev1
        You can also set the SORT criteria to request sorting.
        Possible values: [REVERSE] ARRIVAL CC DATE FROM SIZE SUBJECT TO

        Examples:
        search()
        search( FROM='lc', NOTSUBJECT = 1, SUBJECT = 'imap' )
        (all messages containing 'lc' in the From: header but not having
         'imap' in the subject)
        search( SORT='REVERSE DATE' )
        """

        if not self.selected:
            raise argumentError("No mailbox selected for search")

        query = []  # query elements that are ANDed together
        or_query = []  # query elements that are ORed together

        # Check criteria and build query

        # string-argument options. Negated if "notoption" is 1.
        for key in ("FROM", "TO", "CC", "BCC", "SUBJECT", "BODY"):
            if search:
                or_query.append(self._simpleQuery(key, search))

            elif criteria.has_key(key):
                query.append(self._simpleQuery(key, criteria[key],
                                                  criteria.get("NOT" + key, 0)))


        # Combine string search options into a single query if there
        # are alternative OR statements. The result will be ANDed with
        # the next criteria below.
        # IMAP uses prefixed binary logic (i.e. "OR (OR c1 c2) c3" etc)
        if or_query:  # we know there are more than 1 element
            c1 = or_query.pop()
            while or_query:
                c2 = or_query.pop()
                c1 = "OR (%s) %s" % (c1, c2)

            query.append(c1)

        # date-argument options.
        # IGNORE for now (until we can check/convert date format to DD-MON-YYYY)
        for key in ("BEFORE", "ON", "SINCE",
                     "SENTBEFORE", "SENTON", "SENTSINCE"):
            if criteria.has_key(key):
                pass

        # no argument options
        for key in ("NEW", "OLD", "FLAGGED", "SEEN", "RECENT", "ANSWERED",
                     "DELETED"):
            if criteria.has_key(key):
                if criteria[key] == 0:
                    query.append("NOT " + key)
                else:
                    query.append(key)

        if len(query) == 0:
            query.append("ALL")  # must have something there

        # Exclude \Deleted messages if the UNDELETED criteria is not present
        if not criteria.has_key("DELETED"):
            query.append("NOT DELETED")

        query = "(" + join(query, " ") + ")"

        # See if we want the results sorted.
        # If we do, try to use the SORT extension if available, otherwise
        # it gets more complicated because we need to get the headers
        sort = None
        result = None
        if criteria.has_key("SORT"):  # We want the results sorted

            if "SORT" in self.imap.capabilities:
                result = self.imap.sort(criteria=query,
                                         sort="(" + criteria["SORT"] + ")")
            else:
                sort = criteria["SORT"]  # signal that we need "manual" sorting
                result = self.imap.uid("SEARCH", query)
        else:
            result = self.imap.uid("SEARCH", query)

        result = self._checkStatus(result)[0]

        # result is now a string with numbers: '3 6 7 10'
        # Make it a tuple. We don't convert to ints because as far as we
        # are concerned we don't care what is in there

        if sort:
            return self._sort(split(result), sort)
        else:
            return self.headers(split(result))


    def headers(self, message_set):

        "Retrieve headers for a message set"

        # Sample headers element (generated by _parseFetch):
        # {
        #   envelope_data,
        #   'FLAGS':        {'Seen': 1, 'Deleted': 1 },
        #   'INTERNALDATE': '07-Feb-2001 18:45:28 -0800',
        #   'RFC822.SIZE':  2013,
        #   'UID':          3
        # }

        # envelope_data adds the following fields:
        # DATE, SUBJECT, FROM, SENDER, REPLYTO, TO, CC, BCC, INREPLYTO, MSGID
        # Header fields are tuples with email addresses
        # Note that envelope DATE is in RFC822 format

        # Save message_set and headers list for future reference
        if type(message_set) == type("string"):
            message_set = (message_set,)
        self.header_set = self.fetch(message_set, "ALL")
        self.message_set = message_set

        return self.header_set


    def msgStructure(self, message):

        """Return message structure for this message UID

        message structure returned as follows:
        simple message is a dictionary as described in _parseMsgSimple()
        multipart message is a list containing the subtype then the body parts
        """

        if self.lastUID == message:
            return self.lastStructure

        # BODY.PEEK does not mark the message as \Seen
        data = self.fetch((message,), "BODY.PEEK")

        if not data or not data[0]:
            raise argumentError("Message UID %s does not exist!" % message)

        structure = self._parseMsg(data[0]["BODY"])
        self.lastUID = message
        self.lastStructure = structure
        return structure


    def fetch(self, message_set, message_parts):
        "Generic FETCH. message_set is a tuple or list!."

        "Does not update self.header_set."

        "Returns a list of dictionaries"
        "Don't use to fetch body parts though, see comments below."

        if len(message_set):
            result = self.imap.uid("FETCH", join(message_set, ","),
                                    "(" + message_parts + ")")
            result = self._checkStatus(result)
        else:
            result = ()

        data = []
        for line in result:

            # imaplib splits the result if it finds any literals but it also
            # incorrectly closes the current tuple right after the literal
            # body so the rest of the line comes as the next "response".
            # This will definitely screw up our parsing so don't request
            # things that can return literals (like BODY parts and such)
            # We kludge things here for when the literal is the last element
            if type(line) == type(()):
                line = join(line, "\r\n")
            # Then next line could be ")" and we need to skip it.
            elif line == ')':
                continue

            parsed = self._parseFetch(line)

            # If we have an ENVELOPE here try to "humanize" it
            # We also merge the envelope fields in the main dict because
            # I think there are no key name conflicts
            if parsed:
                if parsed.has_key("ENVELOPE"):
                    new_envelope = self._fixEnvelope(parsed["ENVELOPE"])
                    parsed.update(new_envelope)
                    del parsed["ENVELOPE"]

            data.append(parsed)

        return data


    def msgFlag(self, message, set=None, flag="Flagged"):

        "Get/Set user flag (Flagged) on message"

        # You need to see the RFC if you want to change other flags

        if set != None:
            flags = "+FLAGS.SILENT"
            if set == 0:
                flags = "-FLAGS.SILENT"

            result = self.imap.uid("STORE", message, flags, "\\%s" % flag)
            result = self._checkStatus(result)
            return set

        else:
            result = self.fetch((message,), "FLAGS")[0]
            return result["FLAGS"].has_key(flag)


    def msgCopy(self, message, new_mailbox):

        "Copy a message (specified by UID) to another mailbox"

        result = self.imap.uid("COPY", message, new_mailbox)
        result = self._checkStatus(result)


    def msgMove(self, message, new_mailbox):

        "Move a message (specified by UID) to another mailbox"

        self.msgCopy(message, new_mailbox)
        self.realDelete(message)


    def msgDelete(self, message):

        "Move the message to Trash"

        self.list(noData=1)
        trash = self.mailboxes.getLeaf((self.inbox, "Trash"))
        if not trash:
            # Trash does not exist, try to create it
            trash = self.create(self.inbox, "Trash")

        self.msgMove(message, str(trash))


    def realDelete(self, message):

        "Mark the message as deleted (will be deleted on logout or expunge)"

        result = self.imap.uid("STORE", message, "+FLAGS", "(\\Deleted)")
        result = self._checkStatus(result)


    def msgStore(self, mailbox, rfc822message):

        "Store RFC822 message in mailbox"

        result = self.imap.append(mailbox, None, None, rfc822message)
        self._checkStatus(result)
        return self.status(mailbox)


    def msgRetrieve(self, message, part="RFC822", encoding=None):

        """Retrieve a full message or a message part for this UID

        You can get a message part if you specify the part id
        by default it returns the whole RFC822 part of it
        Although theoretically it could fetch multiple parts, imaplib
        massacrates the result so it's difficult to parse.
        Specify encoding type to get the data back decoded
        """

        # Convert part number to IMAP-style "BODY[part]"
        if '0' < part[0] <= '9':
            part = "BODY[%s]" % part

        result = self.imap.uid("FETCH", message, "(" + part + ")")
        result = self._checkStatus(result)

        if not result[0]:
            return None

        data = result[0][1]  # imaplib split the returned literal
        # see if we need to decode it.
        if encoding in ('base64', 'quoted-printable', 'uuencode'):
            output = cStringIO.StringIO()
            input = cStringIO.StringIO(data)
            mimetools.decode(input, output, encoding)
            input.close()
            data = output.getvalue()
            output.close()

        return data


    ###########################################################################
    # INTERNAL METHODS
    ###########################################################################
    # Mostly parsers for the various IMAP4 response string sequences
    # and various helper methods

    def _makeTuple(self, mailbox):

        "Make a tuple out of a mailbox name"

        return split(mailbox, self.delimiter)


    def _joinTuple(self, mailboxT):

        "Make an IMAP name out of a tuple"

        return join(mailboxT, self.delimiter)


    def _initMailboxList(self, init=0):

        "Initialize mailboxes list if needed or requested (init=1)"

        if init or not self.mailboxes:
            self.mailboxes = Mailbox()


    def _updateMailboxList(self, result, subscribed):

        "update self.mailboxes with data from an imaplib list() or lsub()"

        for mailbox in result:
            if not mailbox:
                break

            mailbox, flags = self._parseMailboxResponse(mailbox)
            mailboxT = self._makeTuple(mailbox)

            # We will only check status on subscribed mailboxes if needed
            if (self.getStatus and subscribed and
                 not flags.has_key("NOSELECT")):
                # Subscribed mailboxes need not exist according to RFC
                # we are going to execute the status() anyway and set
                # the "NOSELECT" flag if it failed, so the names with
                # getStatus=1 are the same as the one with it on 0.
                try:
                    self.status(mailbox)
                except commandError:
                    flags["NOSELECT"] = 1

            # I kind of assume here that we already did a LIST()
            if subscribed and not self.mailboxes.getLeaf(mailboxT):
                flags["NOSELECT"] = 1

            self.mailboxes.add(mailboxT,
                                name=mailbox,
                                flags=flags,
                                subscribed=subscribed)


    def _checkStatus(self, result):

        """Check the status of an IMAP operation, return data part of result

        Used after each call to a self.imap method"""

        if result[0] == "NO":
            raise commandError("IMAP command failed: " + result[1][0])
        elif result[0] != "OK":  # "BAD"
            raise protocolError("IMAP protocol error: " + result[1][0])

        # See if we have any additional data that was sent by the server
        # see resp_text in rfc.

        extra = self.imap.response("OK")[1]
        for line in extra:
            if line and line[0:7] == "[UNSEEN":
                self.unseen = int(line[9:-1])

        return result[1]


    def _parseMailboxResponse(self, response):

        """Parse a mailbox line returned by the IMAP server

        Used after a LIST/LSUB in list()"""

        # Syntax (see mailbox_list in RFC): (flags)
        # Format example: (\Unmarked \HasChildren) "." "INBOX"
        # Mailbox attributes:
        # \Noinferiors \Noselect \Marked \Unmarked ...

        # NOTE: Should use regular expressions, maybe

        flagstring, pos = self._getPList(response)
        flags = self._parseFlags(flagstring)
        pos = pos + 1  # skip the space

        # See if we need to extract the delimiter
        if not self.delimiter:
            if upper(response[pos:pos + 3]) != 'NIL':  # must be quoted delimiter
                if response[pos + 1] == '\\':  # escaped delimiter
                    self.delimiter_incr = 4
                    self.delimiter = response[pos + 2]
                else:
                    self.delimiter = response[pos + 1]
            else:
                pass  # we won't be able to use hierarchies

        # skip the mandatory space after ")" plus the whole delimiter
        mailbox = response[pos + 1 + self.delimiter_incr:]

        return (self._getString(mailbox)[0], flags)


    def _getString(self, astring):

        """extract the string from atomic, quoted or literal form

        returns a tuple where the first element is the extracted string
        and the second is the position after the end of it (so we can
        continue parsing the input string)
        """

        trimmed = len(astring)
        astring = lstrip(astring)
        trimmed = trimmed - len(astring)

        if astring[0] == '{':  # literal: "{" size "}" CR LF data
            pos = index(astring, "}\r\n")
            size = int(astring[1:pos])
            return (astring[pos + 3, pos + 3 + size], pos + 3 + size + trimmed)

        elif astring[0] == '"':  # quoted.
            # The only quoted_specials allowed are " and \

            # Find the position of the end-of-string quote
            found = RE_UNESCAPED_QUOTE.search(astring)
            if not found:
                # should return exception - data is malformed probably
                return (None, 1 + trimmed)

            pos = found.end() - 1  # the double quote is the last char
            string = astring[1:pos]

            # unescape escape sequences
            string = replace(string, r'\\', '\\')  # \\ -> \
            string = replace(string, r'\"', '"')  # \" -> "
            return (string, pos + 1 + trimmed)

        else:
            found = RE_ATOM.search(astring)
            if not found:
                # Should raise an exception...
                # We add one to avoid getting in an infinite loop
                return (None, 1 + trimmed)

            pos = found.end()

            string = found.group(1)

            if upper(string) == "NIL":
                return (None, pos + trimmed)
            else:
                return (astring[:pos], pos + trimmed)


    def _getPList(self, plist, start=1):

        "make a tuple structure from a parenthesized list (i.e. envelope)"

        tuple = []

        l = len(plist)
        i = start  # first char is a "("

        while i < l:

            if plist[i] == '(':  # nested, process recursively
                (data, offset) = self._getPList(plist, i + 1)
                tuple.append(data)
                i = offset

            elif plist[i] == ')':  # our level is closed, return the data
                return (tuple, i + 1)

            elif plist[i] == ' ':
                i = i + 1

            else:
                (string, offset) = self._getString(plist[i:])
                tuple.append(string)
                i = i + offset

        # We should not get here (it means the list wasn't closed)
        return (tuple, l)


    def _simpleQuery(self, key, arg, negate=0):

        "Return a query element doing the necessary sanity checks on arg"

        "Used by search()"

        if negate:
            key = "NOT " + key

        if arg:
            if not RE_STRING.search(arg):
                raise argumentError("Invalid search string for " + key)

            # Escape quoted_specials (double quotes and escape char)
            arg = RE_QUOTED_SPECIALS.sub(r'\\\1', arg)
            return '%s "%s"' % (key, arg)

        else:
            return key


    def _sort(self, message_set, sortby):

        """
        Sort a message set based on given criteria and return the header set.

        used by search()
        Sort criteria: one or two of: ARRIVAL CC DATE FROM SIZE SUBJECT TO
        REVERSE can prefix any of them.
        See the headers() method elsewhere for the format of the header set.
        """
        # ## STUB (NOT IMPLEMENTED)

        # see if we already have the headers
        if not (self.header_set and
                self.message_set and self.message_set == message_set):
            headers = self.headers(message_set)

        return headers

        # NOTE: Should store the headers in case they are requested later


    def _parseFetch(self, line):

        """Parse a FETCH response, fill out a dictionary with the fields

        Used after a fetch() call"""

        # Parsing the response is difficult because of literals and
        # parenthesized lists. A lexical parser would probably work great here.

        if not line:
            return None

        try:
            pos = index(line, " ")  # First chars are: number SPACE "("
        except ValueError:
            raise resultError("Can't parse FETCH result '" + line[:64] + "'")

        pos = pos + 2  # skip them.

        line = line[pos:-1]

        data = {}

        done = 0
        while len(line) > 0 and not done:
            (field, line) = split(line, None, 1)
            field = upper(field)

            if   field in ("UID", "RFC822.SIZE"):  # number
                (num, pos) = self._getString(line)
                data[field] = int(num)

            elif field in ("INTERNALDATE", "RFC822.HEADER", "RFC822.TEXT"):
                # nstring ::= quoted / literal / "NIL"
                (data[field], pos) = self._getString(line)

            elif field in ("ENVELOPE", "BODY", "BODYSTRUCTURE"):
                (data[field], pos) = self._getPList(line)

            elif field == "FLAGS":
                (temp, pos) = self._getPList(line)
                data[field] = self._parseFlags(temp)

            else:
                print "Don't know how to handle %s tag." % (field)
                done = 1  # for now

            line = line[pos:]

        return data


    def _parseParameters(self, params):
        """Parse body parameter list

        Used in _parseMsgSimple()"""

        parsed = {}
        key = None
        if params:
            for elem in params:
                if not key:
                    key = elem
                else:
                    parsed[key] = elem
                    key = None

        return parsed


    def _parseMsgSimple(self, data, part):
        """
        return message structure dictionary for a simple message given in data:

        { 'part':         '1',    # MIME part identifier
          'type':         'text',
          'subtype:       'plain', # type/subtype is a MIME type
          'param':        ['charset', 'iso-8859-1'],
          'id':           None,
          'description':  None,
          'encoding':     '7bit', # '8bit','binary','base64','quoted-printable'
          'size':         330,
          # if type is 'text' or 'message'
          'lines':        17,
          # if type/subtype is 'message/rfc822':
          'envelope':     envelope_data,
          'body':         { another simple message structure }
        }
        """

        # data looks like this:
        # ['text', 'plain', [param_data], None, None, '7bit', '330', '17']
        # (an rfc822/message will contain envelope and body before no of lines)

        body = {
            'part':           part,
            'type':           data[0],
            'subtype':        data[1],
            'param':          self._parseParameters(data[2]),
            'id':             data[3],
            'description':    data[4],
            'encoding':       data[5],
            'size':           data[6]
        }

        if body['type'] == 'message' and body['subtype'] == 'rfc822':
            # [7] is envelope, [8] is body, [9] is lines
            body['envelope'] = self._fixEnvelope(data[7])
            body['body'] = self._parseMsg(data[8], part)
            body['lines'] = data[9]

        elif len(data) >= 8:
            body['lines'] = data[7]

        return body


    def _parseMsg(self, data, part=""):
        """Parse a multipart or simple message's structure

        called by msgStructure()"""

        # multipart data looks like this (empirically from courier because
        # I can't make it match the body and body_type_mpart specs).
        # [ [body], [body], [...], subtype] ]
        # (subtype='mixed', 'alternative', 'type' is assumed 'multipart')

        # if the first element of the body array is another array then
        # we have a multipart message (the last element is the subtype)
        if type(data[0]) == type("string"):
            # "simple" message
            if part == "":
                part = "1"
            return self._parseMsgSimple(data, part)

        else:
            if part != "":
                part = part + "."

            # multipart message
            count = len(data)
            parts = [data[count-1]]  # the subtype (mixed, alternative etc)

            for i in range(0, count-1):  # should be >=2 anyway
                parts.append(self._parseMsg(data[i], "%s%d" % (part, i+1)))

            return parts


    def _fixEnvelope(self, envelope):
        """Structure the envelope data

        Used whenever a FETCH might've returned an ENVELOPE field"""

        # envelope is a tuple with the following elements, in this order:
        # DATE, SUBJECT, FROM, SENDER, REPLYTO, TO, CC, BCC, INREPLYTO, MSGID
        # This makes it a dictionary and puts the addresses in RFC822 format

        headers = ("DATE", "SUBJECT",
                    "FROM", "SENDER", "REPLYTO", "TO", "CC", "BCC",
                    "INREPLYTO", "MSGID")

        newenvelope = {}

        for i in range(0, len(headers)):
            try:
                list = envelope[i]

            except IndexError:
                list = None

            if list and type(list) == type([]):  # only headers are arrays
                newlist = []
                for addy in list:

                    # Header fields are tuples, each individual element is
                    # itself a tuple: ( NAME, ROUTE, USERNAME, HOST )
                    # Special case where HOST or USERNAME are None (grouping)
                    # is not treated and will probably break something
                    # Similarly, no escaping is attempted on address components

                    email = {'name': addy[0],
                             'email': '%s@%s' % (addy[2], addy[3])}
                    newlist.append(email)
                list = newlist

            newenvelope[headers[i]] = list

        return newenvelope


    def _parseFlags(self, flags):
        "Make a dictionary out of the ['\\flag1','\\flag2'] list"

        parsed = {}

        if flags:
            for flag in flags:
                if flag[0] == '\\':
                    flag = flag[1:]
                flag = upper(flag)
                parsed[flag] = 1

        return parsed
Beispiel #20
0
 def send_in_my_mailbox(self, data):
     forward, recipient, topic, body = parse_data(data)
     if body:
         mailbox = Mailbox(self.recipient.login)
         mailbox.write_letter(forward, recipient, topic, body)
Beispiel #21
0
    def read(self, item: Item, box: mailbox.Mailbox) -> bool:
        try:
            f = open(item.data.filename, mode='rb')
        except OSError as e:
            pmlib.log.exception(e)
            return False

        f.seek(128)  # move to first mail

        n = 0
        count = 1

        stream = f.read(-1)
        item.size = len(stream)
        positions: List[Position] = []

        start = 0
        for byte in stream:
            if byte == 0x1a:  # 1A seperates the mails
                pos = Position(start=start, end=n)
                positions.append(pos)
                count += 1
                start = n + 1
            n += 1

        max_count = len(positions)

        count = "{0:d}".format(max_count).rjust(6, " ")
        size = convert_bytes(item.size)

        pmlib.log.inform(
            item.parent.name,
            "{0:s} mails for {1:s} ({2:s})".format(count, item.name, size))

        progress = pmlib.log.progress(max_count)

        n = 0
        for _pos in positions:
            value = stream[_pos.start:_pos.end]

            msg = email.message_from_bytes(value)
            try:
                box.add(msg)
            except UnicodeEncodeError as e:
                text = self._store_fault(item, n, value)
                item.add_error(n, text, e)
                item.report.failure += 1
            else:
                item.report.success += 1

            box.flush()
            progress.inc()
            n += 1
            item.report.count = n

        pmlib.log.clear()

        for _error in item.report.error:
            pmlib.log.error(_error.text)

        f.close()
        return True
Beispiel #22
0
def cli(ctx, host, user, password, debug):
    ctx.ensure_object(dict)
    ctx.obj["DEBUG"] = debug
    mailbox = Mailbox(debug)
    mailbox.connect(host, user, password)
    ctx.obj["mailbox"] = mailbox
def main():
    user_registry = UserRegistry(Mailbox.create_mailbox('user_registry'), 1)
    user_registry.start()
    user_registry.join()
    request_method = default_proxy and proxy_post or post
    r = request_method(url_prefix + '/user/register?%s' % time.time(), data=data).json()
    if 'successful' in r['strText']:
        global current_acc
        current_acc = acc
        write_file('login.id', acc)
        print('注册成功')
        return True
    print(r['strText'])
    return r['strText']


def active_account(active_resp):
    active_url = re.findall(r'(http.+) ', active_resp['body']['text'])
    if active_url:
        requests.get(active_url[0])
        return False
    return True


if __name__ == '__main__':
    mail = Mailbox(True, active_account)
    if isinstance(register(mail.address), bool):
        mail.forever(active_account)
    pl = map_proxy_list()
    plt = '\r\n'.join(pl)
    write_file('proxy.list', plt)
    print('已将获取到的%s个代理写入 proxy.list 当中.' % len(pl))
    print('开始筛选代理,你可以通过设置超时时间来作为筛选条件')
    TestProxy(pl, timeout=1)
Beispiel #25
0
Datei: run.py Projekt: MGniew/ZSW
from flask import Flask
from flask import Response
from mailbox import Mailbox

app = Flask(__name__)

mailbox = Mailbox()


@app.route("/state")
def get_state():
    response = Response(mailbox.get_state())
    response.headers['Access-Control-Allow-Origin'] = '*'
    return response


@app.route("/state/<state>", methods=['POST'])
def state_changed(state):
    mailbox.set_state(state)
    return mailbox.get_state()


if __name__ == "__main__":
    app.run(debug=True, host='10.0.0.2', processes=5)
Beispiel #26
0
class protocolThread(threading.Thread):
    def __init__(self, host, port, vk, sk):
        threading.Thread.__init__(self)
        self.messages = Messages()
        self.mailbox = Mailbox(host, port, timeout=None)
        self.vk = vk
        self.sk = sk
        self.session = None
        self.number = None
        self.number_of_players = None
        self.players = {}

    def run(self):
        crypto = Crypto()
        crypto.generate_key_pair()
        enc_key = crypto.export_public_key()
        self.mailbox.connect()
        self.messages.make_greeting(self.vk)
        msg = self.messages.packets.SerializeToString()
        self.mailbox.send(msg)
        req = self.mailbox.recv()
        self.messages.packets.ParseFromString(req)
        self.session = self.messages.packets.packet[-1].packet.session
        self.number = self.messages.packets.packet[-1].packet.number
        if self.session != '':
            print("Player #" + str(self.number) + " get session number.\n")
        # Here is when announcment should begin
        req = self.mailbox.recv()
        self.messages.packets.ParseFromString(req)
        phase = self.messages.get_phase()
        number = self.messages.get_number()
        time.sleep(1)
        if phase == 1 and number > 0:
            print("player #" + str(self.number) +
                  " is about to share verification key with " + str(number) +
                  " players.\n")
            self.number_of_players = number
            #Share the keys
            self.messages.clear_packets()
            self.messages.packets.packet.add()
            self.messages.packets.packet[-1].packet.from_key.key = self.vk
            self.messages.packets.packet[-1].packet.session = self.session
            self.messages.packets.packet[-1].packet.number = self.number
            shared_key_message = self.messages.packets.SerializeToString()
            messages = self.mailbox.share(shared_key_message, self.number,
                                          self.number_of_players)
            self.messages.packets.ParseFromString(messages)
            self.players = {
                packet.packet.number: str(packet.packet.from_key.key)
                for packet in self.messages.packets.packet
            }
        print("Player #" + str(self.number) + " got players " +
              str(self.players) + '\n')
        # crypto = Crypto()
        # crypto.generate_key_pair()
        # enc_key = crypto.export_public_key()
        # clear old messages
        self.messages.clear_packets()
        # add encrytion key
        self.messages.add_encryption_key(enc_key, None)
        # self.messages.add_str('x')
        self.messages.packets.packet[-1].packet.from_key.key = self.players[
            self.number]
        self.messages.packets.packet[-1].packet.session = self.session
        self.messages.packets.packet[-1].packet.number = self.number
        # self.messages.packets.packet[-1].signature.signature = '1234'
        # for the packet
        # self.messages.form_last_packet(self.sk, self.session, self.number, self.vk, None)
        # # share the keys
        outcome_message = self.messages.packets.SerializeToString()
        print("Player " + str(self.number) +
              " is about to share encrytion key.\n")
        msgs = self.mailbox.share(outcome_message, self.number,
                                  self.number_of_players)
        # self.mailbox.send(outcome_message)
        # print(self.mailbox.send(outcome_message))
        # # parse the result
        # try:
        #     self.messages.packets.ParseFromString(msgs)
        # except DecodeError:
        #     print('Decoding Error!')
        # # get encryption keys
        # if (self.messages.encryption_keys_count() == self.number_of_players):
        #     self.encryption_keys = self.messages.get_encryption_keys()
        #     print('Player '+ str(self.number) + ' recieved all keys for test\n')
        # else:
        #     raise Exception('Not get encryption keys!')
        #
        time.sleep(10)
        self.mailbox.close()
Beispiel #27
0
 def __init__(self, path, factory=None, create=True, file=None):
     Mailbox.__init__(self, path, factory, create)
     self.file = file