@@ -942,6 +942,65 @@ fn strip_trailing_crlf(raw_data: &[u8], ix_start: usize, mut ix: usize) -> usize
942942 ix
943943}
944944
945+ fn parse_multipart (
946+ raw_data : & [ u8 ] ,
947+ ix_body : usize ,
948+ boundary : String ,
949+ in_multipart_digest : bool ,
950+ ) -> Result < ( Vec < ParsedMail < ' _ > > , usize ) , MailParseError > {
951+ let mut subparts = Vec :: new ( ) ;
952+ let mut ix_body_end = ix_body;
953+
954+ if let Some ( ix_boundary_start) =
955+ find_from_u8_line_prefix ( raw_data, ix_body, boundary. as_bytes ( ) )
956+ {
957+ ix_body_end = strip_trailing_crlf ( raw_data, ix_body, ix_boundary_start) ;
958+ let mut ix_boundary_end = ix_boundary_start + boundary. len ( ) ;
959+ while let Some ( ix_part_start) =
960+ find_from_u8 ( raw_data, ix_boundary_end, b"\n " ) . map ( |v| v + 1 )
961+ {
962+ let ix_part_boundary_start =
963+ find_from_u8_line_prefix ( raw_data, ix_part_start, boundary. as_bytes ( ) ) ;
964+ let ix_part_end = ix_part_boundary_start
965+ . map ( |x| strip_trailing_crlf ( raw_data, ix_part_start, x) )
966+ // if there is no terminating boundary, assume the part end is the end of the email
967+ . unwrap_or ( raw_data. len ( ) ) ;
968+
969+ subparts. push ( parse_mail_recursive (
970+ & raw_data[ ix_part_start..ix_part_end] ,
971+ in_multipart_digest,
972+ ) ?) ;
973+ ix_boundary_end = ix_part_boundary_start
974+ . map ( |x| x + boundary. len ( ) )
975+ . unwrap_or ( raw_data. len ( ) ) ;
976+ if ix_boundary_end + 2 > raw_data. len ( )
977+ || ( raw_data[ ix_boundary_end] == b'-' && raw_data[ ix_boundary_end + 1 ] == b'-' )
978+ {
979+ break ;
980+ }
981+ }
982+ }
983+ Ok ( ( subparts, ix_body_end) )
984+ }
985+
986+ fn parse_subparts < ' a > (
987+ raw_data : & ' a [ u8 ] ,
988+ ix_body : usize ,
989+ ctype : & ' _ ParsedContentType ,
990+ ) -> Result < ( Vec < ParsedMail < ' a > > , & ' a [ u8 ] ) , MailParseError > {
991+ if raw_data. len ( ) > ix_body
992+ && ctype. mimetype . starts_with ( "multipart" )
993+ && let Some ( boundary) = ctype. params . get ( "boundary" )
994+ {
995+ let boundary = String :: from ( "--" ) + boundary;
996+ let in_multipart_digest = ctype. mimetype == "multipart/digest" ;
997+ let ( subparts, ix_body_end) =
998+ parse_multipart ( raw_data, ix_body, boundary, in_multipart_digest) ?;
999+ return Ok ( ( subparts, & raw_data[ ix_body..ix_body_end] ) ) ;
1000+ }
1001+ Ok ( ( Vec :: new ( ) , & raw_data[ ix_body..] ) )
1002+ }
1003+
9451004fn parse_mail_recursive (
9461005 raw_data : & [ u8 ] ,
9471006 in_multipart_digest : bool ,
@@ -953,46 +1012,7 @@ fn parse_mail_recursive(
9531012 . map ( parse_content_type)
9541013 . unwrap_or_else ( || ParsedContentType :: default_conditional ( in_multipart_digest) ) ;
9551014
956- let mut subparts = Vec :: new ( ) ;
957- let mut body_bytes = & raw_data[ ix_body..] ;
958-
959- if ctype. mimetype . starts_with ( "multipart/" )
960- && let Some ( boundary) = ctype. params . get ( "boundary" )
961- && raw_data. len ( ) > ix_body
962- {
963- let boundary = String :: from ( "--" ) + boundary;
964- let in_multipart_digest = ctype. mimetype == "multipart/digest" ;
965- if let Some ( ix_boundary_start) =
966- find_from_u8_line_prefix ( raw_data, ix_body, boundary. as_bytes ( ) )
967- {
968- let ix_body_end = strip_trailing_crlf ( raw_data, ix_body, ix_boundary_start) ;
969- body_bytes = & raw_data[ ix_body..ix_body_end] ;
970- let mut ix_boundary_end = ix_boundary_start + boundary. len ( ) ;
971- while let Some ( ix_part_start) =
972- find_from_u8 ( raw_data, ix_boundary_end, b"\n " ) . map ( |v| v + 1 )
973- {
974- let ix_part_boundary_start =
975- find_from_u8_line_prefix ( raw_data, ix_part_start, boundary. as_bytes ( ) ) ;
976- let ix_part_end = ix_part_boundary_start
977- . map ( |x| strip_trailing_crlf ( raw_data, ix_part_start, x) )
978- // if there is no terminating boundary, assume the part end is the end of the email
979- . unwrap_or ( raw_data. len ( ) ) ;
980-
981- subparts. push ( parse_mail_recursive (
982- & raw_data[ ix_part_start..ix_part_end] ,
983- in_multipart_digest,
984- ) ?) ;
985- ix_boundary_end = ix_part_boundary_start
986- . map ( |x| x + boundary. len ( ) )
987- . unwrap_or ( raw_data. len ( ) ) ;
988- if ix_boundary_end + 2 > raw_data. len ( )
989- || ( raw_data[ ix_boundary_end] == b'-' && raw_data[ ix_boundary_end + 1 ] == b'-' )
990- {
991- break ;
992- }
993- }
994- }
995- }
1015+ let ( subparts, body_bytes) = parse_subparts ( raw_data, ix_body, & ctype) ?;
9961016
9971017 Ok ( ParsedMail {
9981018 raw_bytes : raw_data,
0 commit comments