IMAP allows clients to operate on the mailbox, message status, and content on the server, making it suitable for maintaining a shared view across multiple devices. POP3 primarily provides listing, downloading, and deleting messages in the maildrop. Both can cache emails locally, and neither implies "delete immediately after download." The real difference lies in how much state and operations the server provides for synchronization.
Capability
IMAP
POP3
Organize messages
Multiple mailboxes, server-side status, and search
Centered on the current maildrop message list
Read
Can fetch headers, body parts, or attachments only
RETR fetches the entire message; optional TOP fetches header and partial lines
Delete
Separate marking and expunging, also supports MOVE
DELE marks for deletion; update occurs on normal QUIT
Multi-device consistency
Mechanisms like UID, flags, and sync extensions
No equivalent shared folder/read-sync model
Offline
Depends on downloaded content and local operation queue
Can read offline after download
Notifications
IDLE receives mailbox change notifications
Basic protocol usually relies on client polling
This article uses IMAP4rev2 (RFC 9051) as the primary semantic reference. When encountering IMAP4rev1 services, extensions must be determined via CAPABILITY; do not arbitrarily mix old and new response examples. RFC 9051
IMAP Session: Login Does Not Mean Mailbox Selected
The connection goes through states such as unauthenticated, authenticated, mailbox selected, and logout. LIST lists mailboxes after authentication; SELECT selects a read-write mailbox, while EXAMINE provides a read-only view; FETCH, STORE, etc., operate on the selected mailbox. Successful authentication does not automatically imply that all subsequent commands target INBOX.
Commands carry client tags, such as a003; the final OK/NO/BAD with the same tag indicates the command is complete. Untagged responses starting with * report data or state changes and are not the final response to another command; + is a continuation prompt. Client parsers should handle interleaved responses rather than treating "reading one line" as the end of a call.
Example
How to Interpret
* 42 EXISTS
There are 42 messages in the current mailbox, not that 42 new messages were added
* OK [UIDVALIDITY 700]
The validity value of the current UID namespace
* OK [UIDNEXT 109]
The predicted boundary for future UIDs; does not guarantee the next message is exactly 109
a003 OK [READ-WRITE] SELECT completed
Selection command completed; mailbox operations can continue
RECENT / \Recent in old IMAP4rev1 is deprecated in rev2; it never directly represented a consistent unread count across all devices. Unread status is typically determined by the presence of \Seen.
Sequence Numbers, UID, UIDVALIDITY: Why Cache Keys Need Three Parts
The message sequence number is the position in the current mailbox, starting from 1. When preceding messages are cleared, subsequent sequence numbers shift forward. The UID is stable and incrementing within the same mailbox and UIDVALIDITY but can have gaps; it is not a global message ID for the account.
Assume the client sees sequence number 2 corresponding to UID 104, and then another client removes sequence number 1. If you continue to execute STORE 2 based on the remembered position, the current target might already be UID 108. Synchronizers should use UID operations with full scope and promptly update received deletion/sequence change information.
uids=[101,104,108]remembered_sequence=2remembered_uid=uids[remembered_sequence-1]assertremembered_uid==104uids.pop(0)# Original seq 1 cleared
assertuids[remembered_sequence-1]==108assertuids.index(remembered_uid)+1==1old_key=('INBOX',700,104)new_epoch_key=('INBOX',701,104)assertold_key!=new_epoch_keyprint('Sequence shift and UIDVALIDITY cache isolation model passed')
Actual cache keys should also include account/server identifiers. When UIDVALIDITY changes, old UID mappings cannot continue to locate server messages; you need to re-enumerate and establish associations, rather than directly applying old offline deletion commands to new UID 104. After copying or moving to another mailbox, the target UID may also change; supported UID mapping responses help update the cache. UIDPLUS RFC 4315
Details of UIDNEXT and Asterisk Ranges
The value of UIDNEXT is used to predict future UID allocations, and UIDs can still skip numbers. Another point often misjudged is that ranges allow endpoints to be in reverse order: if the mailbox's maximum UID is 108, in UID FETCH 109:*, the asterisk represents the largest UID, and it cannot be simply understood as always returning an empty set. Clients should use appropriate search/synchronization methods and verify that the returned UIDs are indeed higher than the local watermark.
Non-existent specified UIDs are usually ignored, and command OK does not guarantee the target message was found. Therefore, operation completion, target existence, and target status matching expectations are three different observations.
After deleting the first message, is sequence number 2 still the same message?
After clearing the first message, sequence number 2 points to UID 108, while UID 104 moves to sequence number 1. Rebuilding the mailbox, even if 104 reappears, old cache keys cannot be reused; what changes is the identity scope, not just list reordering.
Preparing the visual
After deleting the first message, is sequence number 2 still the same message?
Sequence numbers move with the current position; UIDs depend on the mailbox and UIDVALIDITY scope. Same numbers do not mean the same object identity.
{"id":"imap-position-identity","title":"After deleting the first message, is sequence number 2 still the same message?","summary":"Sequence numbers move with the current position; UIDs depend on the mailbox and UIDVALIDITY scope. Same numbers do not mean the same object identity.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"actions\"><button id=\"expunge\" data-i18n=\"expunge\"></button><button id=\"epoch\" data-i18n=\"epoch\"></button><button id=\"reset\" data-i18n=\"reset\"></button></div><section class=\"panel\"><h3 data-i18n=\"mailbox\"></h3><div id=\"mailbox\"></div></section><div class=\"metrics\"><div><span data-i18n=\"seq\"></span><strong id=\"seq\"></strong></div><div><span data-i18n=\"uid\"></span><strong id=\"uid\"></strong></div></div><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px var(--viz-font-ui);padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 var(--viz-font-ui);overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n#mailbox .tr>*{min-height:4.8em}.metrics strong{font-size:16px}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}let epoch=700,uids=[101,104,108];function draw(){table('mailbox',[['sequence','UID','epoch'],...[0,1,2].map(i=>[uids[i]?i+1:'—',uids[i]||'—',uids[i]?epoch:'—'])]);set('seq',uids[1]?'UID'+uids[1]+' @'+epoch:'∅');set('uid',epoch!==700?'INVALID SCOPE':uids.includes(104)?'UID104 @700':'∅');$('#expunge').disabled=!uids.length;$('#epoch').disabled=epoch!==700;$('#mailbox').dataset.snapshot=JSON.stringify({epoch,uids});}$('#expunge').onclick=()=>{uids.shift();draw()};$('#epoch').onclick=()=>{epoch=701;uids=[101,104,108];draw()};$('#reset').onclick=()=>{epoch=700;uids=[101,104,108];draw()};draw();","audio":false,"strings":{"epoch":"Rebuild mailbox and change UIDVALIDITY","expunge":"Expunge current first message","heading":"After deleting the first message, is sequence number 2 still the same message?","intro":"Retain the sequence number and UID remembered by the client, then clear the previous message or switch UIDVALIDITY.","mailbox":"Current mailbox object","reset":"Reset","scope":"Fixed INBOX and same account, UIDs 101/104/108, initial UIDVALIDITY 700, remember seq 2/UID 104. After epoch change, same numbers represent new objects; do not automatically apply old offline operations.","scopeLabel":"Model Scope and Conventions","seq":"Locate by remembered seq 2","uid":"Locate by old scope UID 104"}}
Fetching Content, Modifying Flags, and Reading Literals by Byte
UID FETCH 104 (UID FLAGS RFC822.SIZE BODY.PEEK[HEADER.FIELDS (FROM SUBJECT DATE)]) can first fetch fields needed for the display list, avoiding downloading the entire large attachment. BODY.PEEK[...] does not implicitly set \Seen due to reading content; the corresponding fetch behavior of normal BODY[...] may set it.
When returning content, the server can use {N} literals, where N indicates the number of subsequent raw bytes. The body may contain line breaks, parentheses, or text that looks like responses; the parser must read exactly N bytes before resuming protocol parsing, and cannot simply look for the closing parenthesis by line.
payload='Subject: Status\r\n'.encode('utf-8')assertlen(payload)==17# Five Chinese characters 15 B, plus CRLF 2 B
wire=b'{17}\r\n'+payload+b')\r\na004 OK done\r\n'header, rest=wire.split(b'\r\n',1)size=int(header[1:-1])literal, tail=rest[:size], rest[size:]assertliteral.decode('utf-8')=='Subject: Status\r\n'asserttail.startswith(b')\r\na004 OK')assertlen(literal)!=len(literal.decode('utf-8'))print('UTF-8 literal byte-delimited parsing passed')
Marking as read can be done with UID STORE 104 +FLAGS.SILENT (\Seen). +FLAGS adds specified flags; using FLAGS replaces the entire set and may overwrite updates from other clients. .SILENT suppresses the corresponding flags data echo generated by this operation, but does not close all server state notifications.
Deletion and Move: Operations Do Not Share the Same "Delete Button" Semantics
Setting \Deleted is just a mark; EXPUNGE actually clears messages marked for deletion in the selected mailbox. A normal EXPUNGE may clear messages marked by another client as well, so you cannot assume it only processes UIDs you just operated on. When supported, UID EXPUNGE with a limited UID set can narrow the scope.
MOVE moves messages from one mailbox to another. Old clients simulate this via COPY, marking for deletion, and EXPUNGE, which involves intermediate states and failure windows; dedicated MOVE avoids issues with partial composite operations, but multi-message operations still need to handle partial failures and cannot describe a bulk move as an all-or-nothing transaction like an application database. MOVE RFC 6851
CLOSE may clear messages marked for deletion in a read-write selected state; UNSELECT exits the selected state without performing this clearing. When doing read-only checks, prioritize understanding EXAMINE semantics and do not arbitrarily call operations with deletion consequences just to "exit the mailbox."
IDLE is Change Notification, Not a Persistent Event Log
The client sends a tagged IDLE, and the server returns + and keeps the command waiting, during which it can report changes like EXISTS or flags. When the client wants to execute the next normal command, it first sends an untagged DONE, waits for the IDLE tag completion response, and then continues.
Moment
Example Interaction
Client Next Step
Start Waiting
a010 IDLE, server + idling
Continuously read untagged responses
New Status Hint
* 43 EXISTS
Record what needs syncing, do not treat the number as UID
End Waiting
DONE, server a010 OK ...
Then initiate FETCH/SEARCH, etc.
Connection Drop
No persistent event position guarantee
Reconnect, check UIDVALIDITY, catch up on state
The specification recommends ending and resending IDLE within an interval of no more than 29 minutes to accommodate server idle timeouts; intermediate NAT or mobile device sleep may still cause earlier disconnections. IDLE provides timely notifications but does not promise fixed latency, always-online status, or replayable message notifications during disconnections. IMAP IDLE
Incremental Synchronization and Concurrent Conflicts
Comparing only UIDNEXT can detect some new changes, but cannot know about changes to old message flags or cleared UIDs. Services supporting CONDSTORE use MODSEQ to identify state changes; QRESYNC further supports fast resynchronization and VANISHED deletion information. Before use, you need to enable them according to protocol version and capabilities; do not assume all services implement them. CONDSTORE/QRESYNC RFC 7162
Assume the client reads message MODSEQ 20, and during offline time, another client changes it to 21. A conditional STORE with UNCHANGEDSINCE 20 can reject overwriting the new state and inform the unapplied target via MODIFIED. The client should re-read and decide on merging, rather than ignoring the conflict and continuing to advance the local watermark.
The recovery process is therefore: verify mailbox and UIDVALIDITY, supplement additions, changes, and deletions, confirm local data is persisted, and then save the sync watermark. IDLE hints and sync watermarks are not the same thing; updating the watermark before saving actual content may lead to mistakenly believing synchronization is complete after a crash.
POP3: Download, Mark, and Update Are Three Separate Actions
After POP3 authentication, it enters TRANSACTION; LIST/STAT view messages and sizes, RETR downloads, and DELE marks for deletion. Only a normal QUIT from the transaction state enters UPDATE, executing deletions based on marks; RSET can clear deletion marks, and abnormal disconnections should not enter deletion updates solely due to previous DELE. POP3 RFC 1939
Therefore, "POP3 download equals delete" is not a protocol rule. Clients can retain server copies, or request deletion after successfully saving local copies. If multiple devices retain copies, they can each download, but there is no shared read and folder synchronization semantics like IMAP.
POP3 message numbers are only used for positioning within the current maildrop session and may change across sessions. Optional UIDL provides cross-session identifiers, allowing clients to avoid duplicate downloads; it is not an RFC 5322 Message-ID. The specification even allows special cases where identical copies have the same unique-id; do not treat UIDL as a globally unique UUID that can ignore duplicates.
Local save and server UPDATE also do not share a common transaction: if you record "downloaded" first and then persist content, a client crash may result in missed storage; if content is saved but local records are not yet committed, reconnecting may cause duplicate downloads. When QUIT is executed but the response is lost, the deletion result is also ambiguous. Archiving programs need to reliably commit local content and indexes, and re-enumerate server state upon reconnecting.
After DELE and a drop, is the message deleted?
RETR then DELE; the server copy remains; after reconnecting from an abnormal drop, the mark disappears and the message is retained. Only after resetting and proceeding with a normal QUIT does the server delete. If you delete and QUIT without downloading, this model also exposes the result of having no local copy.
Preparing the visual
After DELE and a drop, is the message deleted?
RETR copies content, DELE only marks, normal QUIT enters UPDATE. Abnormal drops do not automatically treat uncommitted marks as deleted.
{"id":"pop3-delete-commit","title":"After DELE and a drop, is the message deleted?","summary":"RETR copies content, DELE only marks, normal QUIT enters UPDATE. Abnormal drops do not automatically treat uncommitted marks as deleted.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"actions\"><button id=\"retr\" data-i18n=\"retr\"></button><button id=\"dele\" data-i18n=\"dele\"></button><button id=\"rset\" data-i18n=\"rset\"></button><button id=\"quit\" data-i18n=\"quit\"></button><button id=\"drop\" data-i18n=\"drop\"></button><button id=\"reconnect\" data-i18n=\"reconnect\"></button><button id=\"reset\" data-i18n=\"reset\"></button></div><section class=\"panel\"><h3 data-i18n=\"state\"></h3><div id=\"state\"></div></section><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px var(--viz-font-ui);padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 var(--viz-font-ui);overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n#state .tr{grid-template-columns:1fr 1fr}.tr>*{min-height:4em}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}let server=true,local=false,mark=false,open=true;function draw(){table('state',[['server copy',server?'✓':'∅'],['local saved',local?'✓':'∅'],['DELE mark',mark?'✓':'∅'],['session',open?'TRANSACTION':'CLOSED']]);$('#retr').disabled=$('#dele').disabled=!open||!server||mark;$('#rset').disabled=!open||!mark;$('#quit').disabled=$('#drop').disabled=!open;$('#reconnect').disabled=open;$('#state').dataset.snapshot=JSON.stringify({server,local,mark,open});}$('#retr').onclick=()=>{local=true;draw()};$('#dele').onclick=()=>{mark=true;draw()};$('#rset').onclick=()=>{mark=false;draw()};$('#quit').onclick=()=>{if(mark)server=false;mark=false;open=false;draw()};$('#drop').onclick=()=>{mark=false;open=false;draw()};$('#reconnect').onclick=()=>{open=true;draw()};$('#reset').onclick=()=>{server=true;local=false;mark=false;open=true;draw()};draw();","audio":false,"strings":{"dele":"DELE Mark","drop":"Abnormal Drop","heading":"After DELE and a drop, is the message deleted?","intro":"Operate download, deletion mark, normal QUIT, and abnormal drop separately, observing server and local copies.","quit":"Normal QUIT","reconnect":"Reconnect","reset":"Reset","retr":"RETR Download Save","rset":"RSET Undo Mark","scope":"One message, single client; QUIT update assumes success and response arrival, local RETR persists immediately. Real UPDATE failures and response loss are covered in the text, not simulating the entire POP3 session.","scopeLabel":"Model Scope and Conventions","state":"Copy and Session State"}}
TLS, Authentication, and Selection Criteria
IMAP commonly uses TCP 993, POP3 commonly uses TCP 995 for implicit TLS; 143/110 can be upgraded via STARTTLS/STLS respectively, with specific capabilities needing negotiation. Server identity verification should be completed before sending passwords; whether OAuth or other SASL mechanisms are supported is determined by server capabilities; do not skip certificate verification just because the connection uses TLS. Email Access TLS RFC 8314
Multi-device collaboration, server search, and folder synchronization fit the IMAP state model better; one-way download to an independent archive library can use POP3, but "simple" does not automatically eliminate backup, deduplication, and deletion timing issues. IMAP synchronization is also not a backup: accidental deletion on the server can be synchronized to all clients; independent version retention and recovery points are another capability.