classification
Title: Add a method to move messages to IMAPlib
Type: enhancement Stage: patch review
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: mcepl
Priority: normal Keywords: patch

Created on 2018-04-21 19:10 by mcepl, last changed 2020-03-19 18:44 by vstinner.

Pull Requests
URL Status Linked Edit
PR 19072 open mcepl, 2020-03-19 14:45
Messages (2)
msg315578 - (view) Author: Matej Cepl (mcepl) * Date: 2018-04-21 19:10
I am in the process of writing script working with IMAP first time using Python 3 for it (unfortunately, most of servers where I run other code is so ancient that even Python 2.7 is a stretch), and it is really nice experience so far. Many problems which are dealt with on the StackExchange with arcane workarounds are now resolved in email or imaplib libraries. Thank you, everybody!

However, it seems to me that few higher level commands could greatly improve useability of imaplib library. For example, moving messages (not fault of imaplib) is still horrible mess. In the end I had to write this monstrosity just to make moving messages working:


    Capas = collections.namedtuple('Capas', ['MOVE', 'UIDPLUS'])

    def __login(self, host='localhost', username=None, password=None, ssl=None):
        self.box = imaplib.IMAP4_SSL(host=host)
        ok, data = self.box.login(username, password)
        if ok != 'OK':
            raise IOError('Cannot login with credentials %s' %
                          str((host, username, password,)))

        ok, data = box.capability()
        capas = data[0].decode()
        box.features_present = Capas._make(['MOVE' in capas, 'UIDPLUS' in capas])

    def move_messages(self, target, messages):
        if self.box.features_present.MOVE:
            ok, data = self.box.uid('MOVE', '%s %s' % (messages, target))
            if ok != 'OK':
                raise IOError('Cannot move messages to folder %s' % target)
        elif self.box.features_present.UIDPLUS:
            ok, data = self.box.uid('COPY', '%s %s' % (messages, target))
            if ok != 'OK':
                raise IOError('Cannot copy messages to folder %s' % target)
            ok, data = self.box.uid('STORE',
                                    r'+FLAGS.SILENT (\DELETED) %s' % messages)
            if ok != 'OK':
                raise IOError('Cannot delete messages.')
            ok, data = self.box.uid('EXPUNGE', messages)
            if ok != 'OK':
                raise IOError('Cannot expunge messages.')
        else:
            ok, data = self.box.uid('COPY', '%s %s' % (messages, target))
            if ok != 'OK':
                raise IOError('Cannot copy messages to folder %s' % target)
            ok, data = self.box.uid('STORE',
                                    r'+FLAGS.SILENT (\DELETED) %s' % messages)
            if ok != 'OK':
                raise IOError('Cannot delete messages.')

It would be nice if some capabilities detection (see issue 18921) was embedded into login method, and if some version of move_messages was included in imaplib itself.
msg321952 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2018-07-19 11:56
See also bpo-33336: [imaplib] MOVE is a legal command.
History
Date User Action Args
2020-03-19 18:44:09vstinnersetnosy: - vstinner
2020-03-19 14:45:47mceplsetkeywords: + patch
stage: test needed -> patch review
pull_requests: + pull_request18427
2018-07-19 11:56:39vstinnersetnosy: + vstinner
messages: + msg321952
2018-04-27 18:20:02terry.reedysetstage: test needed
versions: - Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7
2018-04-21 19:10:03mceplcreate