1 #include "etpan_mime.h"
2 #ifndef mailmime_param_new_with_data
3 #include <libetpan/mailprivacy_tools.h>
13 time_t mail_mkgmtime(struct tm * tmp);
15 #define MAX_MESSAGE_ID 512
17 static char * generate_boundary(void)
19 char id[MAX_MESSAGE_ID];
25 // no random needed here
32 snprintf(id, MAX_MESSAGE_ID, "%.4lx%.4lx%.4lx%.4lx", value1, value2,
38 struct mailmime * part_new_empty(
39 struct mailmime_content * content,
40 struct mailmime_fields * mime_fields,
44 struct mailmime * build_info;
48 char * attr_name = NULL;
49 char * attr_value = NULL;
50 struct mailmime_parameter * param = NULL;
51 clist * parameters = NULL;
52 char *boundary = NULL;
57 mime_type = MAILMIME_SINGLE;
60 switch (content->ct_type->tp_type) {
61 case MAILMIME_TYPE_DISCRETE_TYPE:
62 mime_type = MAILMIME_SINGLE;
65 case MAILMIME_TYPE_COMPOSITE_TYPE:
66 switch (content->ct_type->tp_data.tp_composite_type->ct_type) {
67 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
68 mime_type = MAILMIME_MULTIPLE;
71 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
72 if (strcasecmp(content->ct_subtype, "rfc822") == 0)
73 mime_type = MAILMIME_MESSAGE;
75 mime_type = MAILMIME_SINGLE;
88 if (mime_type == MAILMIME_MULTIPLE) {
94 attr_name = strdup("boundary");
96 if (attr_name == NULL)
99 boundary = generate_boundary();
101 attr_value = boundary;
102 if (attr_value == NULL)
105 param = mailmime_parameter_new(attr_name, attr_value);
112 if (content->ct_parameters == NULL) {
113 parameters = clist_new();
115 if (parameters == NULL)
119 parameters = content->ct_parameters;
122 r = clist_append(parameters, param);
127 if (content->ct_parameters == NULL)
128 content->ct_parameters = parameters;
131 build_info = mailmime_new(mime_type, NULL, 0, mime_fields, content, NULL,
132 NULL, NULL, list, NULL, NULL);
133 if (build_info == NULL)
143 if (content->ct_parameters == NULL)
145 clist_free(parameters);
150 struct mailmime * get_pgp_encrypted_part(void)
152 struct mailmime * mime = NULL;
153 struct mailmime_fields * mime_fields = NULL;
154 struct mailmime_content * content = NULL;
157 content = mailmime_content_new_with_str("application/pgp-encrypted");
161 mime_fields = mailmime_fields_new_empty();
162 if (mime_fields == NULL)
165 mime = part_new_empty(content, mime_fields, 1);
171 r = mailmime_set_body_text(mime, "Version: 1\n", 10);
179 mailmime_content_free(content);
181 mailmime_fields_free(mime_fields);
188 struct mailmime * get_text_part(
189 const char * filename,
190 const char * mime_type,
196 char * disposition_name = NULL;
197 struct mailmime_fields * mime_fields = NULL;
198 struct mailmime * mime = NULL;
199 struct mailmime_content * content = NULL;
200 struct mailmime_parameter * param = NULL;
201 struct mailmime_disposition * disposition = NULL;
202 struct mailmime_mechanism * encoding = NULL;
205 if (filename != NULL) {
206 disposition_name = strdup(filename);
207 if (disposition_name == NULL)
212 encoding = mailmime_mechanism_new(encoding_type, NULL);
213 if (encoding == NULL)
218 mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
219 disposition_name, NULL, NULL, NULL, (size_t) -1);
220 if (disposition == NULL)
222 disposition_name = NULL;
224 mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
226 if (mime_fields == NULL)
231 content = mailmime_content_new_with_str(mime_type);
235 if (encoding_type != MAILMIME_MECHANISM_7BIT) {
236 param = mailmime_param_new_with_data("charset", "utf-8");
237 r = clist_append(content->ct_parameters, param);
242 mime = part_new_empty(content, mime_fields, 1);
249 r = mailmime_set_body_text(mime, (char *) text, length);
257 free(disposition_name);
259 mailmime_fields_free(mime_fields);
263 mailmime_content_free(content);
265 mailmime_parameter_free(param);
267 mailmime_disposition_free(disposition);
269 mailmime_mechanism_free(encoding);
274 struct mailmime * get_file_part(
275 const char * filename,
276 const char * mime_type,
281 char * disposition_name = NULL;
283 struct mailmime_disposition * disposition = NULL;
284 struct mailmime_mechanism * encoding = NULL;
285 struct mailmime_content * content = NULL;
286 struct mailmime * mime = NULL;
287 struct mailmime_fields * mime_fields = NULL;
290 if (filename != NULL) {
291 disposition_name = strdup(filename);
292 if (disposition_name == NULL)
297 mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
298 disposition_name, NULL, NULL, NULL, (size_t) -1);
299 if (disposition == NULL)
301 disposition_name = NULL;
303 content = mailmime_content_new_with_str(mime_type);
307 encoding_type = MAILMIME_MECHANISM_BASE64;
308 encoding = mailmime_mechanism_new(encoding_type, NULL);
309 if (encoding == NULL)
312 mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
314 if (mime_fields == NULL)
319 mime = part_new_empty(content, mime_fields, 1);
325 r = mailmime_set_body_text(mime, data, length);
332 free(disposition_name);
334 mailmime_disposition_free(disposition);
336 mailmime_mechanism_free(encoding);
338 mailmime_content_free(content);
340 mailmime_fields_free(mime_fields);
347 struct mailmime * part_multiple_new(const char *type)
349 struct mailmime_fields *mime_fields = NULL;
350 struct mailmime_content *content = NULL;
351 struct mailmime *mp = NULL;
353 mime_fields = mailmime_fields_new_empty();
354 if (mime_fields == NULL)
357 content = mailmime_content_new_with_str(type);
361 mp = part_new_empty(content, mime_fields, 0);
369 mailmime_content_free(content);
371 mailmime_fields_free(mime_fields);
376 struct mailimf_field * _new_field(
378 _new_func_t new_func,
382 void *data = new_func(value);
387 struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
389 if (result == NULL) {
394 result->fld_type = type;
395 result->fld_data.fld_return_path = data;
400 void _free_field(struct mailimf_field *field)
403 free(field->fld_data.fld_return_path);
410 _new_func_t new_func,
415 struct mailimf_field * field;
421 field = _new_field(type, new_func, value);
425 r = clist_append(list, field);
432 // http://media2.giga.de/2014/02/Image-28.jpg
434 struct mailimf_date_time * timestamp_to_etpantime(const struct tm *ts)
436 struct mailimf_date_time * result = calloc(1,
437 sizeof(struct mailimf_date_time));
444 result->dt_sec = ts->tm_sec;
445 result->dt_min = ts->tm_min;
446 result->dt_hour = ts->tm_hour;
447 result->dt_day = ts->tm_mday;
448 result->dt_month = ts->tm_mon + 1;
449 result->dt_year = ts->tm_year + 1900;
451 result->dt_zone = (int) (ts->tm_gmtoff / 36L);
456 struct tm * etpantime_to_timestamp(const struct mailimf_date_time *et)
458 struct tm * result = calloc(1, sizeof(struct tm));
465 result->tm_sec = et->dt_sec;
466 result->tm_min = et->dt_min;
467 result->tm_hour = et->dt_hour;
468 result->tm_mday = et->dt_day;
469 result->tm_mon = et->dt_month - 1;
470 result->tm_year = et->dt_year - 1900;
472 result->tm_gmtoff = 36L * (long) et->dt_zone;
477 struct mailimf_mailbox * mailbox_from_string(
482 struct mailimf_mailbox *mb = NULL;
484 char *_address = NULL;
488 _name = name ? strdup(name) : strdup("");
492 _address = strdup(address);
493 if (_address == NULL)
496 mb = mailimf_mailbox_new(_name, _address);
510 struct mailimf_field * create_optional_field(
517 struct mailimf_optional_field *optional_field = NULL;
519 _field = strdup(field);
523 _value = mailmime_encode_subject_header("utf-8", value, 0);
527 optional_field = mailimf_optional_field_new(_field, _value);
528 if (optional_field == NULL)
531 struct mailimf_field * result = calloc(1, sizeof(struct mailimf_field));
536 result->fld_type = MAILIMF_FIELD_OPTIONAL_FIELD;
537 result->fld_data.fld_optional_field = optional_field;
542 if (optional_field) {
543 mailimf_optional_field_free(optional_field);
553 int _append_optional_field(
560 struct mailimf_field * optional_field =
561 create_optional_field(field, value);
563 if (optional_field == NULL)
566 r = clist_append(list, optional_field);
568 mailimf_field_free(optional_field);
573 clist * _get_fields(struct mailmime * mime)
575 clist * _fieldlist = NULL;
579 if (mime->mm_data.mm_message.mm_fields &&
580 mime->mm_data.mm_message.mm_fields->fld_list) {
581 _fieldlist = mime->mm_data.mm_message.mm_fields->fld_list;
587 struct mailmime_content * _get_content(struct mailmime * mime)
589 struct mailmime_content * content = NULL;
593 if (mime->mm_data.mm_message.mm_msg_mime)
594 content = mime->mm_data.mm_message.mm_msg_mime->mm_content_type;
599 char * _get_filename(struct mailmime *mime)
601 clist * _fieldlist = NULL;
605 if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list)
606 _fieldlist = mime->mm_mime_fields->fld_list;
611 for (cur = clist_begin(_fieldlist); cur; cur = clist_next(cur)) {
612 struct mailmime_field * _field = clist_content(cur);
613 if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
614 if (_field->fld_data.fld_disposition &&
615 _field->fld_data.fld_disposition->dsp_parms) {
617 _field->fld_data.fld_disposition->dsp_parms;
619 for (cur2 = clist_begin(_parmlist); cur2; cur2 =
621 struct mailmime_disposition_parm * param =
623 if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME)
624 return param->pa_data.pa_filename;
633 bool parameter_has_value(
634 struct mailmime_content *content,
644 clist * list = content->ct_parameters;
648 for (cur = clist_begin(list); cur != NULL ; cur = clist_next(cur)) {
649 struct mailmime_parameter * param = clist_content(cur);
651 param->pa_name && strcmp(name, param->pa_name) == 0 &&
652 param->pa_value && strcmp(value, param->pa_value) == 0)
659 bool _is_multipart(struct mailmime_content *content, const char *subtype)
663 if (content->ct_type && content->ct_type->tp_type ==
664 MAILMIME_TYPE_COMPOSITE_TYPE &&
665 content->ct_type->tp_data.tp_composite_type &&
666 content->ct_type->tp_data.tp_composite_type->ct_type ==
667 MAILMIME_COMPOSITE_TYPE_MULTIPART) {
669 return content->ct_subtype &&
670 strcmp(content->ct_subtype, subtype) == 0;
678 bool _is_PGP_MIME(struct mailmime_content *content)
682 if (_is_multipart(content, "encrypted") &&
683 parameter_has_value(content, "protocol",
684 "application/pgp-encrypted"))
690 bool _is_text_part(struct mailmime_content *content, const char *subtype)
694 if (content->ct_type && content->ct_type->tp_type ==
695 MAILMIME_TYPE_DISCRETE_TYPE &&
696 content->ct_type->tp_data.tp_discrete_type &&
697 content->ct_type->tp_data.tp_discrete_type->dt_type ==
698 MAILMIME_DISCRETE_TYPE_TEXT) {
700 return content->ct_subtype &&
701 strcmp(content->ct_subtype, subtype) == 0;
709 char * _get_content_type(struct mailmime_content *content)
715 if (content->ct_subtype == NULL)
718 if (content->ct_type && content->ct_type->tp_data.tp_discrete_type) {
722 switch (content->ct_type->tp_data.tp_discrete_type->dt_type) {
723 case MAILMIME_DISCRETE_TYPE_TEXT:
726 case MAILMIME_DISCRETE_TYPE_IMAGE:
729 case MAILMIME_DISCRETE_TYPE_AUDIO:
732 case MAILMIME_DISCRETE_TYPE_VIDEO:
735 case MAILMIME_DISCRETE_TYPE_APPLICATION:
736 _type = "application";
738 case MAILMIME_DISCRETE_TYPE_EXTENSION:
745 len = strlen(_type) + 1 + strlen(content->ct_subtype) + 1;
746 type = calloc(1, len);
748 // BUG: out of memory cannot be signaled
754 strcat(type, content->ct_subtype);