@@ -12,49 +12,39 @@ import (
1212 "github.com/emersion/go-imap/v2/internal/imapwire"
1313)
1414
15- func (c * Client ) fetch (uid bool , seqSet imap.NumSet , options * imap.FetchOptions ) * FetchCommand {
15+ // Fetch sends a FETCH command.
16+ //
17+ // The caller must fully consume the FetchCommand. A simple way to do so is to
18+ // defer a call to FetchCommand.Close.
19+ //
20+ // A nil options pointer is equivalent to a zero options value.
21+ func (c * Client ) Fetch (numSet imap.NumSet , options * imap.FetchOptions ) * FetchCommand {
1622 if options == nil {
1723 options = new (imap.FetchOptions )
1824 }
1925
26+ numKind := imapwire .NumSetKind (numSet )
27+
2028 cmd := & FetchCommand {
21- uid : uid ,
22- seqSet : seqSet ,
29+ numSet : numSet ,
2330 msgs : make (chan * FetchMessageData , 128 ),
2431 }
25- enc := c .beginCommand (uidCmdName ("FETCH" , uid ), cmd )
26- enc .SP ().NumSet (seqSet ).SP ()
27- writeFetchItems (enc .Encoder , uid , options )
32+ enc := c .beginCommand (uidCmdName ("FETCH" , numKind ), cmd )
33+ enc .SP ().NumSet (numSet ).SP ()
34+ writeFetchItems (enc .Encoder , numKind , options )
2835 if options .ChangedSince != 0 {
2936 enc .SP ().Special ('(' ).Atom ("CHANGEDSINCE" ).SP ().ModSeq (options .ChangedSince ).Special (')' )
3037 }
3138 enc .end ()
3239 return cmd
3340}
3441
35- // Fetch sends a FETCH command.
36- //
37- // The caller must fully consume the FetchCommand. A simple way to do so is to
38- // defer a call to FetchCommand.Close.
39- //
40- // A nil options pointer is equivalent to a zero options value.
41- func (c * Client ) Fetch (seqSet imap.NumSet , options * imap.FetchOptions ) * FetchCommand {
42- return c .fetch (false , seqSet , options )
43- }
44-
45- // UIDFetch sends a UID FETCH command.
46- //
47- // See Fetch.
48- func (c * Client ) UIDFetch (seqSet imap.NumSet , options * imap.FetchOptions ) * FetchCommand {
49- return c .fetch (true , seqSet , options )
50- }
51-
52- func writeFetchItems (enc * imapwire.Encoder , uid bool , options * imap.FetchOptions ) {
42+ func writeFetchItems (enc * imapwire.Encoder , numKind imapwire.NumKind , options * imap.FetchOptions ) {
5343 listEnc := enc .BeginList ()
5444
5545 // Ensure we request UID as the first data item for UID FETCH, to be safer.
5646 // We want to get it before any literal.
57- if options .UID || uid {
47+ if options .UID || numKind == imapwire . NumKindUID {
5848 listEnc .Item ().Atom ("UID" )
5949 }
6050
@@ -159,14 +149,42 @@ func writeSectionPartial(enc *imapwire.Encoder, partial *imap.SectionPartial) {
159149type FetchCommand struct {
160150 cmd
161151
162- uid bool
163- seqSet imap.NumSet
164- recvNumSet imap.NumSet
152+ numSet imap. NumSet
153+ recvSeqSet imap.SeqSet
154+ recvUIDSet imap.UIDSet
165155
166156 msgs chan * FetchMessageData
167157 prev * FetchMessageData
168158}
169159
160+ func (cmd * FetchCommand ) recvSeqNum (seqNum uint32 ) bool {
161+ set , ok := cmd .numSet .(imap.SeqSet )
162+ if ! ok || ! set .Contains (seqNum ) {
163+ return false
164+ }
165+
166+ if cmd .recvSeqSet .Contains (seqNum ) {
167+ return false
168+ }
169+
170+ cmd .recvSeqSet .AddNum (seqNum )
171+ return true
172+ }
173+
174+ func (cmd * FetchCommand ) recvUID (uid imap.UID ) bool {
175+ set , ok := cmd .numSet .(imap.UIDSet )
176+ if ! ok || ! set .Contains (uid ) {
177+ return false
178+ }
179+
180+ if cmd .recvUIDSet .Contains (uid ) {
181+ return false
182+ }
183+
184+ cmd .recvUIDSet .AddNum (uid )
185+ return true
186+ }
187+
170188// Next advances to the next message.
171189//
172190// On success, the message is returned. On error or if there are no more
@@ -464,18 +482,11 @@ func (c *Client) handleFetch(seqNum uint32) error {
464482 }
465483
466484 // Skip if we haven't requested or already handled this message
467- var num uint32
468- if cmd .uid {
469- num = uint32 (uid )
485+ if _ , ok := cmd .numSet .(imap.UIDSet ); ok {
486+ return uid != 0 && cmd .recvUID (uid )
470487 } else {
471- num = seqNum
472- }
473- if num == 0 || ! cmd .seqSet .Contains (num ) || cmd .recvNumSet .Contains (num ) {
474- return false
488+ return seqNum != 0 && cmd .recvSeqNum (seqNum )
475489 }
476- cmd .recvNumSet .AddNum (num )
477-
478- return true
479490 })
480491 if cmd != nil {
481492 cmd := cmd .(* FetchCommand )
0 commit comments