#include #include #include #include static char * generate_boundary(const char * boundary_prefix); static struct mailmime * get_text_part(const char * mime_type, const char * text, size_t length, int encoding_type); static struct mailimf_fields * build_fields(void) { struct mailimf_fields * fields; struct mailimf_field * f; clist * list; struct mailimf_from * from; struct mailimf_to * to; struct mailimf_mailbox * mb; struct mailimf_address * addr; struct mailimf_mailbox_list * mb_list; struct mailimf_address_list * addr_list; clist * fields_list; /* build headers */ fields_list = clist_new(); /* build header 'From' */ list = clist_new(); mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), strdup("dinh.viet.hoa@foobaremail.com")); clist_append(list, mb); mb_list = mailimf_mailbox_list_new(list); from = mailimf_from_new(mb_list); f = mailimf_field_new(MAILIMF_FIELD_FROM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); clist_append(fields_list, f); /* build header To */ list = clist_new(); mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), strdup("dinh.viet.hoa@foobaremail.com")); addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); clist_append(list, addr); addr_list = mailimf_address_list_new(list); to = mailimf_to_new(addr_list); f = mailimf_field_new(MAILIMF_FIELD_TO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); clist_append(fields_list, f); fields = mailimf_fields_new(fields_list); return fields; } static struct mailmime * part_new_empty(struct mailmime_content * content, struct mailmime_fields * mime_fields, const char * boundary_prefix, int force_single) { struct mailmime * build_info; clist * list; int r; int mime_type; list = NULL; if (force_single) { mime_type = MAILMIME_SINGLE; } else { switch (content->ct_type->tp_type) { case MAILMIME_TYPE_DISCRETE_TYPE: mime_type = MAILMIME_SINGLE; break; case MAILMIME_TYPE_COMPOSITE_TYPE: switch (content->ct_type->tp_data.tp_composite_type->ct_type) { case MAILMIME_COMPOSITE_TYPE_MULTIPART: mime_type = MAILMIME_MULTIPLE; break; case MAILMIME_COMPOSITE_TYPE_MESSAGE: if (strcasecmp(content->ct_subtype, "rfc822") == 0) mime_type = MAILMIME_MESSAGE; else mime_type = MAILMIME_SINGLE; break; default: goto err; } break; default: goto err; } } if (mime_type == MAILMIME_MULTIPLE) { char * attr_name; char * attr_value; struct mailmime_parameter * param; clist * parameters; char * boundary; list = clist_new(); if (list == NULL) goto err; attr_name = strdup("boundary"); boundary = generate_boundary(boundary_prefix); attr_value = boundary; if (attr_name == NULL) { free(attr_name); goto free_list; } param = mailmime_parameter_new(attr_name, attr_value); if (param == NULL) { free(attr_value); free(attr_name); goto free_list; } if (content->ct_parameters == NULL) { parameters = clist_new(); if (parameters == NULL) { mailmime_parameter_free(param); goto free_list; } } else parameters = content->ct_parameters; r = clist_append(parameters, param); if (r != 0) { clist_free(parameters); mailmime_parameter_free(param); goto free_list; } if (content->ct_parameters == NULL) content->ct_parameters = parameters; } build_info = mailmime_new(mime_type, NULL, 0, mime_fields, content, NULL, NULL, NULL, list, NULL, NULL); if (build_info == NULL) { clist_free(list); return NULL; } return build_info; free_list: clist_free(list); err: return NULL; } static struct mailmime * get_text_part(const char * mime_type, const char * text, size_t length, int encoding_type) { struct mailmime_fields * mime_fields; struct mailmime * mime; struct mailmime_content * content; struct mailmime_parameter * param; struct mailmime_disposition * disposition; struct mailmime_mechanism * encoding; encoding = mailmime_mechanism_new(encoding_type, NULL); disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE, NULL, NULL, NULL, NULL, (size_t) -1); mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL, disposition, NULL); content = mailmime_content_new_with_str(mime_type); param = mailmime_param_new_with_data("charset", "utf-8"); clist_append(content->ct_parameters, param); mime = part_new_empty(content, mime_fields, NULL, 1); mailmime_set_body_text(mime, (char *) text, length); return mime; } #define TEXT "You'll find a file as attachment" static struct mailmime * get_plain_text_part(void) { int mechanism; mechanism = MAILMIME_MECHANISM_QUOTED_PRINTABLE; return get_text_part("text/plain", TEXT, sizeof(TEXT) - 1, mechanism); } static struct mailmime * get_file_part(const char * filename, const char * mime_type, const char * text, size_t length) { char * disposition_name; int encoding_type; struct mailmime_disposition * disposition; struct mailmime_mechanism * encoding; struct mailmime_content * content; struct mailmime * mime; struct mailmime_fields * mime_fields; disposition_name = NULL; if (filename != NULL) { disposition_name = strdup(filename); } disposition = mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, disposition_name, NULL, NULL, NULL, (size_t) -1); content = mailmime_content_new_with_str(mime_type); encoding_type = MAILMIME_MECHANISM_BASE64; encoding = mailmime_mechanism_new(encoding_type, NULL); mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL, disposition, NULL); mime = part_new_empty(content, mime_fields, NULL, 1); mailmime_set_body_text(mime, (char *) text, length); return mime; } #define FILEDATA "SOME-IMAGE-DATA" static struct mailmime * get_sample_file_part(void) { struct mailmime * part; part = get_file_part("file-data.jpg", "image/jpeg", FILEDATA, sizeof(FILEDATA) - 1); return part; } #define MAX_MESSAGE_ID 512 static char * generate_boundary(const char * boundary_prefix) { char id[MAX_MESSAGE_ID]; time_t now; char name[MAX_MESSAGE_ID]; long value; now = time(NULL); #ifndef WIN32 value = random(); gethostname(name, MAX_MESSAGE_ID); #else value = now; strcpy(name, "WINDOWS"); #endif if (boundary_prefix == NULL) boundary_prefix = ""; snprintf(id, MAX_MESSAGE_ID, "%s%llx_%lx_%x", boundary_prefix, (long long)now, value, getpid()); return strdup(id); } static struct mailmime * part_multiple_new(const char * type, const char * boundary_prefix) { struct mailmime_fields * mime_fields; struct mailmime_content * content; struct mailmime * mp; mime_fields = mailmime_fields_new_empty(); if (mime_fields == NULL) goto err; content = mailmime_content_new_with_str(type); if (content == NULL) goto free_fields; mp = part_new_empty(content, mime_fields, boundary_prefix, 0); if (mp == NULL) goto free_content; return mp; free_content: mailmime_content_free(content); free_fields: mailmime_fields_free(mime_fields); err: return NULL; } static struct mailmime * get_multipart_mixed(const char * boundary_prefix) { struct mailmime * mime; mime = part_multiple_new("multipart/mixed", boundary_prefix); return mime; } int main(int argc, char ** argv) { struct mailmime * msg_mime; struct mailmime * mime; struct mailmime * submime; struct mailimf_fields * fields; int col; msg_mime = mailmime_new_message_data(NULL); fields = build_fields(); mailmime_set_imf_fields(msg_mime, fields); mime = get_multipart_mixed(NULL); submime = get_plain_text_part(); mailmime_smart_add_part(mime, submime); submime = get_sample_file_part(); mailmime_smart_add_part(mime, submime); mailmime_add_part(msg_mime, mime); col = 0; mailmime_write_file(stdout, &col, mime); mailmime_free(msg_mime); exit(0); }