Class MboxMailbox
- All Implemented Interfaces:
Mailbox
This implementation handles the standard Unix mbox format as defined in RFC 4155. An mbox file contains multiple messages separated by "From " envelope lines.
Mbox Format:
From sender@example.com Mon Jan 1 00:00:00 2025 [RFC 822 message headers] [message body] From another@example.com Tue Jan 2 00:00:00 2025 [next message...]
From_ Escaping: Lines in the message body that begin with "From " are escaped by prepending ">" to become ">From ". When reading, this escaping is reversed.
This implementation uses file locking to prevent concurrent access.
- Author:
- Chris Burdess
- See Also:
-
Constructor Summary
ConstructorsConstructorDescriptionMboxMailbox(Path mboxFile, String name, boolean readOnly) Creates and opens an mbox mailbox. -
Method Summary
Modifier and TypeMethodDescriptionvoidAppends content data to the message currently being appended.voidclose(boolean expunge) Closes the mailbox and releases any locks.voiddeleteMessage(int messageNumber) Marks a message for deletion.longCompletes the message append operation.expunge()Permanently removes all messages marked for deletion.longReturns the total size of all messages in octets.getMessage(int messageNumber) Returns the message descriptor for the specified message number.getMessageContent(int messageNumber) Opens a channel to read the entire message content.intReturns the number of messages in the mailbox.Returns an iterator over all message descriptors in the mailbox.getMessageTop(int messageNumber, int bodyLines) Opens a channel to read the message headers and optionally a portion of the body, as required by the POP3 TOP command (RFC 1939 Section 7).getName()Returns the name of this mailbox.getUniqueId(int messageNumber) Returns the unique identifier for a message.booleanisDeleted(int messageNumber) Checks if a message is marked for deletion.booleanReturns whether this mailbox is open in read-only mode.search(SearchCriteria criteria) Searches for messages matching the given criteria using the search index.voidstartAppendMessage(Set<Flag> flags, OffsetDateTime internalDate) Begins appending a new message to this mailbox.voidUnmarks all messages marked for deletion.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.bluezoo.gumdrop.mailbox.Mailbox
copyMessages, getChangedSince, getExpungedSince, getFlags, getHighestModSeq, getMessagePath, getMessageTopEndOffset, getModSeq, getPermanentFlags, getUidNext, getUidValidity, moveMessages, openAsyncAppend, openAsyncContent, replaceFlags, setFlags
-
Constructor Details
-
MboxMailbox
Creates and opens an mbox mailbox.- Parameters:
mboxFile- the mbox file pathname- the mailbox namereadOnly- true to open in read-only mode- Throws:
IOException- if the mailbox cannot be opened
-
-
Method Details
-
getName
Description copied from interface:MailboxReturns the name of this mailbox. For POP3, this is typically "INBOX". -
isReadOnly
public boolean isReadOnly()Description copied from interface:MailboxReturns whether this mailbox is open in read-only mode.- Specified by:
isReadOnlyin interfaceMailbox- Returns:
- true if read-only
-
close
Description copied from interface:MailboxCloses the mailbox and releases any locks. This should commit any pending deletions.- Specified by:
closein interfaceMailbox- Parameters:
expunge- if true, permanently remove messages marked for deletion; if false, unmark all deletion marks- Throws:
IOException- if the mailbox cannot be closed properly
-
getMessageCount
Description copied from interface:MailboxReturns the number of messages in the mailbox. This does not include messages marked for deletion.- Specified by:
getMessageCountin interfaceMailbox- Returns:
- the number of accessible messages
- Throws:
IOException- if the count cannot be determined
-
getMailboxSize
Description copied from interface:MailboxReturns the total size of all messages in octets. This does not include messages marked for deletion.- Specified by:
getMailboxSizein interfaceMailbox- Returns:
- the total size in octets
- Throws:
IOException- if the size cannot be determined
-
getMessageList
Description copied from interface:MailboxReturns an iterator over all message descriptors in the mailbox. Messages are returned in order by message number (1-based). Messages marked for deletion are not included.Using an iterator rather than a list allows implementations to lazily load descriptors, reducing memory usage for large mailboxes. Use
Mailbox.getMessageCount()to get the total count.- Specified by:
getMessageListin interfaceMailbox- Returns:
- iterator over message descriptors
- Throws:
IOException- if the messages cannot be enumerated
-
getMessage
Description copied from interface:MailboxReturns the message descriptor for the specified message number.- Specified by:
getMessagein interfaceMailbox- Parameters:
messageNumber- the message sequence number (1-based)- Returns:
- the message descriptor, or null if the message doesn't exist
- Throws:
IOException- if the descriptor cannot be retrieved
-
getMessageContent
Description copied from interface:MailboxOpens a channel to read the entire message content. The content includes headers and body, with proper RFC 822 formatting.The caller is responsible for closing the returned channel.
- Specified by:
getMessageContentin interfaceMailbox- Parameters:
messageNumber- the message sequence number (1-based)- Returns:
- a readable channel for the message content
- Throws:
IOException- if the message cannot be opened
-
getMessageTop
Description copied from interface:MailboxOpens a channel to read the message headers and optionally a portion of the body, as required by the POP3 TOP command (RFC 1939 Section 7).The content returned includes:
- All message headers (RFC 822 format)
- A blank line (CRLF) separating headers from body
- The first
bodyLineslines of the message body
The caller is responsible for closing the returned channel.
- Specified by:
getMessageTopin interfaceMailbox- Parameters:
messageNumber- the message sequence number (1-based)bodyLines- the number of body lines to retrieve after headers (0 means headers only, with trailing blank line)- Returns:
- a readable channel for the headers and body lines
- Throws:
IOException- if the content cannot be retrieved
-
deleteMessage
Description copied from interface:MailboxMarks a message for deletion. The message is not actually deleted until close() is called with expunge=true, or expunge() is called explicitly.- Specified by:
deleteMessagein interfaceMailbox- Parameters:
messageNumber- the message sequence number (1-based)- Throws:
IOException- if the message cannot be marked for deletion
-
isDeleted
Description copied from interface:MailboxChecks if a message is marked for deletion.- Specified by:
isDeletedin interfaceMailbox- Parameters:
messageNumber- the message sequence number (1-based)- Returns:
- true if the message is marked for deletion
- Throws:
IOException- if the status cannot be determined
-
undeleteAll
Description copied from interface:MailboxUnmarks all messages marked for deletion. This is used by the POP3 RSET command.- Specified by:
undeleteAllin interfaceMailbox- Throws:
IOException- if the messages cannot be unmarked
-
expunge
Description copied from interface:MailboxPermanently removes all messages marked for deletion. This is the IMAP EXPUNGE command.- Specified by:
expungein interfaceMailbox- Returns:
- list of expunged message numbers (in ascending order)
- Throws:
IOException- if messages cannot be expunged
-
getUniqueId
Description copied from interface:MailboxReturns the unique identifier for a message. This must be unique and persistent across sessions. Typically derived from Message-ID or a content hash.- Specified by:
getUniqueIdin interfaceMailbox- Parameters:
messageNumber- the message sequence number (1-based)- Returns:
- the unique identifier string
- Throws:
IOException- if the UID cannot be retrieved
-
startAppendMessage
Description copied from interface:MailboxBegins appending a new message to this mailbox.This is the first of three methods used for streaming message append in an event-driven architecture. After calling this method, call
Mailbox.appendMessageContent(ByteBuffer)zero or more times as data arrives, then callMailbox.endAppendMessage()to complete the operation.Only one append operation may be in progress at a time per mailbox instance. Implementations should throw an exception if this method is called while an append is already in progress.
- Specified by:
startAppendMessagein interfaceMailbox- Parameters:
flags- initial flags for the message, or null for no flagsinternalDate- the internal date, or null for current time- Throws:
IOException- if the append cannot be started
-
appendMessageContent
Description copied from interface:MailboxAppends content data to the message currently being appended.This method may be called multiple times as data arrives from the client. The data should be in RFC 822 format. The buffer should be ready for reading (flipped).
This method must only be called after
Mailbox.startAppendMessage(java.util.Set<org.bluezoo.gumdrop.mailbox.Flag>, java.time.OffsetDateTime)and beforeMailbox.endAppendMessage().- Specified by:
appendMessageContentin interfaceMailbox- Parameters:
data- buffer containing message content data, ready for reading- Throws:
IOException- if the content cannot be written
-
endAppendMessage
Description copied from interface:MailboxCompletes the message append operation.This method finalizes the append, assigns a UID to the new message, and makes it visible in the mailbox. After this method returns, the server can send the response to the client.
If an error occurs, implementations should clean up any partial data and throw an exception. The mailbox should remain in a consistent state.
- Specified by:
endAppendMessagein interfaceMailbox- Returns:
- the UID of the newly appended message
- Throws:
IOException- if the append cannot be completed
-
search
Searches for messages matching the given criteria using the search index. Falls back to parsing messages for TEXT/BODY searches.- Specified by:
searchin interfaceMailbox- Parameters:
criteria- the search criteria- Returns:
- list of matching message sequence numbers
- Throws:
IOException- if the search fails- See Also:
-