Esempio n. 1
0
def _process_qualified_mails(mail_bodies, pipeline):
    def handle_error(failure):
        logger.error('failed to process qualified mails - {}'.format(failure))

    processed = imap4.MessageSet()
    for body in mail_bodies.values():
        uid = int(body[0][1])
        summary = parse_mail_attachment(body[0][4])
        if summary.title.find('CANON') and summary.payload_start_index > 0:
            processed += imap4.MessageSet(uid)
            path = pathlib.Path(pipeline.local_store, summary.filename)
            with open(path, 'wb') as f:
                f.write(
                    base64.urlsafe_b64decode(
                        body[0][4][summary.payload_start_index:]))
            logger.info('Successfully downloaded {}'.format(path))

    logger.info('Processed {} scanned files'.format(len(processed)))

    if len(processed) == 0:
        return _next_round(None, pipeline)

    return pipeline.protocol.addFlags(processed, ['\\Seen'], uid=True) \
                            .addCallback(_next_round, pipeline) \
                            .addErrback(handle_error)
Esempio n. 2
0
    def testFullAppend(self):
        """
        Test appending a full message to the mailbox
        """
        infile = os.path.join(HERE, '..', 'rfc822.message')
        message = open(infile)
        acc = self.server.theAccount
        mailbox_name = "appendmbox/subthing"

        def add_mailbox():
            return acc.addMailbox(mailbox_name)

        def login():
            return self.client.login(TEST_USER, TEST_PASSWD)

        def append():
            return self.client.append(
                mailbox_name, message,
                ('\\SEEN', '\\DELETED'),
                'Tue, 17 Jun 2003 11:22:16 -0600 (MDT)',
            )

        d1 = self.connected.addCallback(strip(add_mailbox))
        d1.addCallback(strip(login))
        d1.addCallbacks(strip(append), self._ebGeneral)
        d1.addCallbacks(self._cbStopClient, self._ebGeneral)
        d2 = self.loopback()
        d = defer.gatherResults([d1, d2])

        d.addCallback(lambda _: acc.getMailbox(mailbox_name))
        d.addCallback(lambda mb: mb.fetch(imap4.MessageSet(start=1), True))
        return d.addCallback(self._cbTestFullAppend, infile)
Esempio n. 3
0
    def _findChandlerMessages(self, msgUIDs, start, total):
        if __debug__:
            trace("_findChandlerMessages")

        for msgUID in msgUIDs:
            # Add all messages that match the
            # search criteria to the foundUIDs
            # list.
            self.vars.foundUIDs.append(msgUID)

        mset = self._getSearchMessageSet()

        if mset:
            query = imap4.Query(header=('X-Chandler-Mailer', 'True'),
                                undeleted=True,
                                uid=mset)

            end = start + len(mset)

            d = self.proto.search(query, uid=1)

            d.addCallback(self._findChandlerMessages, end, total)
            d.addErrback(self.catchErrors)

            self._printSearchNum(start, end, total)

            return None

        # This point is reached when self._getSearchMessageSet()
        # returns None indicating that there are no more message
        # uids to search for Chandler Headers.

        if len(self.vars.foundUIDs) == 0:
            # If the search returned no message uids
            # then have the worker commit the last seen UID
            # for the folder to prevent searching the same
            # messages again.
            return self._getNextFolder()

        # Search found one or more messages containing the
        # Chandler Headers.
        msgSet = imap4.MessageSet()

        for uid in self.vars.foundUIDs:
            msgSet.add(uid)

        # FYI: Since there are messages to download the incrementing of
        # the lastUID to highest uid of the searched messages
        # will automatically get commited.
        d = self.proto.fetchFlags(msgSet, uid=True)

        # The True argument indicates the message UIDs were
        # retrieved from an IMAP Search. This flag
        # tells the _getMessageFlagsUID method to
        # perform logic specific to the results of a
        # search
        d.addCallback(self._getMessagesFlagsUID, True)
        d.addErrback(self.catchErrors)

        return None
Esempio n. 4
0
    def testPartialAppend(self):
        """
        Test partially appending a message to the mailbox
        """
        # TODO this test sometimes will fail because of the notify_just_mdoc
        infile = util.sibpath(__file__, 'rfc822.message')

        acc = self.server.theAccount

        def add_mailbox():
            return acc.addMailbox('PARTIAL/SUBTHING')

        def login():
            return self.client.login(TEST_USER, TEST_PASSWD)

        def append():
            message = file(infile)
            return self.client.sendCommand(
                imap4.Command(
                    'APPEND', 'PARTIAL/SUBTHING (\\SEEN) "Right now" '
                    '{%d}' % os.path.getsize(infile), (),
                    self.client._IMAP4Client__cbContinueAppend, message))

        d1 = self.connected.addCallback(strip(add_mailbox))
        d1.addCallback(strip(login))
        d1.addCallbacks(strip(append), self._ebGeneral)
        d1.addCallbacks(self._cbStopClient, self._ebGeneral)
        d2 = self.loopback()
        d = defer.gatherResults([d1, d2])

        d.addCallback(lambda _: acc.getMailbox("PARTIAL/SUBTHING"))
        d.addCallback(lambda mb: mb.fetch(imap4.MessageSet(start=1), True))
        return d.addCallback(self._cbTestPartialAppend, infile)
