java.lang.Object
i2p.susi.webmail.pop3.POP3MailBox
- All Implemented Interfaces:
NewMailListener
POP3 client for retrieving email from POP3 servers over I2P. Supports standard POP3 commands, background checking, and delayed deletion. Optimized for high-latency I2P connections with pipelining and idle timeout management.
Nested Class Summary
Modifier and TypeClassDescriptionprivate classConnects to the POP3 server in a background thread.static interfaceRequest for fetching email data with UIDL and header options.private static enumFor SendRecv.private classRechecks for new mail in a background thread.private static classA command to send and a mode to receive and return the results.Field Summary
FieldsModifier and TypeFieldDescriptionprivate final LogLogger for the mailbox.private BackgroundCheckerChecker polling for new mail in the background.private booleanTrue while connected to the server.private final DelayedDeleterDeletes the mailbox when it goes idle.private booleanTrue once the server capabilities are known.private final StringThe mail server host.private IdleCloserTimer closing the connection when idle.private final AtomicLongWhen a webmail request last used the mailbox.private final AtomicLongWhen the mailbox was last checked for new mail.private StringLast error line received, null if none.private StringLast line received from the server.private intMessages the server reported.private NewMailListenerListener notified of new mail, may be null.private final StringThe login password.private final intThe mail server port.ID to size.private SocketThe connection to the server, null while closed.private booleanTrue if the server supports pipelining.private booleanTrue if the server supports the TOP command.private booleanTrue if the server supports the UIDL command.private final ObjectLock for the mailbox operations.UIDL to ID.private final StringThe login user name.Constructor Summary
ConstructorsMethod Summary
Modifier and TypeMethodDescriptionprivate static StringLooks up a localized string in the message bundle.(package private) booleanConnect to pop3 server if not connected.(package private) static StringcapsText(boolean pipelining, boolean uidl, boolean top) Reports what the server's CAPA (capability) response allowed, so a reader can tell why a listing used TOP or fell back to RETR.private voidIf not connected, connect now.private voidclear()Caller must sync.voidclose()Close without waiting for response.(package private) voidclose(boolean shouldWait) Close and optionally wait for response.private voidconnect()Closes any existing connection first.booleanConnect to pop3 server if not connected.(package private) voiddeletePending(boolean noWait) Delete all pending deletions at once.voiddestroy()Close without waiting for response, and remove any delayed tasks and resources.private booleanSend STAT, UIDL, LIST, and DELE for all pending.private voiddoDelete(boolean noWait) Send DELE for all pending deletions.private booleanCheck the initial response, send CAPA, check the CAPA result Caller must sync.voidfoundNewMail(boolean yes) Relay from the checker to the webmail session object, which relays to MailCache, which will fetch the mail from us in a big circle.voidgetBodies(Collection<POP3MailBox.FetchRequest> requests) Fetch headers and/or bodies.private BufferRetrieve message body from pop3 server (via RETR command) Caller must sync.Fetch the body.private BuffergetHeader(int id) Retrieves header from pop3 server (with TOP command and RETR as fallback) Caller must sync.Fetch the header.private intgetIDfromUIDL(String uidl) Returns number of message with given UIDL Caller must sync.(package private) longTimestamp of the last activity on the POP3 connection.(package private) longTimestamp.(package private) ObjectgetLock()For helper threads to lock.intWarning - forces a connection.private voidgetResultNa(Buffer buffer) No total timeout (result could be large) Caller must sync.Like getResultNa but returns a list of strings, one per line.private intgetSize(int id) Get cached size of a message (via previous LIST command).intGet cached size of a message (via previous LIST command).getUIDLs()Only if connected.(package private) booleanDo we have UIDLs to delete?(package private) booleanIs the connection is still alive.The last error the server or the client reported, stripped of its "-ERR" prefix.(package private) static StringloggedInText(String host, int port) Names the server the login succeeded against.(package private) static StringmailCountText(int mails, String host, int port) Names the server the count came from, so a reader can tell which mailbox is being reported without parsing the sentence.(package private) static StringmaskCommand(String cmd) The command as it may be written to the log.voidqueueForDeletion(String uidl) Queue for later deletion.voidqueueForDeletion(Collection<String> uidls) Queue for later deletion.private booleanSend command to pop3 server (and expect single line answer) Response will be in lastLine.private voidsendCmd1aNoWait(String cmd) Send command to pop3 server.private BufferTries twice Caller must sync.private BufferNo total timeout (result could be large) Caller must sync.Like sendCmdNa but returns a list of strings, one per line.private booleansendCmds(List<POP3MailBox.SendRecv> cmds) Send commands to pop3 server all at once (and expect answers).voidRelay from the checker to the webmail session object, which relays to MailCache, which will fetch the mail from us in a big circle.private voidRecords the current time as the last activity.private voidupdateMailCount(String response) Count the messages the server reports in the scan listing.private voidupdateSizes(List<String> lines) Caller must sync.private voidupdateUIDLs(List<String> lines) Caller must sync.
Field Details
host
The mail server host.user
The login user name.pass
The login password._log
Logger for the mailbox.lastLine
Last line received from the server.lastError
Last error line received, null if none.port
private final int portThe mail server port.mails
private int mailsMessages the server reported.connected
private boolean connectedTrue while connected to the server.gotCAPA
private boolean gotCAPATrue once the server capabilities are known.supportsPipelining
private boolean supportsPipeliningTrue if the server supports pipelining.supportsTOP
private boolean supportsTOPTrue if the server supports the TOP command.supportsUIDL
private boolean supportsUIDLTrue if the server supports the UIDL command.sizes
uidlToID
socket
The connection to the server, null while closed.lastActive
When a webmail request last used the mailbox.lastChecked
When the mailbox was last checked for new mail.synchronizer
Lock for the mailbox operations.delayedDeleter
Deletes the mailbox when it goes idle.backgroundChecker
Checker polling for new mail in the background.idleCloser
Timer closing the connection when idle.newMailListener
Listener notified of new mail, may be null.
Constructor Details
POP3MailBox
Does not connect. Caller must callconnectToServer(NewMailListener)if desired.- Parameters:
host- hostname of the POP3 server to connect toport- TCP port of the POP3 serveruser- account name to log in withpass- password for the account, sent in plaintext unless TLS is used
Method Details
getHeader
getHeader
Retrieves header from pop3 server (with TOP command and RETR as fallback) Caller must sync.- Parameters:
id- the 1-based message number from 1 to the mailbox size; out of range sets lastError- Returns:
- Byte buffer containing header data or null
getBody
getBodies
Fetch headers and/or bodies. Does not cache. ReadBuffer objects are inserted into the requests. No total time limit.- Parameters:
requests- one FetchRequest per message, each holding the ReadBuffer to fill
getBody
Retrieve message body from pop3 server (via RETR command) Caller must sync.- Parameters:
id- the 1-based message number from 1 to the mailbox size; out of range sets lastErrorbuffer- where the retrieved body lines are written, left untouched when the id is out of range- Returns:
- the buffer containing body data or null
queueForDeletion
Queue for later deletion. Non-blocking.- Parameters:
uidls- the server-side unique ids of the mails to queue
queueForDeletion
Queue for later deletion. Non-blocking.- Parameters:
uidl- the server-side unique id of the mail to queue
deletePending
void deletePending(boolean noWait) Delete all pending deletions at once. If previously connected, leaves connected. If not previously connected, closes connection when done.- Parameters:
noWait- fire-and-forget mode, only if connected
getSize
Get cached size of a message (via previous LIST command).- Parameters:
uidl- the server-side unique message id whose cached size is wanted- Returns:
- Message size in bytes or 0 if not found
getSize
private int getSize(int id) Get cached size of a message (via previous LIST command). Caller must sync.- Parameters:
id- the 1-based message number whose LIST size is wanted- Returns:
- Message size in bytes or 0 if not found
isConnected
boolean isConnected()Is the connection is still alive.- Returns:
- true or false
checkConnection
If not connected, connect now. Should be called from all public methods before sending a command. Caller must sync.- Throws:
IOException- if a fresh connection cannot be opened either
updateActivity
private void updateActivity()Records the current time as the last activity.getLastActivity
long getLastActivity()Timestamp of the last activity on the POP3 connection.- Returns:
- milliseconds since the epoch
getLastChecked
long getLastChecked()Timestamp. When we last successfully got the UIDL list.- Returns:
- milliseconds since the epoch
updateMailCount
Count the messages the server reports in the scan listing.- Parameters:
response- line starting with +OK
mailCountText
Names the server the count came from, so a reader can tell which mailbox is being reported without parsing the sentence.- Parameters:
mails- message count the server reported in its STAT responsehost- hostname of the POP3 serverport- TCP port of the POP3 server- Returns:
- the log message
loggedInText
capsText
Reports what the server's CAPA (capability) response allowed, so a reader can tell why a listing used TOP or fell back to RETR. Each capability is spelled out in prose with its wire name beside it, and answered yes or no rather than with a question mark, which reads like an unanswered question.- Parameters:
pipelining- whether the server accepts pipelined commandsuidl- whether the server supports the UIDL commandtop- whether the server supports the TOP command- Returns:
- the multi-line log message
updateUIDLs
updateSizes
clear
private void clear()Caller must sync.connectToServer
Connect to pop3 server if not connected. Checks mail if already connected. Non-Blocking unless an action already in progress. This will NOT call any configured NewMailListener, only the one passed in. It will be called with the value true if the connect was successful, false if not. CallgetNumMails()to see if there really was any new mail. After the callback is executed, the information on new mails, if any, is available via getNumMails(),getUIDLs(), and getSize(). The connection to the server will remain open, so that new emails may be retrieved viagetHeader(String), getBody(), and getBodies(). Failure info is available vialastError().- Parameters:
nml- notified once the listing is retrieved, or never on a connect or scan failure- Returns:
- true if nml will be called back, false on failure and nml will NOT be called back
blockingConnectToServer
boolean blockingConnectToServer()Connect to pop3 server if not connected. Does nothing if already connected. Blocking. This will NOT call any configured NewMailListener. After the callback is executed, the information on new mails, if any, is available via getNumMails(), getUIDLs(), andgetSize(String). The connection to the server will remain open, so that new emails may be retrieved via getHeader(),getBody(String, Buffer), and getBodies(). Failure info is available via lastError().- Returns:
- true if connected
connect
private void connect()Closes any existing connection first. Then, connect to pop3 server, login with USER and PASS and try STAT then. Caller must sync.doHandshake
Check the initial response, send CAPA, check the CAPA result Caller must sync.- Returns:
- true if successful
- Throws:
IOException- if a handshake command cannot be written or answered
doCheckMail
Send STAT, UIDL, LIST, and DELE for all pending. Must be connected. Caller must sync. Leaves socket connected. Caller must close on IOE.- Returns:
- true if every command was sent and received an OK reply
- Throws:
IOException- if not connected, or a command cannot be written or answered
doDelete
Send DELE for all pending deletions. Must be connected. Caller must sync. Leaves socket connected. Caller must close on IOE.- Parameters:
noWait- true to send each DELE and drop it from the pending set without waiting for a reply; false to batch them and wait, pruning only if the connection survives- Throws:
IOException- if a DELE command cannot be written to the server
sendCmd1a
Send command to pop3 server (and expect single line answer) Response will be in lastLine. Does not read past the first line of the response. Caller must sync.- Parameters:
cmd- command to send- Returns:
- true if command was successful (+OK)
- Throws:
IOException- if the server closes the connection without answering
sendCmds
Send commands to pop3 server all at once (and expect answers). Sets lastError to the FIRST error. Caller must sync.- Parameters:
cmds- command to send- Returns:
- true if ALL received lines were successful (+OK)
- Throws:
IOException- if a command cannot be written, or the server sends no reply line
sendCmd1aNoWait
Send command to pop3 server. Does NOT flush or read or wait. Caller must sync.- Parameters:
cmd- command to send non-null- Throws:
IOException- if the command cannot be written to the socket
sendCmdN
sendCmdNa
No total timeout (result could be large) Caller must sync.- Parameters:
cmd- the command to send, such as "RETR 3"buffer- where the multi-line result is written- Returns:
- the buffer or null
- Throws:
IOException- if the server sends no reply, or the result cannot be read
sendCmdNl
Like sendCmdNa but returns a list of strings, one per line. Strings will have trailing \r but not \n. Total timeout 2 minutes. Caller must sync.- Parameters:
cmd- the command to send, such as "LIST"- Returns:
- the lines or null on error
- Throws:
IOException- if the server goes 2 minutes without sending the terminating dot
getResultNa
No total timeout (result could be large) Caller must sync.- Parameters:
buffer- non-null- Throws:
IOException- if a line cannot be read from the server or the buffer write fails
getResultNl
Like getResultNa but returns a list of strings, one per line. Strings will have trailing \r but not \n. Total timeout 2 minutes. Caller must sync.- Returns:
- the lines non-null
- Throws:
IOException- if the server goes 2 minutes without sending the terminating dot
getNumMails
public int getNumMails()Warning - forces a connection.- Returns:
- The amount of e-mails available.
lastError
The last error the server or the client reported, stripped of its "-ERR" prefix.- Returns:
- The most recent error message. Probably not terminated with a newline.
setNewMailListener
Relay from the checker to the webmail session object, which relays to MailCache, which will fetch the mail from us in a big circle.- Parameters:
nml- the session-side listener that new-mail notifications are relayed to
foundNewMail
public void foundNewMail(boolean yes) Relay from the checker to the webmail session object, which relays to MailCache, which will fetch the mail from us in a big circle.- Specified by:
foundNewMailin interfaceNewMailListener- Parameters:
yes- true if new mail was found
destroy
public void destroy()Close without waiting for response, and remove any delayed tasks and resources.getLock
Object getLock()For helper threads to lock.- Returns:
- the monitor serializing all command and connection activity
hasQueuedDeletions
boolean hasQueuedDeletions()Do we have UIDLs to delete?- Returns:
- true if at least one UIDL is waiting to be deleted from the server
close
public void close()Close without waiting for response. Deletes all queued deletions.close
void close(boolean shouldWait) Close and optionally wait for response. Deletes all queued deletions.- Parameters:
shouldWait- true to send QUIT and block until the server acknowledges
getIDfromUIDL
Returns number of message with given UIDL Caller must sync.- Parameters:
uidl- the server-side unique message id to map to a message number- Returns:
- Message number or -1
getUIDLs
Only if connected. Does not force a connect. If not connected, returns null.- Returns:
- A new array of the available UIDLs. No particular order.
maskCommand
The command as it may be written to the log. The login credentials are dropped so that neither the account name nor the password reaches the log files, which are readable through the web console.- Parameters:
cmd- the POP3 command to be logged, non-null- Returns:
- the command with any credential argument replaced
_t