1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 //! Tests nested `MimeMulti`, for its building and synchronous encoding.
15
16 use ylong_http::body::{sync_impl, MimeMulti, MimeMultiEncoder, MimePart};
17
18 // A multi example in [`RFC2049`]
19 // [`RFC2049`]: https://www.rfc-editor.org/rfc/rfc2049
20 //
21 // MIME-Version: 1.0
22 // From: Nathaniel Borenstein <nsb@nsb.fv.com>
23 // To: Ned Freed <ned@innosoft.com>
24 // Date: Fri, 07 Oct 1994 16:15:05 -0700 (PDT)
25 // Subject: A multipart example
26 // Content-Type: multipart/mixed;
27 // boundary=unique-boundary-1
28 //
29 // This is the preamble area of a multipart message.
30 // Mail readers that understand multipart format
31 // should ignore this preamble.
32 //
33 // If you are reading this text, you might want to
34 // consider changing to a mail reader that understands
35 // how to properly display multipart messages.
36 //
37 // --unique-boundary-1
38 //
39 // ... Some text appears here ...
40 //
41 // [Note that the blank between the boundary and the start
42 // of the text in this part means no header fields were
43 // given and this is text in the US-ASCII character set.
44 // It could have been done with explicit typing as in the
45 // next part.]
46 //
47 // --unique-boundary-1
48 // Content-type: text/plain; charset=US-ASCII
49 //
50 // This could have been part of the previous part, but
51 // illustrates explicit versus implicit typing of body
52 // parts.
53 //
54 // --unique-boundary-1
55 // Content-Type: multipart/parallel; boundary=unique-boundary-2
56 //
57 // --unique-boundary-2
58 // Content-Type: audio/basic
59 // Content-Transfer-Encoding: base64
60 //
61 // ... base64-encoded 8000 Hz single-channel
62 // mu-law-format audio data goes here ...
63 //
64 // --unique-boundary-2
65 // Content-Type: image/jpeg
66 // Content-Transfer-Encoding: base64
67 //
68 // ... base64-encoded image data goes here ...
69 //
70 // --unique-boundary-2--
71 //
72 // --unique-boundary-1
73 // Content-type: text/enriched
74 //
75 // This is <bold><italic>enriched.</italic></bold>
76 // <smaller>as defined in RFC 1896</smaller>
77 //
78 // Isn't it
79 // <bigger><bigger>cool?</bigger></bigger>
80 //
81 // --unique-boundary-1
82 // Content-Type: message/rfc822
83 //
84 // From: (mailbox in US-ASCII)
85 // To: (address in US-ASCII)
86 // Subject: (subject in US-ASCII)
87 // Content-Type: Text/plain; charset=ISO-8859-1
88 // Content-Transfer-Encoding: Quoted-printable
89 //
90 // ... Additional text in ISO-8859-1 goes here ...
91 //
92 // --unique-boundary-1--
93
main()94 fn main() {
95 let body_text1 = "\
96 This could have been part of the previous part, but \
97 illustrates explicit versus implicit typing of body parts.\r\n"
98 .as_bytes();
99 let body_text2 = "\
100 ... base64-encoded 8000 Hz single-channel \
101 mu-law-format audio data goes here ...\r\n"
102 .as_bytes();
103 let body_text3 = "... base64-encoded image data goes here ...\r\n".as_bytes();
104
105 let body_text4 = "\
106 This is <bold><italic>enriched.</italic></bold>
107 <smaller>as defined in RFC 1896</smaller>
108
109 Isn't it
110 <bigger><bigger>cool?</bigger></bigger>
111 "
112 .as_bytes();
113
114 let body_text5 = "\
115 From: (mailbox in US-ASCII)
116 To: (address in US-ASCII)
117 Subject: (subject in US-ASCII)
118 Content-Type: Text/plain; charset=ISO-8859-1
119 Content-Transfer-Encoding: Quoted-printable
120
121 ... Additional text in ISO-8859-1 goes here ...
122 "
123 .as_bytes();
124
125 let multi = MimeMulti::builder()
126 .set_content_type(b"multipart/mixed", b"unique-boundary-1".to_vec())
127 .add_part(
128 MimePart::builder()
129 .body_from_bytes("... Some text appears here ...\r\n".as_bytes())
130 .build()
131 .unwrap(),
132 )
133 .add_part(
134 MimePart::builder()
135 .header("Content-type", "text/plain; charset=US-ASCII")
136 .body_from_bytes(body_text1)
137 .build()
138 .unwrap(),
139 )
140 .add_multi(
141 MimeMulti::builder()
142 .set_content_type(b"multipart/parallel", b"unique-boundary-2".to_vec())
143 .add_part(
144 MimePart::builder()
145 .header("Content-type", "audio/basic")
146 .header("Content-Transfer-Encoding", "base64")
147 .body_from_bytes(body_text2)
148 .build()
149 .unwrap(),
150 )
151 .add_part(
152 MimePart::builder()
153 .header("Content-type", "image/jpeg")
154 .header("Content-Transfer-Encoding", "base64")
155 .body_from_bytes(body_text3)
156 .build()
157 .unwrap(),
158 )
159 .build()
160 .unwrap(),
161 )
162 .add_part(
163 MimePart::builder()
164 .header("Content-type", "text/enriched")
165 .body_from_reader(body_text4)
166 .build()
167 .unwrap(),
168 )
169 .add_part(
170 MimePart::builder()
171 .header("Content-type", "message/rfc822")
172 .body_from_reader(body_text5)
173 .build()
174 .unwrap(),
175 )
176 .build()
177 .unwrap();
178
179 let mut multi_encoder = MimeMultiEncoder::from_multi(multi);
180 let mut buf = vec![0u8; 50];
181 let mut v_size = vec![];
182 let mut v_str = vec![];
183
184 loop {
185 let len = sync_impl::Body::data(&mut multi_encoder, &mut buf).unwrap();
186 if len == 0 {
187 break;
188 }
189 v_size.push(len);
190 v_str.extend_from_slice(&buf[..len]);
191 }
192 assert_eq!(
193 v_size,
194 vec![
195 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
196 35
197 ]
198 );
199 // Headers is a HashMap, so that sequence of iter is different.
200 println!("{}", core::str::from_utf8(&v_str).unwrap());
201 }
202