mail.imap.store
import mail
Everything here is re-exported by
import mailis enough and the names are called asmail.*. Importingmail.imap.storeon its own works too and reaches the same definitions.
Where an ImapServer keeps mail.
MailStore is the contract: what a store has to be able to do for the
server to answer with it. Two are provided. MaildirStore keeps mail on
disk in the Maildir layout, which every other mail tool can read, so a
mailbox written here is not trapped here. MemoryStore keeps it in the
process and forgets it on exit, which is what a test and an embedded
server want.
import mail.imap { ImapServer, MaildirStore }
var store = MaildirStore('/var/mail/ann')
store.add_account('ann', 'secret')
ImapServer({ port: 143 }, store).listen()
A store of your own only has to answer the same calls. Nothing here is required to come from a file.
Constants
MAILDIR_PARTS
mail.MAILDIR_PARTS = [...]
INFO_SEPARATOR
mail.INFO_SEPARATOR
MAILDIR_FLAGS
mail.MAILDIR_FLAGS = {...}
DELIMITER
mail.DELIMITER = '.'
INDEX_FILE
mail.INDEX_FILE = 'zuri-uidlist'
Classes
StoredMessage
class mail.StoredMessage
One message in a store.
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
mail.StoredMessage(uid: number, raw, flags: list, received)
Parameters
uid(number) — Unique within its mailbox, and never reused.raw(bytes) — The message exactly as it arrived.flags(list)received(Date) — When the store took it.
StoredMessage.size()
mail.StoredMessage.size() -> number
How large the message is.
Returns number
StoredMessage.has_flag()
mail.StoredMessage.has_flag(flag: string) -> bool
Whether a flag is set.
Parameters
flag(string)
Returns bool
StoredMessage.to_string()
mail.StoredMessage.to_string()
MailStore
class mail.MailStore
What a store has to be able to do.
Every method raises here; a store is something that answers them. Both of the ones that ship do, and so can one of your own.
- printable — has a
@to_string(), soechoandprint()show something useful
MailStore.authenticate()
mail.MailStore.authenticate(username: string, password: string) -> bool
Whether these credentials name an account.
Parameters
username(string)password(string)
Returns bool
MailStore.password_of()
mail.MailStore.password_of(username: string) -> string|nil
The password of an account, for the mechanisms that prove it without
sending it, or nil when there is no such account or the store cannot
produce one.
A store that keeps only hashed passwords returns nil, and the server
then does not offer those mechanisms.
Parameters
username(string)
Returns string|nil
MailStore.has_passwords()
mail.MailStore.has_passwords() -> bool
Whether this store can produce a password rather than only check one.
A server offers the mechanisms that prove a password without sending it only when it can work out the same proof, which means knowing the password. A store that keeps only hashes, or that checks credentials somewhere else entirely, says no here and the server stops offering them.
Returns bool
MailStore.mailboxes()
mail.MailStore.mailboxes(username: string) -> list
The mailboxes an account has.
Parameters
username(string)
Returns list — of string
MailStore.exists()
mail.MailStore.exists(username: string, mailbox: string) -> bool
Whether a mailbox exists.
Parameters
username(string)mailbox(string)
Returns bool
MailStore.create()
mail.MailStore.create(username: string, mailbox: string)
Creates a mailbox.
Parameters
username(string)mailbox(string)
Raises MailboxError if it exists already.
MailStore.remove()
mail.MailStore.remove(username: string, mailbox: string)
Removes a mailbox and everything in it.
Parameters
username(string)mailbox(string)
Raises MailboxError if there is no such mailbox.
MailStore.rename()
mail.MailStore.rename(username: string, from: string, to: string)
Renames a mailbox.
Parameters
username(string)from(string)to(string)
Raises MailboxError if there is no such mailbox, or the new name
is taken.
MailStore.messages()
mail.MailStore.messages(username: string, mailbox: string) -> list
Every message in a mailbox, oldest first.
Parameters
username(string)mailbox(string)
Returns list — of StoredMessage
Raises MailboxError if there is no such mailbox.
MailStore.append()
mail.MailStore.append(username: string, mailbox: string, raw, flags: ?list, received) -> StoredMessage
Adds a message to a mailbox.
Parameters
username(string)mailbox(string)raw(bytes)flags(?list)received(?Date)
Returns StoredMessage
Raises MailboxError if there is no such mailbox.
MailStore.set_flags()
mail.MailStore.set_flags(username: string, mailbox: string, uid: number, flags: list)
Replaces the flags on one message.
Parameters
username(string)mailbox(string)uid(number)flags(list)
Raises MailboxError if there is no such message.
MailStore.expunge()
mail.MailStore.expunge(username: string, mailbox: string) -> list
Removes every message in a mailbox marked \Deleted.
Parameters
username(string)mailbox(string)
Returns list — of number: the identifiers that went.
MailStore.counters()
mail.MailStore.counters(username: string, mailbox: string) -> dict
What the next message added to a mailbox will be numbered, and how to tell that the numbering has been reset.
Parameters
username(string)mailbox(string)
Returns dict — of uidnext and uidvalidity.
MailStore.to_string()
mail.MailStore.to_string()
MemoryStore
class mail.MemoryStore < MailStore
A store that keeps everything in the process and nothing on disk.
Fast, and gone when the program is. This is what a test wants, and what a server embedded in something else wants when the mail it holds is not the point.
import mail.imap { MemoryStore }
var store = MemoryStore()
store.add_account('ann', 'secret')
store.append('ann', 'INBOX', 'From: a@b.com\r\n\r\nhello', nil, nil)
echo store.mailboxes('ann')
echo store.messages('ann', 'INBOX').length()
[INBOX]
1
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
mail.MemoryStore(mailboxes: ?list)
Parameters
mailboxes(?list) — The mailboxes every new account starts with.['INBOX']when not given.
MemoryStore.add_account()
mail.MemoryStore.add_account(username: string, password: string) -> MemoryStore
Adds an account, with the mailboxes a new account starts with.
Parameters
username(string)password(string)
Returns MemoryStore — itself.
MemoryStore.authenticate()
mail.MemoryStore.authenticate(username: string, password: string)
MemoryStore.password_of()
mail.MemoryStore.password_of(username: string)
MemoryStore.has_passwords()
mail.MemoryStore.has_passwords()
MemoryStore.mailboxes()
mail.MemoryStore.mailboxes(username: string)
MemoryStore.exists()
mail.MemoryStore.exists(username: string, mailbox: string)
MemoryStore.create()
mail.MemoryStore.create(username: string, mailbox: string)
MemoryStore.remove()
mail.MemoryStore.remove(username: string, mailbox: string)
MemoryStore.rename()
mail.MemoryStore.rename(username: string, from: string, to: string)
MemoryStore.messages()
mail.MemoryStore.messages(username: string, mailbox: string)
MemoryStore.append()
mail.MemoryStore.append(username: string, mailbox: string, raw, flags: ?list, received)
MemoryStore.set_flags()
mail.MemoryStore.set_flags(username: string, mailbox: string, uid: number, flags: list)
MemoryStore.expunge()
mail.MemoryStore.expunge(username: string, mailbox: string)
MemoryStore.counters()
mail.MemoryStore.counters(username: string, mailbox: string)
MemoryStore.to_string()
mail.MemoryStore.to_string()
MaildirStore
class mail.MaildirStore < MailStore
A store that keeps mail on disk in the Maildir layout.
Each account is a directory under root, holding its INBOX directly and
every other mailbox as .Name beside it, which is the Maildir++
arrangement every other mail tool understands. A mailbox written here
can be read by anything else, and mail delivered by anything else turns
up here.
Flags are kept the Maildir way, as letters at the end of a message’s
filename after :2,. A colon cannot appear in a Windows filename, so on
Windows the flags follow ;2, instead, which is what mbsync writes
there too. A Maildir moved between Windows and any other system keeps
its messages but has to have their flags renamed to match.
Mail is on disk; accounts are not. The store asks the program who its
users are, either as a password given to add_account() or through
set_authenticator(), because where an application keeps its passwords
is the application’s business and not a mail library’s.
import mail.imap { MaildirStore }
var store = MaildirStore('/var/mail')
store.add_account('ann', secret)
store.append('ann', 'INBOX', raw, nil, nil)
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
mail.MaildirStore(root: string)
Parameters
root(string) — The directory the accounts live under. It is created if it is not there.
MaildirStore.add_account()
mail.MaildirStore.add_account(username: string, password: string) -> MaildirStore
Adds an account with a password this store will check itself, and makes its mail directory if it is not there.
Parameters
username(string)password(string)
Returns MaildirStore — itself.
MaildirStore.set_authenticator()
mail.MaildirStore.set_authenticator(checker) -> MaildirStore
Hands credential checking to a function of your own, which is what a program with its own user table wants.
A store with an authenticator can no longer produce a password, so the server stops offering the mechanisms that need one.
Parameters
checker(function(2)) — Given a username and a password, returns whether they are right.
Returns MaildirStore — itself.
MaildirStore.authenticate()
mail.MaildirStore.authenticate(username: string, password: string)
MaildirStore.password_of()
mail.MaildirStore.password_of(username: string)
MaildirStore.has_passwords()
mail.MaildirStore.has_passwords()
MaildirStore.mailboxes()
mail.MaildirStore.mailboxes(username: string)
MaildirStore.exists()
mail.MaildirStore.exists(username: string, mailbox: string)
MaildirStore.create()
mail.MaildirStore.create(username: string, mailbox: string)
MaildirStore.remove()
mail.MaildirStore.remove(username: string, mailbox: string)
MaildirStore.rename()
mail.MaildirStore.rename(username: string, from: string, to: string)
MaildirStore.messages()
mail.MaildirStore.messages(username: string, mailbox: string)
MaildirStore.append()
mail.MaildirStore.append(username: string, mailbox: string, raw, flags: ?list, received)
MaildirStore.set_flags()
mail.MaildirStore.set_flags(username: string, mailbox: string, uid: number, flags: list)
MaildirStore.expunge()
mail.MaildirStore.expunge(username: string, mailbox: string)
MaildirStore.counters()
mail.MaildirStore.counters(username: string, mailbox: string)
MaildirStore.to_string()
mail.MaildirStore.to_string()
2026, Richard Ore and Zuri contributors