author | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
commit | e3b89230f065c48c84b48c88edb6eb088374c487 (patch) (side-by-side diff) | |
tree | 162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/tests | |
parent | 2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff) | |
download | kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2 |
Initial revision
-rw-r--r-- | kmicromail/libetpan/tests/README | 58 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/compose-msg.c | 317 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/fetch-attachment.c | 274 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/frm-common.c | 158 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/frm-common.h | 14 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/frm-simple.c | 227 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/frm-tree.c | 234 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/frm.c | 158 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/option-parser.c | 234 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/option-parser.h | 28 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/readmsg-common.c | 720 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/readmsg-common.h | 34 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/readmsg-simple.c | 133 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/readmsg.c | 355 | ||||
-rw-r--r-- | kmicromail/libetpan/tests/smtpsend.c | 278 |
15 files changed, 3222 insertions, 0 deletions
diff --git a/kmicromail/libetpan/tests/README b/kmicromail/libetpan/tests/README new file mode 100644 index 0000000..66d8b2f --- a/dev/null +++ b/kmicromail/libetpan/tests/README @@ -0,0 +1,58 @@ +compose-msg +----------- + +creates a RFC 2822 message with MIME parts + +syntax: compose-msg "text" filename + + + +all the following programs will take as argument : + + --driver=(pop3|imap|nntp|mbox|mh) -d pop3 (pop3|imap|nntp|mbox|mh) + + default driver is mbox + + --server={server-name} -s {server-name} + --port={port-number} -p {port-number} + --tls -t + --starttls -x + --user={login} -u {login} + --password={password} -v {password} + --path={mailbox} -l {mailbox} + --apop -a + --cache={directory} -c {directory} + +the default driver is mbox with the path /var/mail/$USER + +frm-simple, frm, frm-tree +------------------------- + +frm-simple will list all the mails of a mailbox without any MIME decoding. + +frm will list all the mails of a mailbox and will decode the fields. + +frm-tree will do the same thing as frm and will also show the threads + of the folder. + + +fetch-attachment +---------------- + + fetch-attachment gets all the named attachment of the given message +of the chosen mailbox and writes them on the current directory. + + The program should be given message numbers (as given by frm) as +additionnal arguments. + + +readmsg-simple, readmsg +----------------------- + + readmsg-simple will display the content of the given messages. +All the content (headers and body) will be displayed. + + readmsg will display only the text parts of the given messages. + + The program should be given message numbers (as given by frm) as +additionnal arguments. diff --git a/kmicromail/libetpan/tests/compose-msg.c b/kmicromail/libetpan/tests/compose-msg.c new file mode 100644 index 0000000..f68660b --- a/dev/null +++ b/kmicromail/libetpan/tests/compose-msg.c @@ -0,0 +1,317 @@ +#include <libetpan/libetpan.h> +#include <string.h> +#include <stdlib.h> + +#define DEST_CHARSET "iso-8859-1" + +/* build a mime parameter */ + +static struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value) +{ + char * param_name; + char * param_value; + struct mailmime_parameter * param; + + param_name = strdup(name); + if (param_name == NULL) + goto err; + + param_value = strdup(value); + if (param_value == NULL) + goto free_name; + + param = mailmime_parameter_new(param_name, param_value); + if (param == NULL) + goto free_value; + + return param; + + free_value: + free(param_value); + free_name: + free(param_name); + err: + return NULL; +} + + +/* build sample fields */ + +static struct mailimf_fields * build_fields(void) +{ + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + char * subject; + int r; + struct mailimf_fields * new_fields; + + /* subject field */ + + subject = strdup("this is a sample"); + if (subject == NULL) { + goto err; + } + + /* from field */ + + from = mailimf_mailbox_list_new_empty(); + if (from == NULL) { + goto free_subject; + } + + r = mailimf_mailbox_list_add_parse(from, + "DINH Viet Hoa <hoa@sourceforge.net>"); + if (r != MAILIMF_NO_ERROR) { + goto free_from; + } + + /* to field */ + + to = mailimf_address_list_new_empty(); + if (to == NULL) { + goto free_from; + } + + r = mailimf_address_list_add_parse(to, + "Paul <claws@thewildbeast.co.uk>"); + if (r != MAILIMF_NO_ERROR) { + goto free_to; + } + + new_fields = mailimf_fields_new_with_data(from /* from */, + NULL /* sender */, NULL /* reply-to */, + to, NULL /* cc */, NULL /* bcc */, NULL /* in-reply-to */, + NULL /* references */, + subject); + if (new_fields == NULL) + goto free_to; + + return new_fields; + + free_to: + mailimf_address_list_free(to); + free_from: + mailimf_mailbox_list_free(from); + free_subject: + free(subject); + err: + return NULL; +} + + + +/* text is a string, build a mime part containing this string */ + +static struct mailmime * build_body_text(char * text) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime_sub; + struct mailmime_content * content; + struct mailmime_parameter * param; + int r; + + /* text/plain part */ + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if (mime_fields == NULL) { + goto err; + } + + content = mailmime_content_new_with_str("text/plain"); + if (content == NULL) { + goto free_fields; + } + + param = mailmime_param_new_with_data("charset", DEST_CHARSET); + if (param == NULL) { + goto free_content; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_content; + } + + mime_sub = mailmime_new_empty(content, mime_fields); + if (mime_sub == NULL) { + goto free_content; + } + + r = mailmime_set_body_text(mime_sub, text, strlen(text)); + if (r != MAILIMF_NO_ERROR) { + goto free_mime; + } + + return mime_sub; + + free_mime: + mailmime_free(mime_sub); + goto err; + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + +/* build a mime part containing the given file */ + +static struct mailmime * build_body_file(char * filename) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime_sub; + struct mailmime_content * content; + struct mailmime_parameter * param; + char * dup_filename; + int r; + + /* text/plain part */ + + dup_filename = strdup(filename); + if (dup_filename == NULL) + goto err; + + mime_fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + dup_filename, MAILMIME_MECHANISM_BASE64); + if (mime_fields == NULL) + goto free_dup_filename; + + content = mailmime_content_new_with_str("text/plain"); + if (content == NULL) { + goto free_fields; + } + + param = mailmime_param_new_with_data("charset", DEST_CHARSET); + if (param == NULL) { + goto free_content; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_content; + } + + mime_sub = mailmime_new_empty(content, mime_fields); + if (mime_sub == NULL) { + goto free_content; + } + + dup_filename = strdup(filename); + if (dup_filename == NULL) + goto free_mime; + + r = mailmime_set_body_file(mime_sub, dup_filename); + if (r != MAILIMF_NO_ERROR) { + goto free_mime; + } + + return mime_sub; + + free_mime: + mailmime_free(mime_sub); + goto err; + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + goto err; + free_dup_filename: + free(dup_filename); + err: + return NULL; +} + + +/* build an empty message */ + +static struct mailmime * build_message(struct mailimf_fields * fields) +{ + struct mailmime * mime; + + /* message */ + + mime = mailmime_new_message_data(NULL); + if (mime == NULL) { + goto err; + } + + mailmime_set_imf_fields(mime, fields); + + return mime; + + err: + return NULL; +} + + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + char * text; + char * filename; + struct mailmime * message; + struct mailmime * text_part; + struct mailmime * file_part; + int r; + int col; + + if (argc < 3) { + printf("syntax: compose-msg \"text\" filename\n"); + return 1; + } + + fields = build_fields(); + if (fields == NULL) + goto err; + + message = build_message(fields); + if (message == NULL) + goto free_fields; + + text = argv[1]; + text_part = build_body_text(text); + if (text_part == NULL) + goto free_message; + + filename = argv[2]; + file_part = build_body_file(filename); + if (file_part == NULL) + goto free_text; + + r = mailmime_smart_add_part(message, text_part); + if (r != MAILIMF_NO_ERROR) + goto free_file; + + r = mailmime_smart_add_part(message, file_part); + if (r != MAILIMF_NO_ERROR) + goto free_file_alone; + + col = 0; + mailmime_write(stdout, &col, message); + + mailmime_free(message); + + return 0; + + free_file_alone: + mailmime_free(file_part); + goto free_text; + free_file: + mailmime_free(file_part); + free_text: + mailmime_free(text_part); + free_message: + mailmime_free(message); + goto err; + free_fields: + mailimf_fields_free(fields); + err: + printf("error memory\n"); + return 1; +} diff --git a/kmicromail/libetpan/tests/fetch-attachment.c b/kmicromail/libetpan/tests/fetch-attachment.c new file mode 100644 index 0000000..a79ef8b --- a/dev/null +++ b/kmicromail/libetpan/tests/fetch-attachment.c @@ -0,0 +1,274 @@ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" +#include "readmsg-common.h" + +/* write content to the given filename */ + +static int etpan_write_data(char * filename, char * data, size_t len) +{ + size_t write_len; + FILE * f; + int res; + mode_t old_umask; + + old_umask = umask(0077); + f = fopen(filename, "w"); + umask(old_umask); + if (f == NULL) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len < len) { + res = ERROR_FILE; + goto close; + } + + fclose(f); + + return NO_ERROR; + + close: + fclose(f); + err: + return res; +} + + +/* save attachment */ + +static int save_mime_content(mailmessage * msg_info, + struct mailmime * mime_part) +{ + char * body; + size_t body_len; + int r; + char * filename; + struct mailmime_single_fields fields; + int res; + + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime_part->mm_mime_fields != NULL) + mailmime_single_fields_init(&fields, mime_part->mm_mime_fields, + mime_part->mm_content_type); + + filename = fields.fld_disposition_filename; + + if (filename == NULL) + filename = fields.fld_content_name; + + if (filename == NULL) + return ERROR_INVAL; + + r = etpan_fetch_message(msg_info, mime_part, &fields, &body, &body_len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + printf("writing %s, %i bytes\n", filename, body_len); + + r = etpan_write_data(filename, body, body_len); + if (r != NO_ERROR) { + res = r; + goto free; + } + + mailmime_decoded_part_free(body); + + return NO_ERROR; + + free: + mailmime_decoded_part_free(body); + err: + return res; +} + + + +/* fetch attachments */ + +static int etpan_fetch_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + struct mailmime_single_fields fields; + int res; + + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime->mm_mime_fields != NULL) + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + save_mime_content(msg_info, mime); + + break; + + case MAILMIME_MULTIPLE: + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_fetch_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_fetch_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + struct mailmime * mime; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found ** - %s\n", msg_num, + maildriver_strerror(r)); + optind ++; + continue; + } + + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + r = etpan_fetch_mime(stdout, msg, mime); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} diff --git a/kmicromail/libetpan/tests/frm-common.c b/kmicromail/libetpan/tests/frm-common.c new file mode 100644 index 0000000..eeeadf0 --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-common.c @@ -0,0 +1,158 @@ +#include "frm-common.h" + +#include <string.h> +#include <stdlib.h> + +#define DEST_CHARSET "iso-8859-1" + +/* get part of the from field to display */ + +void get_from_value(struct mailimf_single_fields * fields, + char ** from, int * is_addr) +{ + struct mailimf_mailbox * mb; + + if (fields->fld_from == NULL) { + * from = NULL; + * is_addr = 0; + return; + } + + if (clist_isempty(fields->fld_from->frm_mb_list->mb_list)) { + * from = NULL; + * is_addr = 0; + return; + } + + mb = clist_begin(fields->fld_from->frm_mb_list->mb_list)->data; + + if (mb->mb_display_name != NULL) { + * from = mb->mb_display_name; + * is_addr = 0; + } + else { + * from = mb->mb_addr_spec; + * is_addr = 1; + } +} + +/* remove all CR and LF of a string and replace them with SP */ + +void strip_crlf(char * str) +{ + char * p; + + for(p = str ; * p != '\0' ; p ++) { + if ((* p == '\n') || (* p == '\r')) + * p = ' '; + } +} + +#define MAX_OUTPUT 81 + +/* display information for one message */ + +void print_mail_info(char * prefix, mailmessage * msg) +{ + char * from; + char * subject; + char * decoded_from; + char * decoded_subject; + size_t cur_token; + int r; + int is_addr; + char * dsp_from; + char * dsp_subject; + char output[MAX_OUTPUT]; + struct mailimf_single_fields single_fields; + + is_addr = 0; + from = NULL; + subject = NULL; + + decoded_subject = NULL; + decoded_from = NULL; + + /* from field */ + + if (msg->msg_fields != NULL) + mailimf_single_fields_init(&single_fields, msg->msg_fields); + else + memset(&single_fields, 0, sizeof(single_fields)); + + get_from_value(&single_fields, &from, &is_addr); + + if (from == NULL) + decoded_from = NULL; + else { + if (!is_addr) { + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + from, strlen(from), + &cur_token, DEST_CHARSET, + &decoded_from); + if (r != MAILIMF_NO_ERROR) { + decoded_from = strdup(from); + if (decoded_from == NULL) + goto err; + } + } + else { + decoded_from = strdup(from); + if (decoded_from == NULL) { + goto err; + } + } + } + + if (decoded_from == NULL) + dsp_from = ""; + else { + dsp_from = decoded_from; + strip_crlf(dsp_from); + } + + /* subject */ + + if (single_fields.fld_subject != NULL) + subject = single_fields.fld_subject->sbj_value; + + if (subject == NULL) + decoded_subject = NULL; + else { + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + subject, strlen(subject), + &cur_token, DEST_CHARSET, + &decoded_subject); + if (r != MAILIMF_NO_ERROR) { + decoded_subject = strdup(subject); + if (decoded_subject == NULL) + goto free_from; + } + } + + if (decoded_subject == NULL) + dsp_subject = ""; + else { + dsp_subject = decoded_subject; + strip_crlf(dsp_subject); + } + + snprintf(output, MAX_OUTPUT, "%3i: %-21.21s %s%-53.53s", + msg->msg_index, dsp_from, prefix, dsp_subject); + + printf("%s\n", output); + + if (decoded_subject != NULL) + free(decoded_subject); + if (decoded_from != NULL) + free(decoded_from); + + return; + + free_from: + if (decoded_from) + free(decoded_from); + err: +} diff --git a/kmicromail/libetpan/tests/frm-common.h b/kmicromail/libetpan/tests/frm-common.h new file mode 100644 index 0000000..c1a27c2 --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-common.h @@ -0,0 +1,14 @@ +#ifndef FRM_COMMON_H + +#define FRM_COMMON_H + +#include <libetpan/libetpan.h> + +void get_from_value(struct mailimf_single_fields * fields, + char ** from, int * is_addr); + +void strip_crlf(char * str); + +void print_mail_info(char * prefix, mailmessage * msg); + +#endif diff --git a/kmicromail/libetpan/tests/frm-simple.c b/kmicromail/libetpan/tests/frm-simple.c new file mode 100644 index 0000000..7c3640f --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-simple.c @@ -0,0 +1,227 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include <libetpan/libetpan.h> + +#include <stdlib.h> +#include <string.h> + +#define DEST_CHARSET "iso-8859-1" + +#define MAX_OUTPUT 81 + +/* display information for one message */ + +static void simple_print_mail_info(mailmessage * msg) +{ + char * from; + char * subject; + int is_addr; + char * dsp_from; + char * dsp_subject; + char output[MAX_OUTPUT]; + struct mailimf_single_fields single_fields; + + is_addr = 0; + from = NULL; + subject = NULL; + + if (msg->msg_fields != NULL) + mailimf_single_fields_init(&single_fields, msg->msg_fields); + else + memset(&single_fields, 0, sizeof(single_fields)); + + /* from field */ + + get_from_value(&single_fields, &from, &is_addr); + + if (from == NULL) + dsp_from = strdup(""); + else + dsp_from = strdup(from); + if (dsp_from == NULL) + goto err; + + strip_crlf(dsp_from); + + /* subject */ + + if (single_fields.fld_subject != NULL) + subject = single_fields.fld_subject->sbj_value; + + if (subject == NULL) + dsp_subject = strdup(""); + else + dsp_subject = strdup(subject); + + if (dsp_subject == NULL) + goto free_from; + + strip_crlf(dsp_subject); + + snprintf(output, MAX_OUTPUT, "%3i: %-21.21s %-53.53s\n", + msg->msg_index % 1000, dsp_from, dsp_subject); + + printf("%s\n", output); + + free(dsp_subject); + free(dsp_from); + + return; + + free_from: + free(dsp_from); + err: +} + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + uint32_t i; + struct mailmessage_list * env_list; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* display all the messages */ + + count = 0; + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + printf("could not fetch envelope of message %i\n", i); + } + else { + simple_print_mail_info(msg); + count ++; + } + } + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + diff --git a/kmicromail/libetpan/tests/frm-tree.c b/kmicromail/libetpan/tests/frm-tree.c new file mode 100644 index 0000000..3a8464a --- a/dev/null +++ b/kmicromail/libetpan/tests/frm-tree.c @@ -0,0 +1,234 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include <libetpan/libetpan.h> + +#include <stdlib.h> +#include <string.h> + +#define DEST_CHARSET "iso-8859-1" + +/* display tree */ + +static void +display_sub_tree(MMAPString * prefix, + struct mailmessage_tree * msg_tree, + int level, int has_next, unsigned int * pcount) +{ + carray * list; + uint32_t cur; + + if (msg_tree->node_msg != NULL) { + print_mail_info(prefix->str, msg_tree->node_msg); + (* pcount) ++; + } + + list = msg_tree->node_children; + + if (carray_count(list) != 0) { + char old_prefix[2]; + + if (level > 1) { + memcpy(old_prefix, prefix->str + prefix->len - 2, 2); + if (has_next) + memcpy(prefix->str + prefix->len - 2, "| ", 2); + else + memcpy(prefix->str + prefix->len - 2, " ", 2); + } + for(cur = 0 ; cur < carray_count(list) ; cur ++) { + int sub_has_next; + + if (cur != carray_count(list) - 1) { + if (level > 0) { + if (mmap_string_append(prefix, "+-") == NULL) + return; + } + sub_has_next = 1; + } + else { + if (level > 0) { + if (mmap_string_append(prefix, "\\-") == NULL) + return; + } + sub_has_next = 0; + } + + display_sub_tree(prefix, carray_get(list, cur), + level + 1, sub_has_next, pcount); + + if (mmap_string_truncate(prefix, prefix->len - 2) == NULL) { + return; + } + } + if (level > 1) { + memcpy(prefix->str + prefix->len - 2, old_prefix, 2); + } + } +} + +static void display_tree(struct mailmessage_tree * env_tree, + unsigned int * pcount) +{ + MMAPString * prefix; + + prefix = mmap_string_new(""); + if (prefix == NULL) + return; + + display_sub_tree(prefix, env_tree, 0, 0, pcount); + + mmap_string_free(prefix); +} + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + struct mailmessage_list * env_list; + struct mailmessage_tree * env_tree; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* build threads */ + + r = mail_build_thread(MAIL_THREAD_REFERENCES_NO_SUBJECT, + DEST_CHARSET, + env_list, &env_tree, + mailthread_tree_timecomp); + if (r != MAIL_NO_ERROR) { + printf("can't build tree\n"); + goto free_msg_list; + } + + /* display message tree */ + + count = 0; + display_tree(env_tree, &count); + + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_tree_free_recursive(env_tree); + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + diff --git a/kmicromail/libetpan/tests/frm.c b/kmicromail/libetpan/tests/frm.c new file mode 100644 index 0000000..8ce9d9b --- a/dev/null +++ b/kmicromail/libetpan/tests/frm.c @@ -0,0 +1,158 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include <libetpan/libetpan.h> + +#include <stdlib.h> +#include <string.h> + +#define DEST_CHARSET "iso-8859-1" + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + uint32_t i; + struct mailmessage_list * env_list; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* display all the messages */ + + count = 0; + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + printf("could not fetch envelope of message %i\n", i); + } + else { + print_mail_info("", msg); + count ++; + } + } + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error connecting folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + diff --git a/kmicromail/libetpan/tests/option-parser.c b/kmicromail/libetpan/tests/option-parser.c new file mode 100644 index 0000000..57a1597 --- a/dev/null +++ b/kmicromail/libetpan/tests/option-parser.c @@ -0,0 +1,234 @@ +#define _GNU_SOURCE +#include <getopt.h> + +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" + +/* + options + + --driver (pop3|imap|nntp|mbox|mh|maildir) -d + + default driver is mbox + + --server {server-name} -s + --port {port-number} -p + --tls -t + --starttls -x + --user {login} -u + --password {password} -v + --path {mailbox} -l + --apop -a + --cache {directory} -c + --flags {directory} -f +*/ + +struct storage_name { + int id; + char * name; +}; + +static struct storage_name storage_tab[] = { + {POP3_STORAGE, "pop3"}, + {IMAP_STORAGE, "imap"}, + {NNTP_STORAGE, "nntp"}, + {MBOX_STORAGE, "mbox"}, + {MH_STORAGE, "mh"}, + {MAILDIR_STORAGE, "maildir"}, +}; + +static int get_driver(char * name) +{ + int driver_type; + unsigned int i; + + driver_type = -1; + for(i = 0 ; i < sizeof(storage_tab) / sizeof(struct storage_name) ; i++) { + if (strcasecmp(name, storage_tab[i].name) == 0) { + driver_type = i; + break; + } + } + + return driver_type; +} + +int parse_options(int argc, char ** argv, + int * driver, + char ** server, int * port, int * connection_type, + char ** user, char ** password, int * auth_type, + char ** path, char ** cache_directory, + char ** flags_directory) +{ + int index; + static struct option long_options[] = { + {"driver", 1, 0, 'd'}, + {"server", 1, 0, 's'}, + {"port", 1, 0, 'p'}, + {"tls", 0, 0, 't'}, + {"starttls", 0, 0, 'x'}, + {"user", 1, 0, 'u'}, + {"password", 1, 0, 'v'}, + {"path", 1, 0, 'l'}, + {"apop", 0, 0, 'a'}, + {"cache", 1, 0, 'c'}, + {"flags", 1, 0, 'f'}, + }; + int r; + char location[PATH_MAX]; + char * env_user; + + index = 0; + + * driver = MBOX_STORAGE; + * server = NULL; + * port = 0; + * connection_type = CONNECTION_TYPE_PLAIN; + * user = NULL; + * password = NULL; + * auth_type = POP3_AUTH_TYPE_PLAIN; + env_user = getenv("USER"); + if (env_user != NULL) { + snprintf(location, PATH_MAX, "/var/mail/%s", env_user); + * path = strdup(location); + } + else + * path = NULL; + * cache_directory = NULL; + * flags_directory = NULL; + + while (1) { + r = getopt_long(argc, argv, "d:s:p:txu:v:l:ac:f:", long_options, &index); + + if (r == -1) + break; + + switch (r) { + case 'd': + * driver = get_driver(optarg); + break; + case 's': + if (* server != NULL) + free(* server); + * server = strdup(optarg); + break; + case 'p': + * port = strtoul(optarg, NULL, 10); + break; + case 't': + * connection_type = CONNECTION_TYPE_TLS; + break; + case 'x': + * connection_type = CONNECTION_TYPE_STARTTLS; + break; + case 'u': + if (* user != NULL) + free(* user); + * user = strdup(optarg); + break; + case 'v': + if (* password != NULL) + free(* password); + * password = strdup(optarg); + break; + case 'l': + if (* path != NULL) + free(* path); + * path = strdup(optarg); + break; + case 'a': + * auth_type = POP3_AUTH_TYPE_APOP; + break; + case 'c': + if (* cache_directory != NULL) + free(* cache_directory); + * cache_directory = strdup(optarg); + break; + case 'f': + if (* flags_directory != NULL) + free(* flags_directory); + * flags_directory = strdup(optarg); + break; + } + } + + return 0; +} + +int init_storage(struct mailstorage * storage, + int driver, char * server, int port, + int connection_type, char * user, char * password, int auth_type, + char * path, char * cache_directory, char * flags_directory) +{ + int r; + int cached; + + cached = (cache_directory != NULL); + + switch (driver) { + case POP3_STORAGE: + r = pop3_mailstorage_init(storage, server, port, NULL, connection_type, + auth_type, user, password, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing POP3 storage\n"); + goto err; + } + break; + + case IMAP_STORAGE: + r = imap_mailstorage_init(storage, server, port, NULL, connection_type, + IMAP_AUTH_TYPE_PLAIN, user, password, cached, cache_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing IMAP storage\n"); + goto err; + } + break; + + case NNTP_STORAGE: + r = nntp_mailstorage_init(storage, server, port, NULL, connection_type, + NNTP_AUTH_TYPE_PLAIN, user, password, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing NNTP storage\n"); + goto err; + } + break; + + case MBOX_STORAGE: + r = mbox_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing mbox storage\n"); + goto err; + } + break; + + case MH_STORAGE: + r = mh_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing MH storage\n"); + goto err; + } + break; + case MAILDIR_STORAGE: + r = maildir_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing maildir storage\n"); + goto err; + } + break; + } + + return MAIL_NO_ERROR; + + err: + return r; +} diff --git a/kmicromail/libetpan/tests/option-parser.h b/kmicromail/libetpan/tests/option-parser.h new file mode 100644 index 0000000..d765332 --- a/dev/null +++ b/kmicromail/libetpan/tests/option-parser.h @@ -0,0 +1,28 @@ +#ifndef OPTION_PARSER + +#define OPTION_PARSER + +#include <libetpan/libetpan.h> + +enum { + POP3_STORAGE = 0, + IMAP_STORAGE, + NNTP_STORAGE, + MBOX_STORAGE, + MH_STORAGE, + MAILDIR_STORAGE, +}; + +int parse_options(int argc, char ** argv, + int * driver, + char ** server, int * port, int * connection_type, + char ** user, char ** password, int * auth_type, + char ** path, char ** cache_directory, + char ** flags_directory); + +int init_storage(struct mailstorage * storage, + int driver, char * server, int port, + int connection_type, char * user, char * password, int auth_type, + char * path, char * cache_directory, char * flags_directory); + +#endif diff --git a/kmicromail/libetpan/tests/readmsg-common.c b/kmicromail/libetpan/tests/readmsg-common.c new file mode 100644 index 0000000..060497d --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg-common.c @@ -0,0 +1,720 @@ +#include "readmsg-common.h" + +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* + fetch the data of the mailmime_data structure whether it is a file + or a string. + + data must be freed with mmap_string_unref() +*/ + +#if 0 +static int fetch_data(struct mailmime_data * data, + char ** result, size_t * result_len) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + MMAPString * mmapstr; + + switch (data->dt_type) { + case MAILMIME_DATA_TEXT: + mmapstr = mmap_string_new_len(data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (mmapstr == NULL) { + res = ERROR_MEMORY; + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return NO_ERROR; + + case MAILMIME_DATA_FILE: + fd = open(data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (text == MAP_FAILED) { + res = ERROR_FILE; + goto close; + } + + mmapstr = mmap_string_new_len(text, buf.st_size); + if (mmapstr == NULL) { + res = r; + goto unmap; + } + + munmap(text, buf.st_size); + } + else { + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = r; + goto close; + } + } + + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return NO_ERROR; + + default: + return ERROR_INVAL; + } + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; +} +#endif + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_fields_parse(data, len, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + + + +#define MAX_MAIL_COL 72 + +/* write decoded mailbox */ + +static int +etpan_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb) +{ + int r; + + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + * col = 1; + } + } + + if (mb->mb_display_name) { + char * decoded_from; + size_t cur_token; + + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + mb->mb_display_name, strlen(mb->mb_display_name), + &cur_token, DEST_CHARSET, + &decoded_from); + if (r != MAILIMF_NO_ERROR) { + decoded_from = strdup(mb->mb_display_name); + if (decoded_from == NULL) + return ERROR_MEMORY; + } + + r = mailimf_quoted_string_write(f, col, decoded_from, + strlen(decoded_from)); + if (r != MAILIMF_NO_ERROR) { + free(decoded_from); + return ERROR_FILE; + } + + if (* col > 1) { + + if (* col + strlen(decoded_from) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) { + free(decoded_from); + return r; + } + * col = 1; + } + } + + free(decoded_from); + + r = mailimf_string_write(f, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + + + return NO_ERROR; + +} + +/* write decoded mailbox list */ + +int +etpan_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = 1; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = cur->data; + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + first = 0; + } + + r = etpan_mailbox_write(f, col, mb); + if (r != NO_ERROR) + return r; + } + + return NO_ERROR; +} + +/* write decoded group */ + +static int +etpan_group_write(FILE * f, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_string_write(f, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + if (group->grp_mb_list != NULL) { + r = etpan_mailbox_list_write(f, col, group->grp_mb_list); + if (r != NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + return NO_ERROR; +} + +/* write decoded address */ + +int +etpan_address_write(FILE * f, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = etpan_mailbox_write(f, col, addr->ad_data.ad_mailbox); + if (r != NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = etpan_group_write(f, col, addr->ad_data.ad_group); + if (r != NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + +/* write decoded address list */ + +int +etpan_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = 1; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + first = 0; + } + + r = etpan_address_write(f, col, addr); + if (r != NO_ERROR) + return r; + } + + return NO_ERROR; +} + +/* write decoded subject */ + +static int etpan_subject_write(FILE * f, int * col, + char * subject) +{ + int r; + char * decoded_subject; + size_t cur_token; + + r = mailimf_string_write(f, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) { + return ERROR_FILE; + } + + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + subject, strlen(subject), + &cur_token, DEST_CHARSET, + &decoded_subject); + if (r != MAILIMF_NO_ERROR) { + decoded_subject = strdup(subject); + if (decoded_subject == NULL) + return ERROR_MEMORY; + } + + r = mailimf_string_write(f, col, decoded_subject, strlen(decoded_subject)); + if (r != MAILIMF_NO_ERROR) { + free(decoded_subject); + return ERROR_FILE; + } + + free(decoded_subject); + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + return ERROR_FILE; + } + * col = 0; + + return NO_ERROR; +} + +/* write decoded fields */ + +int fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_FROM: + r = mailimf_string_write(f, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_mailbox_list_write(f, col, + field->fld_data.fld_from->frm_mb_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_string_write(f, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_reply_to->rt_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_TO: + r = mailimf_string_write(f, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_to->to_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_CC: + r = mailimf_string_write(f, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_cc->cc_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_BCC: + r = mailimf_string_write(f, col, "Bcc: ", 10); + if (r != MAILIMF_NO_ERROR) + goto err; + + if (field->fld_data.fld_bcc->bcc_addr_list != NULL) { + r = etpan_address_list_write(f, col, + field->fld_data.fld_bcc->bcc_addr_list); + if (r != NO_ERROR) + goto err; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_SUBJECT: + r = etpan_subject_write(f, col, field->fld_data.fld_subject->sbj_value); + if (r != MAILIMF_NO_ERROR) + goto err; + break; + + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_string_write(f, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_mailbox_list_write(f, col, + field->fld_data.fld_resent_from->frm_mb_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + break; + + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_string_write(f, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_to->to_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_string_write(f, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_cc->cc_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_string_write(f, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + goto err; + + if (field->fld_data.fld_resent_bcc->bcc_addr_list != NULL) { + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_bcc->bcc_addr_list); + if (r != NO_ERROR) + goto err; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_ORIG_DATE: + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + goto err; + break; + + case MAILIMF_FIELD_OPTIONAL_FIELD: + if ((strcasecmp(field->fld_data.fld_optional_field->fld_name, + "X-Mailer") == 0) + || (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Resent-", 7) == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Newsgroups") == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Followup-To") == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "User-Agent") == 0)) { + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + goto err; + } + break; + + case MAILIMF_FIELD_MESSAGE_ID: + case MAILIMF_FIELD_SENDER: + case MAILIMF_FIELD_IN_REPLY_TO: + case MAILIMF_FIELD_REFERENCES: + default: + break; + } + } + + return NO_ERROR; + + err: + return ERROR_FILE; +} diff --git a/kmicromail/libetpan/tests/readmsg-common.h b/kmicromail/libetpan/tests/readmsg-common.h new file mode 100644 index 0000000..70265f2 --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg-common.h @@ -0,0 +1,34 @@ +#ifndef READMSG_COMMON_H + +#define READMSG_COMMON_H + +#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +int etpan_mime_is_text(struct mailmime * build_info); + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content); + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len); + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime); + +int fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +#endif diff --git a/kmicromail/libetpan/tests/readmsg-simple.c b/kmicromail/libetpan/tests/readmsg-simple.c new file mode 100644 index 0000000..ea57d6d --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg-simple.c @@ -0,0 +1,133 @@ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + char * data; + size_t size; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found **\n", msg_num); + optind ++; + continue; + } + + r = mailmessage_fetch(msg, &data, &size); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + fwrite(data, 1, size, stdout); + + mailmessage_fetch_result_free(msg, data); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} diff --git a/kmicromail/libetpan/tests/readmsg.c b/kmicromail/libetpan/tests/readmsg.c new file mode 100644 index 0000000..822c93c --- a/dev/null +++ b/kmicromail/libetpan/tests/readmsg.c @@ -0,0 +1,355 @@ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <libetpan/charconv.h> +#include <libetpan/libetpan.h> + +#include "option-parser.h" +#include "readmsg-common.h" + + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + struct mailmime * mime; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found ** - %s\n", msg_num, + maildriver_strerror(r)); + optind ++; + continue; + } + + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + r = etpan_render_mime(stdout, msg, mime); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} diff --git a/kmicromail/libetpan/tests/smtpsend.c b/kmicromail/libetpan/tests/smtpsend.c new file mode 100644 index 0000000..d5229d9 --- a/dev/null +++ b/kmicromail/libetpan/tests/smtpsend.c @@ -0,0 +1,278 @@ +/* + * Simple Mail Submission Agent using SMTP with libEtPan! + * TODO: Full sendmail like interface + */ + +#include <libetpan/libetpan.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <pwd.h> + +#define _GNU_SOURCE +#include <getopt.h> + +/* globals */ +char *smtp_server; +uint smtp_port = 25; +char *smtp_user; +char *smtp_password; +char *smtp_from; +int smtp_tls = 0; +int smtp_esmtp = 1; + +struct mem_message { + char *data; + size_t len; + MMAPString *mstring; +}; + +#define BLOCKSIZE 4096 + +int collect(struct mem_message *message) { + struct stat sb; + int len; + + memset(message, 0, sizeof(struct mem_message)); + + /* if stdin is a file whose size is known, try to mmap it */ + if (!fstat(0, &sb) && S_ISREG(sb.st_mode) && sb.st_size >= 0) { + message->len = sb.st_size; + if ((message->data = mmap(NULL, message->len, PROT_READ, MAP_SHARED, + STDIN_FILENO, 0)) != MAP_FAILED) + return 0; + } + + /* read the buffer from stdin by blocks, until EOF or error. + save the message in a mmap_string */ + if ((message->mstring = mmap_string_sized_new(BLOCKSIZE)) == NULL) { + perror("mmap_string_new"); + goto error; + } + message->len = 0; + + while ((len = read(STDIN_FILENO, + message->mstring->str + message->len, BLOCKSIZE)) > 0) { + message->len += len; + /* reserve room for next block */ + if ((mmap_string_set_size(message->mstring, + message->len + BLOCKSIZE)) == NULL) { + perror("mmap_string_set_size"); + goto error; + } + } + + if (len == 0) { + message->data = message->mstring->str; + return 0; /* OK */ + } + + perror("read"); + + error: + if (message->mstring != NULL) + mmap_string_free(message->mstring); + return -1; +} + +char *guessfrom() { + uid_t uid; + struct passwd *pw; + char hostname[256]; + int len; + char *gfrom; + + if (gethostname(hostname, sizeof(hostname))) { + perror("gethostname"); + return NULL; + } + hostname[sizeof(hostname) - 1] = '\0'; + + uid = getuid(); + pw = getpwuid(uid); + + len = ((pw != NULL) ? strlen(pw->pw_name) : 12) + + strlen(hostname) + 2; + + if ((gfrom = malloc(len)) == NULL) { + perror("malloc"); + return NULL; + } + if (pw != NULL && pw->pw_name != NULL) + snprintf(gfrom, len, "%s@%s", pw->pw_name, hostname); + else + snprintf(gfrom, len, "#%u@%s", uid, hostname); + return gfrom; +} + +void release(struct mem_message *message) { + if (message->mstring != NULL) + mmap_string_free(message->mstring); + else if (message->data != NULL) + munmap(message->data, message->len); +} + +int send_message(char *data, size_t len, char**rcpts) { + int s = -1; + int ret; + char **r; + int esmtp = 0; + mailsmtp *smtp = NULL; + + if ((smtp = mailsmtp_new(0, NULL)) == NULL) { + perror("mailsmtp_new"); + goto error; + } + + /* first open the stream */ + if ((ret = mailsmtp_socket_connect(smtp, + (smtp_server != NULL ? smtp_server : "localhost"), + smtp_port)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_socket_connect: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + /* then introduce ourselves */ + if (smtp_esmtp && (ret = mailesmtp_ehlo(smtp)) == MAILSMTP_NO_ERROR) + esmtp = 1; + else if (!smtp_esmtp || ret == MAILSMTP_ERROR_NOT_IMPLEMENTED) + ret = mailsmtp_helo(smtp); + if (ret != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_helo: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + if (esmtp && smtp_tls && + (ret = mailsmtp_socket_starttls(smtp)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_starttls: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + if (esmtp && smtp_user != NULL && + (ret = mailsmtp_auth(smtp, smtp_user, + (smtp_password != NULL) ? smtp_password : "")) + != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_auth: %s: %s\n", smtp_user, mailsmtp_strerror(ret)); + goto error; + } + + /* source */ + if ((ret = (esmtp ? + mailesmtp_mail(smtp, smtp_from, 1, "etPanSMTPTest") : + mailsmtp_mail(smtp, smtp_from))) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_mail: %s, %s\n", smtp_from, mailsmtp_strerror(ret)); + goto error; + } + + /* recipients */ + for (r = rcpts; *r != NULL; r++) { + if ((ret = (esmtp ? + mailesmtp_rcpt(smtp, *r, + MAILSMTP_DSN_NOTIFY_FAILURE|MAILSMTP_DSN_NOTIFY_DELAY, + NULL) : + mailsmtp_rcpt(smtp, *r))) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_rcpt: %s: %s\n", *r, mailsmtp_strerror(ret)); + goto error; + } + } + + /* message */ + if ((ret = mailsmtp_data(smtp)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_data: %s\n", mailsmtp_strerror(ret)); + goto error; + } + if ((ret = mailsmtp_data_message(smtp, data, len)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_data_message: %s\n", mailsmtp_strerror(ret)); + goto error; + } + mailsmtp_free(smtp); + return 0; + + error: + if (smtp != NULL) + mailsmtp_free(smtp); + if (s >= 0) + close(s); + return -1; +} + +int main(int argc, char **argv) { + struct mem_message message; + int index, r; + + static struct option long_options[] = { + {"server", 1, 0, 's'}, + {"port", 1, 0, 'p'}, + {"user", 1, 0, 'u'}, + {"password", 1, 0, 'v'}, + {"from", 1, 0, 'f'}, + {"tls", 0, 0, 'S'}, + {"no-esmtp", 0, 0, 'E'}, + }; + + while(1) { + if ((r = getopt_long(argc, argv, "s:p:u:v:f:SE", long_options, &index)) < 0) + break; + switch (r) { + case 's': + if (smtp_server != NULL) + free(smtp_server); + smtp_server = strdup(optarg); + break; + case 'p': + smtp_port = strtoul(optarg, NULL, 10); + break; + case 'u': + if (smtp_user != NULL) + free(smtp_user); + smtp_user = strdup(optarg); + break; + case 'v': + if (smtp_password != NULL) + free(smtp_password); + smtp_password = strdup(optarg); + break; + case 'f': + if (smtp_from != NULL) + free(smtp_from); + smtp_from = strdup(optarg); + break; + case 'S': + smtp_tls = 1; + break; + case 'E': + smtp_esmtp = 0; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + fprintf(stderr, "usage: smtpsend [-f from] [-u user] [-v password] [-s server] [-p port] [-S] <rcpts>...\n"); + return EXIT_FAILURE; + } + + if (smtp_from == NULL && (smtp_from = guessfrom()) == NULL) { + fprintf(stderr, "can't guess a valid from, please use -f option.\n"); + return EXIT_FAILURE; + } + + /* reads message from stdin */ + if (collect(&message)) + return EXIT_FAILURE; + + send_message(message.data, message.len, argv); + + release(&message); + return EXIT_SUCCESS; +} |