An .mbox is one plain text file with every message in it, one after another.
Google Takeout exports Gmail this way, Thunderbird stores each folder this way,
and most mail programs can export to it. To find one message in it, you don't
need to import thousands of others into a mail program first.
A 14-message Takeout export open in the browser, nothing imported.
Read it in place
mutt opens an mbox where it is. -R opens it read-only, so nothing in the file
changes:
mutt -R -f "All mail Including Spam and Trash.mbox"
Type / and a word to jump to the next message whose sender or subject matches,
Enter to read it, q to quit. The
first time, mutt may ask to create a ~/Mail folder; either answer is fine.
For a scripted search, Python's standard library reads mbox files with no
install. Save this as find.py:
import sys, mailbox, email, email.policy
box = mailbox.mbox(sys.argv[1], factory=lambda f: email.message_from_binary_file(f, policy=email.policy.default))
word = sys.argv[2].lower()
for key, msg in box.iteritems():
if word in f"{msg['from']} {msg['subject']}".lower():
print(key, msg['date'], msg['from'], msg['subject'], sep=' | ')
python3 find.py "All mail Including Spam and Trash.mbox" lease
1 | Thu, 04 Sep 2025 09:15:00 +0000 | Priya Raman <[email protected]> | Re: Lease renewal for the flat
8 | Thu, 18 Sep 2025 16:15:00 +0000 | Priya Raman <[email protected]> | Lease renewal for the flat
The first number is the message's place in the mailbox. Write that one out as
an .eml:
python3 -c 'import mailbox, sys; sys.stdout.buffer.write(mailbox.mbox(sys.argv[1]).get_bytes(int(sys.argv[2])))' "All mail Including Spam and Trash.mbox" 8 > lease.eml
get_bytes leaves out the mbox From line, so lease.eml is the message as
it was sent, and any mail program opens it. Encoded subjects come out readable:
the script prints Café Lumière where the file says =?UTF-8?Q?Caf=C3=A9....
Where the mailbox is in a Takeout download
Takeout sends an archive (.zip or .tgz), not the mailbox itself. Gmail's
part is in a Mail folder inside it, usually as one file called
All mail Including Spam and Trash.mbox. Google's own steps for requesting
the export are in Download your Google data.
Unpack the archive before you open anything. The MBOX Viewer reads the bytes, not the file name, and says so if you give it the ZIP.
Gmail labels are a header
An mbox has no folders, so Takeout writes each message's labels into a header:
X-GM-THRID: 1810000000000063352
X-Gmail-Labels: Inbox,Home
Labels are separated by commas, and a message can have several. To see which labels a mailbox uses and how often:
import sys, mailbox
from collections import Counter
count = Counter()
for msg in mailbox.mbox(sys.argv[1]):
for label in (msg['X-Gmail-Labels'] or '').split(','):
if label.strip():
count[label.strip()] += 1
for label, n in count.most_common():
print(f'{n:6} {label}')
10 Inbox
2 Receipts
2 Important
2 Home
2 Sent
2 Starred
2 Category Updates
1 Category Promotions
1 Archived
1 Spam
The MBOX Viewer reads the same header and shows the twelve most used labels as chips above the list. Pick one to see only those messages.
One label chip narrows the list to the messages Gmail filed under it.
Why counting "From " lines gets it wrong
Each message starts with a line beginning From (no colon). The quick count
is grep:
grep -c '^From ' old-client.mbox
5
That mailbox holds 4 messages. One body has a sentence that starts with "From ",
written by a mail program that never escaped it as >From . Python's mailbox
splits there too, and reports 5:
python3 -c 'import mailbox, sys; print(len(mailbox.mbox(sys.argv[1])))' old-client.mbox
5
The MBOX Viewer only counts a From line that has a sender and a date and
follows an empty line, so it finds 4, and so does formail from procmail. On a
clean export the counts agree: all of them found 14 in the Takeout file above.
If a message from an old client looks truncated in Python, this is why. Open the same mailbox in the MBOX Viewer to see the whole message.
Apple Mail and Thunderbird import it
Both can open an mbox, but by copying it into their own store. In Apple Mail it is File › Import Mailboxes; in Thunderbird, the ImportExportTools NG add-on. For a multi-gigabyte export that is a long wait and a second copy on disk, and the messages then sit in your mail program. Do that when you want the archive kept there. To find one message, read the file in place instead. We did not run these two imports for this guide; check the app's own help for your version.
How big a mailbox the browser handles
The MBOX Viewer opens files up to 16 GB. It reads the mailbox as a stream and keeps only a short summary per message (sender, subject, date, labels, where it sits in the file); a message is read from disk when you open it. Memory grows with the number of messages, not the size of the file. Run over a 281 MB test mailbox of 560,000 small messages, the same indexing code took 7 seconds and about 630 MB of memory, roughly 1 KB per message. A Takeout export of a few gigabytes with large attachments has far fewer messages than that.
A file of several gigabytes takes a while to read. The list fills as it goes, and you can search and open messages before it finishes.
Save the message
- Unpack the Takeout archive and drop the
.mboxon the MBOX Viewer. - Type a sender or a word from the subject into Search sender or subject, or pick a label chip.
- Click the message. Its attachments are listed above the text.
- Press Download as .eml. The arrow next to it has the other choices: the
message as it sits in the mailbox, Outlook
.msg, Apple Mail.emlx, or all its attachments as a ZIP.
Search, open the message, and download it as an .eml.
To keep a set of messages as separate files, narrow the list with search or a
label first, then use the converter. It saves every message shown, one .eml
per message, in one ZIP.
An .eml opens in Apple Mail, Thunderbird and Outlook. On a machine with none
of them, open it in the Email Viewer.