|
|
@ -790,35 +790,35 @@ int mailmime_multipart_next_parse(const char * message, size_t length, |
|
|
|
|
|
|
|
if (cur_token >= length) |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
|
|
|
|
switch(state) { |
|
|
|
|
|
|
|
switch (state) { |
|
|
|
|
|
|
|
case MULTIPART_NEXT_STATE_0: |
|
|
|
switch (message[cur_token]) { |
|
|
|
case ' ': |
|
|
|
state = MULTIPART_NEXT_STATE_0; |
|
|
|
break; |
|
|
|
state = MULTIPART_NEXT_STATE_0; |
|
|
|
break; |
|
|
|
case '\t': |
|
|
|
state = MULTIPART_NEXT_STATE_0; |
|
|
|
break; |
|
|
|
state = MULTIPART_NEXT_STATE_0; |
|
|
|
break; |
|
|
|
case '\r': |
|
|
|
state = MULTIPART_NEXT_STATE_1; |
|
|
|
break; |
|
|
|
state = MULTIPART_NEXT_STATE_1; |
|
|
|
break; |
|
|
|
case '\n': |
|
|
|
state = MULTIPART_NEXT_STATE_2; |
|
|
|
break; |
|
|
|
state = MULTIPART_NEXT_STATE_2; |
|
|
|
break; |
|
|
|
default: |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case MULTIPART_NEXT_STATE_1: |
|
|
|
switch (message[cur_token]) { |
|
|
|
case '\n': |
|
|
|
state = MULTIPART_NEXT_STATE_2; |
|
|
|
break; |
|
|
|
state = MULTIPART_NEXT_STATE_2; |
|
|
|
break; |
|
|
|
default: |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
return MAILIMF_ERROR_PARSE; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
@ -831,6 +831,7 @@ int mailmime_multipart_next_parse(const char * message, size_t length, |
|
|
|
return MAILIMF_NO_ERROR; |
|
|
|
} |
|
|
|
|
|
|
|
/* N.B. Modified to allow add enigmail memoryhole Subject header to fields. */ |
|
|
|
static int |
|
|
|
mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
size_t * indx, char * boundary, |
|
|
@ -911,13 +912,14 @@ mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
preamble_length = preamble_end - preamble_begin; |
|
|
|
|
|
|
|
part_begin = cur_token; |
|
|
|
|
|
|
|
while (1) { |
|
|
|
r = mailmime_lwsp_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
res = r; |
|
|
|
goto err; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
r = mailimf_crlf_parse(message, length, &cur_token); |
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
part_begin = cur_token; |
|
|
@ -941,7 +943,10 @@ mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
} |
|
|
|
|
|
|
|
final_part = 0; |
|
|
|
|
|
|
|
|
|
|
|
/* Go through the whole block of parts corresponding to this boundary, |
|
|
|
parse each by consuming each one and going back to the top of |
|
|
|
the loop */ |
|
|
|
while (!final_part) { |
|
|
|
size_t bp_token; |
|
|
|
struct mailmime * mime_bp; |
|
|
@ -949,7 +954,7 @@ mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
size_t data_size; |
|
|
|
struct mailimf_fields * fields; |
|
|
|
struct mailmime_fields * mime_fields; |
|
|
|
|
|
|
|
|
|
|
|
r = mailmime_body_part_dash2_transport_crlf_parse(message, length, |
|
|
|
&cur_token, boundary, &data_str, &data_size); |
|
|
|
if (r == MAILIMF_ERROR_PARSE) { |
|
|
@ -962,29 +967,44 @@ mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
|
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
bp_token = 0; |
|
|
|
|
|
|
|
r = mailimf_optional_fields_parse(data_str, data_size, |
|
|
|
|
|
|
|
struct mailimf_fields * envelope_fields = NULL; |
|
|
|
|
|
|
|
int is_memoryhole_part = 0; |
|
|
|
|
|
|
|
|
|
|
|
r = mailimf_memoryhole_fields_parse(data_str, data_size, |
|
|
|
&bp_token, &fields); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
res = r; |
|
|
|
goto free; |
|
|
|
} |
|
|
|
|
|
|
|
r = mailimf_crlf_parse(data_str, data_size, &bp_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
mailimf_fields_free(fields); |
|
|
|
res = r; |
|
|
|
goto free; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
is_memoryhole_part = 1; |
|
|
|
} |
|
|
|
else { |
|
|
|
r = mailimf_optional_fields_parse(data_str, data_size, |
|
|
|
&bp_token, &fields); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
res = r; |
|
|
|
goto free; |
|
|
|
} |
|
|
|
|
|
|
|
r = mailimf_crlf_parse(data_str, data_size, &bp_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
mailimf_fields_free(fields); |
|
|
|
res = r; |
|
|
|
goto free; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
mime_fields = NULL; |
|
|
|
r = mailmime_fields_parse(fields, &mime_fields); |
|
|
|
mailimf_fields_free(fields); |
|
|
|
|
|
|
|
/* mailimf_fields_free(fields); */ /* we don't do this now to preserve for memoryhole */ |
|
|
|
|
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
res = r; |
|
|
|
goto free; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
r = mailmime_parse_with_default(data_str, data_size, |
|
|
|
&bp_token, default_subtype, NULL, |
|
|
|
mime_fields, &mime_bp); |
|
|
@ -1006,6 +1026,8 @@ mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
goto free; |
|
|
|
} |
|
|
|
|
|
|
|
mime_bp->mm_imf_fields = fields; |
|
|
|
|
|
|
|
r = mailmime_multipart_next_parse(message, length, &cur_token); |
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
/* do nothing */ |
|
|
@ -1089,7 +1111,8 @@ mailmime_multipart_body_parse(const char * message, size_t length, |
|
|
|
|
|
|
|
enum { |
|
|
|
MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, |
|
|
|
MAILMIME_DEFAULT_TYPE_MESSAGE |
|
|
|
MAILMIME_DEFAULT_TYPE_MESSAGE, |
|
|
|
MAILMIME_DEFAULT_TYPE_RFC2822_EXTRA_HEADERS |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -1240,29 +1263,28 @@ static void remove_unparsed_mime_headers(struct mailimf_fields * fields) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
size_t * indx, int default_type, |
|
|
|
struct mailmime_content * content_type, |
|
|
|
struct mailmime_fields * mime_fields, |
|
|
|
struct mailmime ** result) |
|
|
|
{ |
|
|
|
static int mailmime_parse_with_default(const char *message, size_t length, |
|
|
|
size_t *indx, int default_type, |
|
|
|
struct mailmime_content *content_type, |
|
|
|
struct mailmime_fields *mime_fields, |
|
|
|
struct mailmime **result) { |
|
|
|
size_t cur_token; |
|
|
|
|
|
|
|
int body_type; |
|
|
|
|
|
|
|
int encoding; |
|
|
|
struct mailmime_data * body; |
|
|
|
char * boundary; |
|
|
|
struct mailimf_fields * fields; |
|
|
|
clist * list; |
|
|
|
struct mailmime * msg_mime; |
|
|
|
struct mailmime_data *body; |
|
|
|
char *boundary; |
|
|
|
struct mailimf_fields *fields; |
|
|
|
clist *list; |
|
|
|
struct mailmime *msg_mime; |
|
|
|
|
|
|
|
struct mailmime * mime; |
|
|
|
struct mailmime *mime; |
|
|
|
|
|
|
|
int r; |
|
|
|
int res; |
|
|
|
struct mailmime_data * preamble; |
|
|
|
struct mailmime_data * epilogue; |
|
|
|
struct mailmime_data *preamble; |
|
|
|
struct mailmime_data *epilogue; |
|
|
|
|
|
|
|
/* |
|
|
|
note that when this function is called, content type is always detached, |
|
|
@ -1271,23 +1293,23 @@ static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
|
|
|
|
preamble = NULL; |
|
|
|
epilogue = NULL; |
|
|
|
|
|
|
|
cur_token = * indx; |
|
|
|
|
|
|
|
cur_token = *indx; |
|
|
|
|
|
|
|
/* get content type */ |
|
|
|
|
|
|
|
if (content_type == NULL) { |
|
|
|
if (mime_fields != NULL) { |
|
|
|
clistiter * cur; |
|
|
|
|
|
|
|
for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; |
|
|
|
cur = clist_next(cur)) { |
|
|
|
struct mailmime_field * field; |
|
|
|
|
|
|
|
clistiter *cur; |
|
|
|
|
|
|
|
for (cur = clist_begin(mime_fields->fld_list); cur != NULL; |
|
|
|
cur = clist_next(cur)) { |
|
|
|
struct mailmime_field *field; |
|
|
|
|
|
|
|
field = clist_content(cur); |
|
|
|
if (field->fld_type == MAILMIME_FIELD_TYPE) { |
|
|
|
content_type = field->fld_data.fld_content; |
|
|
|
|
|
|
|
|
|
|
|
/* detach content type from list */ |
|
|
|
field->fld_data.fld_content = NULL; |
|
|
|
clist_delete(mime_fields->fld_list, cur); |
|
|
@ -1309,17 +1331,16 @@ static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { |
|
|
|
content_type = mailmime_get_content_text(); |
|
|
|
if (content_type == NULL) { |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto err; |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto err; |
|
|
|
} |
|
|
|
} |
|
|
|
else /* message */ { |
|
|
|
} else /* message */ { |
|
|
|
body_type = MAILMIME_MESSAGE; |
|
|
|
|
|
|
|
|
|
|
|
content_type = mailmime_get_content_message(); |
|
|
|
if (content_type == NULL) { |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto err; |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto err; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1333,19 +1354,19 @@ static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { |
|
|
|
case MAILMIME_COMPOSITE_TYPE_MULTIPART: |
|
|
|
boundary = mailmime_extract_boundary(content_type); |
|
|
|
|
|
|
|
|
|
|
|
if (boundary == NULL) |
|
|
|
body_type = MAILMIME_SINGLE; |
|
|
|
body_type = MAILMIME_SINGLE; |
|
|
|
else |
|
|
|
body_type = MAILMIME_MULTIPLE; |
|
|
|
body_type = MAILMIME_MULTIPLE; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case MAILMIME_COMPOSITE_TYPE_MESSAGE: |
|
|
|
|
|
|
|
if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) |
|
|
|
body_type = MAILMIME_MESSAGE; |
|
|
|
body_type = MAILMIME_MESSAGE; |
|
|
|
else |
|
|
|
body_type = MAILMIME_SINGLE; |
|
|
|
body_type = MAILMIME_SINGLE; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
@ -1365,20 +1386,19 @@ static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
encoding = mailmime_transfer_encoding_get(mime_fields); |
|
|
|
else |
|
|
|
encoding = MAILMIME_MECHANISM_8BIT; |
|
|
|
|
|
|
|
|
|
|
|
if (body_type == MAILMIME_MESSAGE) { |
|
|
|
switch (encoding) { |
|
|
|
case MAILMIME_MECHANISM_QUOTED_PRINTABLE: |
|
|
|
case MAILMIME_MECHANISM_BASE64: |
|
|
|
body_type = MAILMIME_SINGLE; |
|
|
|
break; |
|
|
|
case MAILMIME_MECHANISM_QUOTED_PRINTABLE: |
|
|
|
case MAILMIME_MECHANISM_BASE64: |
|
|
|
body_type = MAILMIME_SINGLE; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
cur_token = * indx; |
|
|
|
body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, |
|
|
|
message + cur_token, length - cur_token, |
|
|
|
NULL); |
|
|
|
|
|
|
|
cur_token = *indx; |
|
|
|
body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, message + cur_token, |
|
|
|
length - cur_token, NULL); |
|
|
|
if (body == NULL) { |
|
|
|
free(boundary); |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
@ -1392,107 +1412,109 @@ static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
fields = NULL; |
|
|
|
|
|
|
|
switch (body_type) { |
|
|
|
case MAILMIME_MESSAGE: |
|
|
|
{ |
|
|
|
struct mailmime_fields * submime_fields; |
|
|
|
|
|
|
|
r = mailimf_envelope_and_optional_fields_parse(message, length, |
|
|
|
&cur_token, &fields); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
r = mailimf_crlf_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
mailimf_fields_free(fields); |
|
|
|
res = r; |
|
|
|
case MAILMIME_MESSAGE: { |
|
|
|
struct mailmime_fields *submime_fields; |
|
|
|
|
|
|
|
r = mailimf_envelope_and_optional_fields_parse(message, length, &cur_token, |
|
|
|
&fields); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
r = mailimf_crlf_parse(message, length, &cur_token); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
mailimf_fields_free(fields); |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
submime_fields = NULL; |
|
|
|
r = mailmime_fields_parse(fields, &submime_fields); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
mailimf_fields_free(fields); |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
remove_unparsed_mime_headers(fields); |
|
|
|
|
|
|
|
r = mailmime_parse_with_default(message, length, &cur_token, |
|
|
|
MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, NULL, |
|
|
|
submime_fields, &msg_mime); |
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
/* do nothing */ |
|
|
|
} else if (r == MAILIMF_ERROR_PARSE) { |
|
|
|
mailmime_fields_free(mime_fields); |
|
|
|
msg_mime = NULL; |
|
|
|
} else { |
|
|
|
mailmime_fields_free(mime_fields); |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MAILMIME_MULTIPLE: { |
|
|
|
int default_subtype; |
|
|
|
|
|
|
|
default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; |
|
|
|
if (content_type != NULL) |
|
|
|
if (strcasecmp(content_type->ct_subtype, "digest") == 0) |
|
|
|
default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; |
|
|
|
|
|
|
|
cur_token = *indx; |
|
|
|
r = mailmime_multipart_body_parse(message, length, &cur_token, boundary, |
|
|
|
default_subtype, &list, &preamble, |
|
|
|
&epilogue); |
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
/* do nothing */ |
|
|
|
} else if (r == MAILIMF_ERROR_PARSE) { |
|
|
|
list = clist_new(); |
|
|
|
if (list == NULL) { |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
submime_fields = NULL; |
|
|
|
r = mailmime_fields_parse(fields, &submime_fields); |
|
|
|
} else { |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
free(boundary); |
|
|
|
} break; |
|
|
|
|
|
|
|
default: /* MAILMIME_SINGLE */ |
|
|
|
if (strcasecmp(content_type->ct_subtype, "rfc822-headers") == 0) { |
|
|
|
// default_subtype = MAILMIME_DEFAULT_TYPE_RFC2822_EXTRA_HEADERS; |
|
|
|
struct mailmime_fields *submime_fields; |
|
|
|
|
|
|
|
r = mailimf_envelope_and_optional_fields_parse(message, length, |
|
|
|
&cur_token, &fields); |
|
|
|
if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { |
|
|
|
mailimf_fields_free(fields); |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
remove_unparsed_mime_headers(fields); |
|
|
|
|
|
|
|
r = mailmime_parse_with_default(message, length, |
|
|
|
&cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, |
|
|
|
NULL, submime_fields, &msg_mime); |
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
/* do nothing */ |
|
|
|
} |
|
|
|
else if (r == MAILIMF_ERROR_PARSE) { |
|
|
|
mailmime_fields_free(mime_fields); |
|
|
|
msg_mime = NULL; |
|
|
|
} |
|
|
|
else { |
|
|
|
mailmime_fields_free(mime_fields); |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case MAILMIME_MULTIPLE: |
|
|
|
{ |
|
|
|
int default_subtype; |
|
|
|
|
|
|
|
default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; |
|
|
|
if (content_type != NULL) |
|
|
|
if (strcasecmp(content_type->ct_subtype, "digest") == 0) |
|
|
|
default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; |
|
|
|
|
|
|
|
cur_token = * indx; |
|
|
|
r = mailmime_multipart_body_parse(message, length, |
|
|
|
&cur_token, boundary, |
|
|
|
default_subtype, |
|
|
|
&list, &preamble, &epilogue); |
|
|
|
if (r == MAILIMF_NO_ERROR) { |
|
|
|
/* do nothing */ |
|
|
|
} |
|
|
|
else if (r == MAILIMF_ERROR_PARSE) { |
|
|
|
list = clist_new(); |
|
|
|
if (list == NULL) { |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
res = r; |
|
|
|
goto free_content; |
|
|
|
} |
|
|
|
|
|
|
|
free(boundary); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: /* MAILMIME_SINGLE */ |
|
|
|
/* do nothing */ |
|
|
|
/* else do nothing */ |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
mime = mailmime_new(body_type, message, length, |
|
|
|
mime_fields, content_type, |
|
|
|
body, preamble, /* preamble */ |
|
|
|
epilogue, /* epilogue */ |
|
|
|
list, fields, msg_mime); |
|
|
|
mime = mailmime_new(body_type, message, length, mime_fields, content_type, |
|
|
|
body, preamble, /* preamble */ |
|
|
|
epilogue, /* epilogue */ |
|
|
|
list, fields, msg_mime); |
|
|
|
if (mime == NULL) { |
|
|
|
res = MAILIMF_ERROR_MEMORY; |
|
|
|
goto free; |
|
|
|
} |
|
|
|
|
|
|
|
* result = mime; |
|
|
|
* indx = length; |
|
|
|
*result = mime; |
|
|
|
*indx = length; |
|
|
|
|
|
|
|
return MAILIMF_NO_ERROR; |
|
|
|
|
|
|
|
free: |
|
|
|
free: |
|
|
|
if (epilogue != NULL) |
|
|
|
mailmime_data_free(epilogue); |
|
|
|
if (preamble != NULL) |
|
|
@ -1500,12 +1522,12 @@ static int mailmime_parse_with_default(const char * message, size_t length, |
|
|
|
if (msg_mime != NULL) |
|
|
|
mailmime_free(msg_mime); |
|
|
|
if (list != NULL) { |
|
|
|
clist_foreach(list, (clist_func) mailmime_free, NULL); |
|
|
|
clist_foreach(list, (clist_func)mailmime_free, NULL); |
|
|
|
clist_free(list); |
|
|
|
} |
|
|
|
free_content: |
|
|
|
free_content: |
|
|
|
mailmime_content_free(content_type); |
|
|
|
err: |
|
|
|
err: |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|