Skip to content

Add a method to move messages to IMAPlib #77508

Description

@mcepl
mannequin
BPO 33327
Nosy @mcepl
PRs
  • WIP: bpo-33327: Add IMAP4.move_messages() method. #19072
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2018-04-21.19:10:03.702>
    labels = ['3.8', 'type-feature', 'library']
    title = 'Add a method to move messages to IMAPlib'
    updated_at = <Date 2021-09-19.23:36:53.735>
    user = 'https://github.com/mcepl'

    bugs.python.org fields:

    activity = <Date 2021-09-19.23:36:53.735>
    actor = 'mcepl'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2018-04-21.19:10:03.702>
    creator = 'mcepl'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 33327
    keywords = ['patch']
    message_count = 6.0
    messages = ['315578', '321952', '372955', '372966', '372967', '402188']
    nosy_count = 2.0
    nosy_names = ['mcepl', 'frispete']
    pr_nums = ['19072']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue33327'
    versions = ['Python 3.8']

    Linked PRs

    Activity

    1. mcepl commented on Apr 21, 2018

      mceplmannequin
      MannequinAuthor

      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 bpo-18921) was embedded into login method, and if some version of move_messages was included in imaplib itself.

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Apr 21, 2018
    3. vstinner commented on Jul 19, 2018

      @vstinner
      Member

      See also bpo-33336: [imaplib] MOVE is a legal command.

    4. frispete commented on Jul 3, 2020

      frispetemannequin
      Mannequin

      If I'm not mistaken, this is applied to the openSUSE TW version of Python.
      For some reason, this seems to not play well with <instance>.uid('move',...)
      on a cyrus imap server (v2.4.19). Is that to be expected?

      2020-07-03 18:04:05  INFO: [imap_reorg] move b'10399' from 2017-01-01 06:30:35+02:00 to INBOX.2017
      Traceback (most recent call last):
        File "./imap_reorg.py", line 431, in <module>
          sys.exit(main())
        File "./imap_reorg.py", line 425, in main
          return process()
        File "./imap_reorg.py", line 133, in trace_and_call
          result = func(*args, **kwargs)
        File "./imap_reorg.py", line 358, in process
          ret |= reorg.run_expr(expr)
        File "./imap_reorg.py", line 345, in run_expr
          return method(*args)
        File "./imap_reorg.py", line 328, in yearly
          ret = self.imap.uid('move', uid, dest)
        File "/usr/lib64/python3.8/imaplib.py", line 881, in uid
          typ, dat = self._simple_command(name, command, *args)
        File "/usr/lib64/python3.8/imaplib.py", line 1205, in _simple_command
          return self._command_complete(name, self._command(name, *args))
        File "/usr/lib64/python3.8/imaplib.py", line 1030, in _command_complete
          raise self.error('%s command error: %s %s' % (name, typ, data))
      imaplib.error: UID command error: BAD [b'Unrecognized UID subcommand']
      
    5. mcepl commented on Jul 3, 2020

      mceplmannequin
      MannequinAuthor
      1. no this has not been included anywhere, just in the unfinished PR on GitHub
      2. only thing which I was fighting to get into Python (and I did) was https://bugs.python.org/issue33336 but that’s another issue (without this whole discussion here would not be even possible), it is now part of the upstream Python
      3. are you certain that the IMAP server in question supports MOVE command? (have you noticed all that business with CAPABILITIES and particularly the UID one?)
    6. mcepl commented on Jul 3, 2020

      mceplmannequin
      MannequinAuthor

      Sorry, UIDPLUS capability.

    7. mcepl commented on Sep 19, 2021

      mceplmannequin
      MannequinAuthor

      Hans-Peter Jansen (frispete)

      imaplib.error: UID command error: BAD [b'Unrecognized UID subcommand']

      You missed the fix for https://bugs.python.org/issue33336

    8. transferred this issue fromon Apr 10, 2022
    9. added a commit that references this issue on Jul 5, 2026
    10. serhiy-storchaka commented on Jul 5, 2026

      @serhiy-storchaka
      Member

      Added imaplib.IMAP4.move() in GH-153121, a wrapper for the MOVE command (RFC 6851). uid('MOVE', ...) works as well.

    11. added
      3.16new features, bugs and security fixes
      and removed on Jul 5, 2026
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.16new features, bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytopic-emailtype-featureA feature request or enhancement

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions