@@ -1532,6 +1532,19 @@ pub const ImapSession = struct {
15321532 const want_body_text_only = (std .mem .indexOf (u8 , items_raw , "BODY[TEXT]" ) != null ) or
15331533 (std .mem .indexOf (u8 , items_raw , "BODY.PEEK[TEXT]" ) != null );
15341534
1535+ // Parse partial fetch <offset.count> if present
1536+ var partial_offset : ? usize = null ;
1537+ var partial_count : ? usize = null ;
1538+ if (std .mem .indexOf (u8 , items_raw , "<" )) | angle_start | {
1539+ if (std .mem .indexOfScalarPos (u8 , items_raw , angle_start , '>' )) | angle_end | {
1540+ const partial_spec = items_raw [angle_start + 1 .. angle_end ];
1541+ if (std .mem .indexOf (u8 , partial_spec , "." )) | dot | {
1542+ partial_offset = std .fmt .parseInt (usize , partial_spec [0.. dot ], 10 ) catch null ;
1543+ partial_count = std .fmt .parseInt (usize , partial_spec [dot + 1 .. ], 10 ) catch null ;
1544+ }
1545+ }
1546+ }
1547+
15351548 var seq = start ;
15361549 while (seq <= end ) : (seq += 1 ) {
15371550 const filename = files [seq - 1 ];
@@ -1653,8 +1666,23 @@ pub const ImapSession = struct {
16531666 try self .writeData ("\r \n " );
16541667 } else if (want_body_text_only ) {
16551668 // BODY[TEXT] or BODY.PEEK[TEXT] — return just the body (after headers)
1656- const resp = try std .fmt .allocPrint (self .allocator , "* {d} FETCH (UID {d} FLAGS ({s}) RFC822.SIZE {d} INTERNALDATE \" {s}\" {s} BODY[TEXT] {{{d}}}\r \n {s})" , .{
1657- seq , uid , flag_str , content .len , date_str , bs_part , body .len , body ,
1669+ // Apply partial fetch <offset.count> if requested
1670+ const text_data = if (partial_offset ) | off | blk : {
1671+ if (off >= body .len ) break :blk @as ([]const u8 , "" );
1672+ const remaining = body [off .. ];
1673+ if (partial_count ) | cnt | {
1674+ break :blk remaining [0.. @min (cnt , remaining .len )];
1675+ }
1676+ break :blk remaining ;
1677+ } else body ;
1678+ const section_tag = if (partial_offset ) | off | blk : {
1679+ break :blk std .fmt .allocPrint (self .allocator , "BODY[TEXT]<{d}>" , .{off }) catch "BODY[TEXT]" ;
1680+ } else @as ([]const u8 , "BODY[TEXT]" );
1681+ defer if (partial_offset != null ) {
1682+ if (! std .mem .eql (u8 , section_tag , "BODY[TEXT]" )) self .allocator .free (section_tag );
1683+ };
1684+ const resp = try std .fmt .allocPrint (self .allocator , "* {d} FETCH (UID {d} FLAGS ({s}) RFC822.SIZE {d} INTERNALDATE \" {s}\" {s} {s} {{{d}}}\r \n {s})" , .{
1685+ seq , uid , flag_str , content .len , date_str , bs_part , section_tag , text_data .len , text_data ,
16581686 });
16591687 defer self .allocator .free (resp );
16601688 try self .writeData (resp );
@@ -1668,8 +1696,23 @@ pub const ImapSession = struct {
16681696 try self .writeData (resp );
16691697 try self .writeData ("\r \n " );
16701698 } else if (want_full_body ) {
1671- const resp = try std .fmt .allocPrint (self .allocator , "* {d} FETCH (UID {d} FLAGS ({s}) RFC822.SIZE {d} INTERNALDATE \" {s}\" {s} BODY[] {{{d}}}\r \n {s})" , .{
1672- seq , uid , flag_str , content .len , date_str , bs_part , content .len , content ,
1699+ // Apply partial fetch <offset.count> if requested
1700+ const fetch_data = if (partial_offset ) | off | blk : {
1701+ if (off >= content .len ) break :blk @as ([]const u8 , "" );
1702+ const remaining = content [off .. ];
1703+ if (partial_count ) | cnt | {
1704+ break :blk remaining [0.. @min (cnt , remaining .len )];
1705+ }
1706+ break :blk remaining ;
1707+ } else content ;
1708+ const body_tag = if (partial_offset ) | off | blk : {
1709+ break :blk std .fmt .allocPrint (self .allocator , "BODY[]<{d}>" , .{off }) catch "BODY[]" ;
1710+ } else @as ([]const u8 , "BODY[]" );
1711+ defer if (partial_offset != null ) {
1712+ if (! std .mem .eql (u8 , body_tag , "BODY[]" )) self .allocator .free (body_tag );
1713+ };
1714+ const resp = try std .fmt .allocPrint (self .allocator , "* {d} FETCH (UID {d} FLAGS ({s}) RFC822.SIZE {d} INTERNALDATE \" {s}\" {s} {s} {{{d}}}\r \n {s})" , .{
1715+ seq , uid , flag_str , content .len , date_str , bs_part , body_tag , fetch_data .len , fetch_data ,
16731716 });
16741717 defer self .allocator .free (resp );
16751718 try self .writeData (resp );
0 commit comments