Two weeks ago, I needed to mass-download a few IMAP mailboxes before migrating them to another provider.
Gist contains many scripts to do so, and I tried one of them, but it did not work as I wanted. I wanted to download all the IMAP folders, not only Inbox.
Therefore, I wrote my version of that script 😄️.
I used imapclient
instead of the built-in imaplib
because it is more Pythonic and handles all the tedious conversions between bytes, strings, and other types.
The center of the script is the process
function. It connects to an IMAP server, queries the list of folders, and downloads all the messages from each one but trash and spam (but notice that the comparison is case-sensitive!).
client.fetch
downloads all the messages you provide to it, which caused an OOM in my case. Therefore, I split the list with the message IDs into chunks. I had to write the batches
function because I was running on Python 3.11. From Python 3.12, you can use itertools.batched
instead.
Messages in the RFC822 format are ready to be written as a .eml
file. The advantage is that this format is standard and can be opened by any email client. But it is also quite verbose and takes up a lot of space. Think, for example, to base64′ed attachments. Therefore, I decided to compress them with Gzip first as a tradeoff.
As for the filename, since this script was intended to be a one-time-only run, I did not bother to create a unique filename to run the script multiple times. So, I used the message ID from the IMAP session, but the script avoids overwriting existing files.
At the end of the file, I added an example of how to call process
. The most important detail is to use a Path
for the destination, not a string.
You are supposed to change the script to fit your needs. For my use case, I defined an array with all the credentials and then called the function for each item.
You can download the script here. I dedicated it to the public domain, but, of course, it comes without any warranty.