Esempio n. 5
0
def _fetch_qualified_mails(uids, pipeline):
    def handle_error(failure):
        logger.error('IMAP4 fetch failed because of {}'.format(failure))

    if len(uids) == 0:
        logger.info('Found no qualified mails.')
        return _next_round(None, pipeline)

    logger.info('Found {} preliminary qualified mails.'.format(len(uids)))

    messages = reduce(lambda x, y: x + imap4.MessageSet(y), uids,
                      imap4.MessageSet())

    # Set peek = True to avoid accidentally flag an irrelevant message.
    return pipeline.protocol.fetchSpecific(messages, uid=True, headerType='TEXT', peek=True) \
                            .addCallback(_process_qualified_mails, pipeline) \
                            .addErrback(handle_error)
Esempio n. 6
0
 def cbGotSearch(self, results):
     if results:
         ms = imap4.MessageSet()
         for n in results:
             ms.add(n)
         self.fetchUID(ms).addCallback(self.cbGotUIDs)
     else:
         self.cbClosed(None)
Esempio n. 7
0
 def _addDeleteCallback(self, d, folderPath):
     msgSet = imap4.MessageSet(1, None)
     d.addCallback(lambda x: self.proto.select(folderPath))
     d.addCallback(
         lambda x: self.proto.addFlags(msgSet, ("\\Deleted", ), uid=True))
     d.addCallback(lambda x: self.proto.expunge())
     d.addCallback(lambda x: self.proto.close())
     d.addCallback(lambda x: self.proto.delete(folderPath))
Esempio n. 8
0
    def __checkForNewMessages(self, msgs):
        if __debug__:
            self.printCurrentView("checkForNewMessages")

            #XXX: Need to store and compare UIDVALIDITY
        #if not msgs['UIDVALIDITY']:
        #    print "server: %s has no UUID Validity:\n%s" % (self.account.host, msgs)

        if msgs['EXISTS'] == 0:
            utils.NotifyUIAsync(constants.DOWNLOAD_NO_MESSAGES)
            return self._actionCompleted()

        if self.__getNextUID() == 0:
            msgSet = imap4.MessageSet(1, None)
        else:
            msgSet = imap4.MessageSet(self.__getNextUID(), None)

        d = self.proto.fetchFlags(msgSet, uid=True)

        d.addCallback(self.__getMessagesFlagsUID).addErrback(self.catchErrors)

        return d
Esempio n. 9
0
    def _checkForNewMessages(self, msgs):
        if __debug__:
            trace("_checkForNewMessages")

        #XXX: Need to store and compare UIDVALIDITY.
        #     The issue is what does Chandler do if the
        #     UIDVALIDITY has changed. Not being a
        #     traditional mail client we could not
        #     just refetch the messages since the
        #     Message Items may have changed dramatically
        #     i.e. unstamped as Mail and stamped as an Event
        #     and shared with other users. Or altered as
        #     part of an Edit / Update workflow.
        #     For now UIDVALIDITY will be ignored :(
        #if not msgs['UIDVALIDITY']:
        #    print "server: %s has no UUID Validity:\n%s" % (self.account.host, msgs)

        if self.cancel:
            return self._actionCompleted()

        if msgs['EXISTS'] == 0:
            return self._getNextFolder()

        # Check that we have not already downloaded the max
        # number of messages for the folder
        max = self.vars.folderItem.downloadMax
        downloaded = self.vars.folderItem.downloaded

        if max > 0 and max == downloaded:
            if __debug__:
                trace("Max number of messages %s reached. No new mail will be \
                       downloaded from '%s'" %
                      (max, self.vars.folderItem.displayName))

            return self._getNextFolder()

        self.vars.lastUID = self.vars.folderItem.lastMessageUID

        if not self.vars.lastUID > 0:
            self.vars.lastUID = 1

        msgSet = imap4.MessageSet(self.vars.lastUID, None)

        if self.vars.folderItem.folderType == "CHANDLER_HEADERS":
            return self.proto.fetchUID(msgSet, uid=1).addCallbacks(
                self._searchForChandlerMessages, self.catchErrors)
        else:
            return self.proto.fetchFlags(msgSet, uid=True).addCallback(
                self._getMessagesFlagsUID).addErrback(self.catchErrors)
Esempio n. 10
0
def main(reactor,
         username=b"alice",
         password=b"secret",
         strport="tls:example.com:993"):
    endpoint = endpoints.clientFromString(reactor, strport)
    factory = protocol.Factory.forProtocol(imap4.IMAP4Client)
    try:
        client = yield endpoint.connect(factory)
        yield client.login(username, password)
        yield client.select('INBOX')
        info = yield client.fetchEnvelope(imap4.MessageSet(1))
        print('First message subject:', info[1]['ENVELOPE'][1])
    except Exception:
        print("IMAP4 client interaction failed")
        failure.Failure().printTraceback()
Esempio n. 11
0
 def fetchNextMessage(self):
     # self.log.debug("IMAP in fetchnextmessage")
     if self.messageUIDs:
         nextUID = self.messageUIDs.pop(0)
         messageListToFetch = imap4.MessageSet(nextUID)
         self.log.debug("Downloading message %d of %d (%s)" %
                        (self.messageCount - len(self.messageUIDs),
                         self.messageCount, nextUID))
         self.fetchMessage(messageListToFetch, True).addCallback(
             self.cbGotMessage,
             messageListToFetch).addErrback(self.ebLogError)
     else:
         self.log.debug("Seeing if anything new has arrived")
         # Go back and see if any more messages have come in
         self.expunge().addCallback(self.cbInboxSelected)
Esempio n. 12
0
 def fetchNextMessage(self):
     # self.log.debug("IMAP in fetchnextmessage")
     if self.messageUIDs:
         nextUID = self.messageUIDs.pop(0)
         messageListToFetch = imap4.MessageSet(nextUID)
         self.log.debug("Downloading message {count} of {total} ({next})",
                        count=self.messageCount - len(self.messageUIDs),
                        total=self.messageCount,
                        next=nextUID)
         self.fetchMessage(str(messageListToFetch), True).addCallback(
             self.cbGotMessage,
             messageListToFetch).addErrback(self.ebLogError)
     else:
         # We're done for this polling interval
         self.expunge()
Esempio n. 13
0
def main(reactor,
         username="******",
         password="******",
         strport="ssl:host=173.37.183.72:port=993"):
    endpoint = endpoints.clientFromString(reactor, strport)
    factory = protocol.Factory()
    factory.protocol = imap4.IMAP4Client
    try:
        client = yield endpoint.connect(factory)
        yield client.login(username, password)
        yield client.select('INBOX')
        info = yield client.fetchEnvelope(imap4.MessageSet(1))
        print 'First message subject:', info[1]['ENVELOPE'][1]
    except:
        print "IMAP4 client interaction failed"
        failure.Failure().printTraceback()
Esempio n. 14
0
def cbRecent(result, proto):
    """
    Callback invoked when search command completes.

    Retrieve the subject header of every message in the result.
    """
    if result:
        s = imap4.MessageSet(zip(result, result))
        return proto.fetchSpecific(
            s,
            headerType='HEADER.FIELDS',
            headerArgs=['FROM', 'SUBJECT', 'DATE'],
        ).addCallback(cbFetch, proto)
    else:
        proto.display("No recent messages; Goodbye\n")
        return proto.logout()
 def expunge(self, messageSet=imap4.MessageSet()):
     files = set()
     self.maildir.lock()
     if not messageSet.last:
         for k in self.maildir.keys():
             messageSet.add(k)
             files.add(self.maildir.get_file(k)._file)
         self.maildir.clear()
     try:
         return [
             messageNum for messageNum in messageSet
             if not self.maildir.discard(messageNum)
         ]
     finally:
         self.maildir.unlock()
         for f in files:
             os.unlink(f.name)
Esempio n. 16
0
    def _getSearchMessageSet(self):
        size = len(self.vars.searchUIDs)

        if size == 0:
            return None

        num = size > constants.MAX_IMAP_SEARCH_NUM and \
              constants.MAX_IMAP_SEARCH_NUM or \
              size

        mset = imap4.MessageSet()

        for i in xrange(0, num):
            mset.add(self.vars.searchUIDs[i])

        # Reduce the list removing all uids that have been
        # added to the message set
        self.vars.searchUIDs = self.vars.searchUIDs[num:]

        return mset
Esempio n. 17
0
	def _filterNewUnseen(self, newUnseenList):
		'''
		Main method in this class: get the list of unseen messages
		and check them against the last list. New unseen messages
		are then displayed via _onHeaderList
		@param newUnseenList: new list of unseen messages
		'''
		debug('[CheckMail] %s: _filterNewUnseen: %s' % (self._name, repr(newUnseenList)))
		if self._unseenList is None:
			debug('[CheckMail] %s: _filterNewUnseen: init' % (self._name))
			# Notifications.AddNotification(MessageBox, str(len(newUnseenList)) + ' ' + _("unread messages in mailbox %s") %self._name, type=MessageBox.TYPE_INFO, timeout=config.plugins.emailimap.timeout.value)
		else:
			newMessages = filter(lambda x: x not in self._unseenList, newUnseenList)
			if newMessages:
				debug("[CheckMail] %s: _filterNewUnseen: new message(s): %s" % (self._name, repr(newMessages)))
				# construct MessageSet from list of message numbers
				# newMessageSet = reduce(lambda x,y: y.add(x), newMessages, imap4.MessageSet())
				newMessageSet = imap4.MessageSet()
				for i in newMessages:
					newMessageSet.add(i)
				if not self._account.getHeaders(self._onHeaderList, newMessageSet):
					debug("[CheckMail] %s: _filterNewUnseen: could not get Headers" % (self._name))

		self._unseenList = newUnseenList