Commit 98ca43a0 98ca43a049365269e4052170eba3103a8d35e20b by Sergey Poznyakoff

imap client: improve parsing of BODY[] items.

* include/mailutils/imap.h (mu_imap_fetch_body) <key>: Rename to section.
<fields>: New member.
* libproto/imap/fetch.c: Rewrite response item parser.
* mu/imap.c: Improve fetch_response_printer
1 parent 827a4ba2
...@@ -175,7 +175,8 @@ struct mu_imap_fetch_body ...@@ -175,7 +175,8 @@ struct mu_imap_fetch_body
175 int type; 175 int type;
176 size_t *partv; 176 size_t *partv;
177 size_t partc; 177 size_t partc;
178 char *key; 178 char *section;
179 mu_list_t fields;
179 char *text; 180 char *text;
180 }; 181 };
181 182
......
...@@ -86,7 +86,8 @@ _free_fetch_response (void *ptr) ...@@ -86,7 +86,8 @@ _free_fetch_response (void *ptr)
86 { 86 {
87 case MU_IMAP_FETCH_BODY: 87 case MU_IMAP_FETCH_BODY:
88 free (resp->body.partv); 88 free (resp->body.partv);
89 free (resp->body.key); 89 free (resp->body.section);
90 mu_list_destroy (&resp->body.fields);
90 free (resp->body.text); 91 free (resp->body.text);
91 break; 92 break;
92 93
...@@ -139,81 +140,94 @@ alloc_response (union mu_imap_fetch_response **resp, int type) ...@@ -139,81 +140,94 @@ alloc_response (union mu_imap_fetch_response **resp, int type)
139 return 0; 140 return 0;
140 } 141 }
141 142
142 static int 143 enum parse_response_state
143 _uid_mapper (struct imap_list_element **elt, 144 {
144 union mu_imap_fetch_response **return_resp) 145 resp_kw,
146 resp_val,
147 resp_body,
148 resp_body_section,
149 resp_skip,
150 resp_body_hlist,
151 resp_body_end
152 };
153
154 struct parse_response_env;
155
156 typedef int (*mapper_fn) (union mu_imap_fetch_response *resp,
157 struct imap_list_element *elt,
158 struct parse_response_env *env);
159
160 struct parse_response_env
145 { 161 {
162 mu_list_t result;
163 struct imap_list_element *elt;
164 enum parse_response_state state;
146 union mu_imap_fetch_response *resp; 165 union mu_imap_fetch_response *resp;
147 int rc; 166 mapper_fn mapper;
167 const char *section;
168 mu_list_t hlist;
169 int status;
170 };
171
172
173 static int
174 _uid_mapper (union mu_imap_fetch_response *resp,
175 struct imap_list_element *elt,
176 struct parse_response_env *parse_env)
177 {
148 char *p; 178 char *p;
149 size_t uid; 179 size_t uid;
150 180
151 if (elt[1]->type != imap_eltype_string) 181 if (elt->type != imap_eltype_string)
152 return MU_ERR_FAILURE; 182 return MU_ERR_FAILURE;
153 uid = strtoul (elt[1]->v.string, &p, 0); 183 uid = strtoul (elt->v.string, &p, 0);
154 if (*p) 184 if (*p)
155 return MU_ERR_FAILURE; 185 return MU_ERR_FAILURE;
156 rc = alloc_response (&resp, MU_IMAP_FETCH_UID);
157 if (rc)
158 return rc;
159 resp->uid.uid = uid; 186 resp->uid.uid = uid;
160 *return_resp = resp;
161 return 0; 187 return 0;
162 } 188 }
163 189
164 static int 190 static int
165 _size_mapper (struct imap_list_element **elt, 191 _size_mapper (union mu_imap_fetch_response *resp,
166 union mu_imap_fetch_response **return_resp) 192 struct imap_list_element *elt,
193 struct parse_response_env *parse_env)
167 { 194 {
168 union mu_imap_fetch_response *resp;
169 int rc;
170 char *p; 195 char *p;
171 size_t size; 196 size_t size;
172 197
173 if (elt[1]->type != imap_eltype_string) 198 if (elt->type != imap_eltype_string)
174 return MU_ERR_FAILURE; 199 return MU_ERR_FAILURE;
175 size = strtoul (elt[1]->v.string, &p, 0); 200 size = strtoul (elt->v.string, &p, 0);
176 if (*p) 201 if (*p)
177 return MU_ERR_FAILURE; 202 return MU_ERR_FAILURE;
178 rc = alloc_response (&resp, MU_IMAP_FETCH_RFC822_SIZE);
179 if (rc)
180 return rc;
181 resp->rfc822_size.size = size; 203 resp->rfc822_size.size = size;
182 *return_resp = resp;
183 return 0; 204 return 0;
184 } 205 }
185 206
186 static int 207 static int
187 _body_mapper (struct imap_list_element **elt, 208 _body_mapper (union mu_imap_fetch_response *resp,
188 union mu_imap_fetch_response **return_resp) 209 struct imap_list_element *elt,
210 struct parse_response_env *parse_env)
189 { 211 {
190 union mu_imap_fetch_response *resp; 212 const char *section, *p;
191 int rc;
192 char *section, *p;
193 size_t partc = 0; 213 size_t partc = 0;
194 size_t *partv = NULL; 214 size_t *partv = NULL;
195 215
196 if (elt[1]->type != imap_eltype_string) 216 if (elt->type != imap_eltype_string)
197 return MU_ERR_FAILURE; 217 return MU_ERR_FAILURE;
198 rc = alloc_response (&resp, MU_IMAP_FETCH_BODY);
199 if (rc)
200 return rc;
201 218
202 section = strchr (elt[0]->v.string, '['); 219 section = parse_env->section;
203 if (section) 220 if (section)
204 { 221 {
205 p = section; 222 p = section;
206 while (1) 223 while (mu_isdigit (*p))
207 { 224 {
225 partc++;
208 p = strchr (p, '.'); 226 p = strchr (p, '.');
209 if (*p) 227 if (p)
210 { 228 {
211 p++; 229 p++;
212 if (mu_isdigit (p[1])) 230 continue;
213 {
214 partc++;
215 continue;
216 }
217 } 231 }
218 232
219 break; 233 break;
...@@ -222,6 +236,16 @@ _body_mapper (struct imap_list_element **elt, ...@@ -222,6 +236,16 @@ _body_mapper (struct imap_list_element **elt,
222 else 236 else
223 p = NULL; 237 p = NULL;
224 238
239 if (p)
240 {
241 resp->body.section = strdup (p);
242 if (!resp->body.section)
243 {
244 free (resp);
245 return ENOMEM;
246 }
247 }
248
225 if (partc) 249 if (partc)
226 { 250 {
227 size_t i; 251 size_t i;
...@@ -237,51 +261,33 @@ _body_mapper (struct imap_list_element **elt, ...@@ -237,51 +261,33 @@ _body_mapper (struct imap_list_element **elt,
237 resp->body.partc = partc; 261 resp->body.partc = partc;
238 resp->body.partv = partv; 262 resp->body.partv = partv;
239 263
240 if (p && *p) 264 resp->body.fields = parse_env->hlist;
241 { 265 parse_env->hlist = NULL;
242 size_t len = strlen (p);
243 resp->body.key = malloc (len);
244 if (!resp->body.key)
245 {
246 free (resp->body.partv);
247 free (resp);
248 return ENOMEM;
249 }
250 len--;
251 memcpy (resp->body.key, p, len);
252 resp->body.key[len] = 0;
253 }
254 266
255 resp->body.text = strdup (elt[1]->v.string); 267 resp->body.text = strdup (elt->v.string);
256 if (!resp->body.text) 268 if (!resp->body.text)
257 { 269 {
258 free (resp->body.key); 270 free (resp->body.section);
259 free (resp->body.partv); 271 free (resp->body.partv);
260 free (resp); 272 free (resp);
261 return ENOMEM; 273 return ENOMEM;
262 } 274 }
263 *return_resp = resp;
264 return 0; 275 return 0;
265 } 276 }
266 277
267 static int 278 static int
268 _rfc822_mapper (const char *key, struct imap_list_element *elt, 279 _rfc822_mapper (union mu_imap_fetch_response *resp,
269 union mu_imap_fetch_response **return_resp) 280 struct imap_list_element *elt,
281 struct parse_response_env *parse_env)
270 { 282 {
271 union mu_imap_fetch_response *resp;
272 int rc;
273
274 if (elt->type != imap_eltype_string) 283 if (elt->type != imap_eltype_string)
275 return MU_ERR_FAILURE; 284 return MU_ERR_FAILURE;
276 rc = alloc_response (&resp, MU_IMAP_FETCH_BODY);
277 if (rc)
278 return rc;
279 285
280 resp->body.partc = 0; 286 resp->body.partc = 0;
281 resp->body.partv = NULL; 287 resp->body.partv = NULL;
282 288
283 resp->body.key = strdup (key); 289 resp->body.section = strdup (parse_env->section);
284 if (!resp->body.key) 290 if (!resp->body.section)
285 { 291 {
286 free (resp); 292 free (resp);
287 return ENOMEM; 293 return ENOMEM;
...@@ -290,74 +296,66 @@ _rfc822_mapper (const char *key, struct imap_list_element *elt, ...@@ -290,74 +296,66 @@ _rfc822_mapper (const char *key, struct imap_list_element *elt,
290 resp->body.text = strdup (elt->v.string); 296 resp->body.text = strdup (elt->v.string);
291 if (!resp->body.text) 297 if (!resp->body.text)
292 { 298 {
293 free (resp->body.key); 299 free (resp->body.section);
294 free (resp->body.partv); 300 free (resp->body.partv);
295 free (resp); 301 free (resp);
296 return ENOMEM; 302 return ENOMEM;
297 } 303 }
298 *return_resp = resp;
299 return 0; 304 return 0;
300 } 305 }
301 306
302 static int 307 static int
303 _rfc822_header_mapper (struct imap_list_element **elt, 308 _rfc822_header_mapper (union mu_imap_fetch_response *resp,
304 union mu_imap_fetch_response **return_resp) 309 struct imap_list_element *elt,
310 struct parse_response_env *parse_env)
305 { 311 {
306 return _rfc822_mapper ("HEADER", elt[1], return_resp); 312 parse_env->section = "HEADER";
313 return _rfc822_mapper (resp, elt, parse_env);
307 } 314 }
308 315
309 static int 316 static int
310 _rfc822_text_mapper (struct imap_list_element **elt, 317 _rfc822_text_mapper (union mu_imap_fetch_response *resp,
311 union mu_imap_fetch_response **return_resp) 318 struct imap_list_element *elt,
319 struct parse_response_env *parse_env)
312 { 320 {
313 return _rfc822_mapper ("TEXT", elt[1], return_resp); 321 parse_env->section = "TEXT";
322 return _rfc822_mapper (resp, elt, parse_env);
314 } 323 }
315 324
316 static int 325 static int
317 _flags_mapper (struct imap_list_element **elt, 326 _flags_mapper (union mu_imap_fetch_response *resp,
318 union mu_imap_fetch_response **return_resp) 327 struct imap_list_element *elt,
328 struct parse_response_env *parse_env)
319 { 329 {
320 union mu_imap_fetch_response *resp; 330 if (elt->type != imap_eltype_list)
321 int rc;
322 int flags;
323
324 if (elt[1]->type != imap_eltype_list)
325 return MU_ERR_FAILURE; 331 return MU_ERR_FAILURE;
326 if (_mu_imap_collect_flags (elt[1], &flags)) 332 if (_mu_imap_collect_flags (elt, &resp->flags.flags))
327 return MU_ERR_FAILURE; 333 return MU_ERR_FAILURE;
328
329 rc = alloc_response (&resp, MU_IMAP_FETCH_FLAGS);
330 if (rc)
331 return rc;
332 resp->flags.flags = flags;
333 *return_resp = resp;
334 return 0; 334 return 0;
335 } 335 }
336 336
337 static int 337 static int
338 _date_mapper (struct imap_list_element **elt, 338 _date_mapper (union mu_imap_fetch_response *resp,
339 union mu_imap_fetch_response **return_resp) 339 struct imap_list_element *elt,
340 struct parse_response_env *parse_env)
340 { 341 {
341 union mu_imap_fetch_response *resp;
342 int rc;
343 const char *p; 342 const char *p;
344 struct tm tm; 343 struct tm tm;
345 struct mu_timezone tz; 344 struct mu_timezone tz;
346 345
347 if (elt[1]->type != imap_eltype_string) 346 if (elt->type != imap_eltype_string)
348 return MU_ERR_FAILURE; 347 return MU_ERR_FAILURE;
349 p = elt[1]->v.string; 348 p = elt->v.string;
350 if (mu_parse_imap_date_time (&p, &tm, &tz)) 349 if (mu_parse_imap_date_time (&p, &tm, &tz))
351 return MU_ERR_FAILURE; 350 return MU_ERR_FAILURE;
352 rc = alloc_response (&resp, MU_IMAP_FETCH_INTERNALDATE);
353 if (rc)
354 return rc;
355 resp->internaldate.tm = tm; 351 resp->internaldate.tm = tm;
356 resp->internaldate.tz = tz; 352 resp->internaldate.tz = tz;
357 *return_resp = resp;
358 return 0; 353 return 0;
359 } 354 }
360 355
356 /* FIXME */
357 #define _bodystructure_mapper NULL
358
361 struct fill_env 359 struct fill_env
362 { 360 {
363 struct mu_imap_fetch_envelope *envelope; 361 struct mu_imap_fetch_envelope *envelope;
...@@ -524,23 +522,17 @@ _fill_response (void *item, void *data) ...@@ -524,23 +522,17 @@ _fill_response (void *item, void *data)
524 } 522 }
525 523
526 static int 524 static int
527 _envelope_mapper (struct imap_list_element **elt, 525 _envelope_mapper (union mu_imap_fetch_response *resp,
528 union mu_imap_fetch_response **return_resp) 526 struct imap_list_element *elt,
527 struct parse_response_env *parse_env)
529 { 528 {
530 union mu_imap_fetch_response *resp;
531 int rc;
532 struct fill_env env; 529 struct fill_env env;
533 530
534 if (elt[1]->type != imap_eltype_list) 531 if (elt->type != imap_eltype_list)
535 return MU_ERR_FAILURE; 532 return MU_ERR_FAILURE;
536 rc = alloc_response (&resp, MU_IMAP_FETCH_ENVELOPE);
537 if (rc)
538 return rc;
539 env.envelope = &resp->envelope; 533 env.envelope = &resp->envelope;
540 env.n = 0; 534 env.n = 0;
541 mu_list_foreach (elt[1]->v.list, _fill_response, &env); 535 mu_list_foreach (elt->v.list, _fill_response, &env);
542
543 *return_resp = resp;
544 return 0; 536 return 0;
545 } 537 }
546 538
...@@ -548,81 +540,146 @@ struct mapper_tab ...@@ -548,81 +540,146 @@ struct mapper_tab
548 { 540 {
549 char *name; 541 char *name;
550 size_t size; 542 size_t size;
551 int prefix; 543 int type;
552 int (*mapper) (struct imap_list_element **, union mu_imap_fetch_response **); 544 mapper_fn mapper;
553 }; 545 };
554 546
555 static struct mapper_tab mapper_tab[] = { 547 static struct mapper_tab mapper_tab[] = {
556 #define S(s) s, (sizeof (s) - 1) 548 #define S(s) s, (sizeof (s) - 1)
557 { S("BODYSTRUCTURE"), 0, }, 549 { S("BODYSTRUCTURE"), },
558 { S("BODY["), 1, _body_mapper }, 550 { S("BODY"), MU_IMAP_FETCH_BODY, _body_mapper },
559 { S("BODY"), 0, _body_mapper }, 551 { S("ENVELOPE"), MU_IMAP_FETCH_ENVELOPE, _envelope_mapper },
560 { S("ENVELOPE"), 0, _envelope_mapper }, 552 { S("FLAGS"), MU_IMAP_FETCH_FLAGS, _flags_mapper },
561 { S("FLAGS"), 0, _flags_mapper }, 553 { S("INTERNALDATE"), MU_IMAP_FETCH_INTERNALDATE, _date_mapper },
562 { S("INTERNALDATE"), 0, _date_mapper }, 554 { S("RFC822"), MU_IMAP_FETCH_BODY, _body_mapper},
563 { S("RFC822"), 0, _body_mapper}, 555 { S("RFC822.HEADER"), MU_IMAP_FETCH_BODY, _rfc822_header_mapper },
564 { S("RFC822.HEADER"), 0, _rfc822_header_mapper }, 556 { S("RFC822.SIZE"), MU_IMAP_FETCH_RFC822_SIZE, _size_mapper },
565 { S("RFC822.SIZE"), 0, _size_mapper }, 557 { S("RFC822.TEXT"), MU_IMAP_FETCH_BODY, _rfc822_text_mapper },
566 { S("RFC822.TEXT"), 0, _rfc822_text_mapper }, 558 { S("UID"), MU_IMAP_FETCH_UID, _uid_mapper },
567 { S("UID"), 0, _uid_mapper },
568 #undef S 559 #undef S
569 { NULL } 560 { NULL }
570 }; 561 };
571 562
572 static int 563 static int
573 _fetch_mapper (void **itmv, size_t itmc, void *call_data) 564 _extract_string (void **itmv, size_t itmc, void *call_data)
574 { 565 {
575 int *status = call_data; 566 struct imap_list_element *elt = itmv[0];
576 struct mapper_tab *mt; 567 if (elt->type != imap_eltype_string)
577 struct imap_list_element *elt[2]; 568 return MU_LIST_MAP_SKIP;
578 char *kw; 569 itmv[0] = elt->v.string;
579 size_t kwlen; 570 return 0;
580 union mu_imap_fetch_response *resp; 571 }
581 572
582 elt[0] = itmv[0]; 573 static int
583 elt[1] = itmv[1]; 574 _fetch_fold (void *item, void *data)
584 575 {
585 if (elt[0]->type != imap_eltype_string) 576 struct imap_list_element *elt = item;
586 { 577 struct parse_response_env *env = data;
587 *status = MU_ERR_FAILURE; 578
588 return MU_LIST_MAP_STOP|MU_LIST_MAP_SKIP; 579 switch (env->state)
589 }
590 kw = elt[0]->v.string;
591 kwlen = strlen (kw);
592 for (mt = mapper_tab; mt->name; mt++)
593 { 580 {
594 if (mt->prefix) 581 case resp_kw:
582 {
583 int rc;
584 char *kw;
585 size_t kwlen;
586 struct mapper_tab *mt;
587
588 if (elt->type != imap_eltype_string)
589 {
590 env->status = MU_ERR_FAILURE;
591 return MU_ERR_FAILURE;
592 }
593 kw = elt->v.string;
594 kwlen = strlen (kw);
595 for (mt = mapper_tab; mt->name; mt++)
596 {
597 if (mt->size == kwlen && memcmp (mt->name, kw, kwlen) == 0)
598 break;
599 }
600
601 if (!mt->name)
602 {
603 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE9,
604 ("ignoring unknown FETCH item '%s'", kw));
605 env->state = resp_skip;
606 return 0;
607 }
608
609 env->mapper = mt->mapper;
610 rc = alloc_response (&env->resp, mt->type);
611 if (rc)
612 {
613 env->status = rc;
614 return MU_ERR_FAILURE;
615 }
616 env->state = mt->type == MU_IMAP_FETCH_BODY ? resp_body : resp_val;
617 break;
618 }
619
620 case resp_val:
621 if (env->mapper)
595 { 622 {
596 if (mt->size >= kwlen && memcmp (mt->name, kw, kwlen) == 0) 623 int rc = env->mapper (env->resp, elt, env);
597 break; 624 if (rc)
625 _free_fetch_response (env->resp);
626 else
627 mu_list_append (env->result, env->resp);
598 } 628 }
599 else if (mt->size == kwlen && memcmp (mt->name, kw, kwlen) == 0) 629 env->resp = NULL;
600 break; 630 mu_list_destroy (&env->hlist);
601 } 631 env->state = resp_kw;
602 632 break;
603 if (!mt->name) 633
604 { 634 case resp_body:
605 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE9, 635 if (_mu_imap_list_element_is_string (elt, "["))
606 ("ignoring unknown FETCH item '%s'", kw)); 636 env->state = resp_body_section;
607 return MU_LIST_MAP_SKIP; 637 else
608 }
609
610 if (mt->mapper)
611 {
612 int rc = mt->mapper (elt, &resp);
613 if (rc == 0)
614 { 638 {
615 itmv[0] = resp; 639 env->mapper = _bodystructure_mapper;
616 return MU_LIST_MAP_OK; 640 env->state = resp_val;
617 } 641 }
642 break;
643
644 case resp_body_section:
645 if (elt->type != imap_eltype_string)
646 {
647 env->status = MU_ERR_PARSE;
648 return MU_ERR_FAILURE;
649 }
650 else if (strncmp (elt->v.string, "HEADER.FIELDS", 13) == 0)
651 env->state = resp_body_hlist;
618 else 652 else
653 env->state = resp_body_end;
654 env->section = elt->v.string;
655 break;
656
657 case resp_skip:
658 mu_list_destroy (&env->hlist);
659 env->state = resp_kw;
660 break;
661
662 case resp_body_hlist:
663 if (elt->type != imap_eltype_list)
619 { 664 {
620 *status = rc; 665 env->status = MU_ERR_PARSE;
621 return MU_LIST_MAP_STOP|MU_LIST_MAP_SKIP; 666 return MU_ERR_FAILURE;
622 } 667 }
623 } 668 mu_list_map (elt->v.list, _extract_string, NULL, 1, &env->hlist);
669 env->state = resp_body_end;
670 break;
624 671
625 return MU_LIST_MAP_SKIP; 672 case resp_body_end:
673 if (_mu_imap_list_element_is_string (elt, "]"))
674 env->state = resp_val;
675 else
676 {
677 env->status = MU_ERR_PARSE;
678 return MU_ERR_FAILURE;
679 }
680 }
681
682 return 0;
626 } 683 }
627 684
628 int 685 int
...@@ -630,7 +687,8 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list) ...@@ -630,7 +687,8 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list)
630 { 687 {
631 mu_list_t result; 688 mu_list_t result;
632 int status; 689 int status;
633 690 struct parse_response_env env;
691
634 status = mu_list_create (&result); 692 status = mu_list_create (&result);
635 if (status) 693 if (status)
636 { 694 {
...@@ -639,11 +697,14 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list) ...@@ -639,11 +697,14 @@ _mu_imap_parse_fetch_response (mu_list_t input, mu_list_t *result_list)
639 return 1; 697 return 1;
640 } 698 }
641 mu_list_set_destroy_item (result, _free_fetch_response); 699 mu_list_set_destroy_item (result, _free_fetch_response);
642 mu_list_map (input, _fetch_mapper, &status, 2, &result); 700 memset (&env, 0, sizeof (env));
643 if (status) 701
702 env.result = result;
703 mu_list_foreach (input, _fetch_fold, &env);
704 if (env.status)
644 mu_list_destroy (&result); 705 mu_list_destroy (&result);
645 else 706 else
646 *result_list = result; 707 *result_list = result;
647 708 mu_list_destroy (&env.hlist);
648 return status; 709 return status;
649 } 710 }
......
...@@ -241,17 +241,19 @@ fetch_response_printer (void *item, void *data) ...@@ -241,17 +241,19 @@ fetch_response_printer (void *item, void *data)
241 switch (resp->type) 241 switch (resp->type)
242 { 242 {
243 case MU_IMAP_FETCH_BODY: 243 case MU_IMAP_FETCH_BODY:
244 mu_stream_printf (str, "BODY [%s]", resp->body.key); 244 mu_stream_printf (str, "BODY [");
245 if (resp->body.partv) 245 if (resp->body.partv)
246 { 246 {
247 size_t i; 247 size_t i;
248 248
249 mu_stream_printf (str, ", part: ");
250 for (i = 0; i < resp->body.partc; i++) 249 for (i = 0; i < resp->body.partc; i++)
251 mu_stream_printf (str, "%lu.", 250 mu_stream_printf (str, "%lu.",
252 (unsigned long) resp->body.partv[i]); 251 (unsigned long) resp->body.partv[i]);
253 } 252 }
254 mu_stream_printf (str, "\nBEGIN%s\nEND\n", resp->body.text); 253 if (resp->body.section)
254 mu_stream_printf (str, "%s", resp->body.section);
255 mu_stream_printf (str, "]");
256 mu_stream_printf (str, "\nBEGIN\n%s\nEND\n", resp->body.text);
255 break; 257 break;
256 258
257 case MU_IMAP_FETCH_BODYSTRUCTURE: 259 case MU_IMAP_FETCH_BODYSTRUCTURE:
......