diff options
-rw-r--r-- | OPS | 2 | ||||
-rw-r--r-- | compose.c | 23 | ||||
-rw-r--r-- | curs_main.c | 9 | ||||
-rw-r--r-- | functions.h | 3 | ||||
-rw-r--r-- | lib.c | 1 | ||||
-rw-r--r-- | mutt.h | 2 | ||||
-rw-r--r-- | parse.c | 10 | ||||
-rw-r--r-- | postpone.c | 150 | ||||
-rw-r--r-- | protos.h | 4 | ||||
-rw-r--r-- | send.c | 73 | ||||
-rw-r--r-- | sendlib.c | 39 |
11 files changed, 183 insertions, 133 deletions
@@ -32,6 +32,7 @@ OP_COMPOSE_RENAME_FILE "rename/move an attached file" OP_COMPOSE_SEND_MESSAGE "send the message" OP_COMPOSE_TOGGLE_UNLINK "toggle whether to delete file after sending it" OP_COMPOSE_UPDATE_ENCODING "update an attachment's encoding info" +OP_COMPOSE_WRITE_MESSAGE "write the message to a folder" OP_COPY_MESSAGE "copy a message to a file/mailbox" OP_CREATE_ALIAS "create an alias from a message sender" OP_CURRENT_BOTTOM "move entry to bottom of screen" @@ -45,6 +46,7 @@ OP_DELETE_THREAD "delete all messages in thread" OP_DISPLAY_ADDRESS "display full address of sender" OP_DISPLAY_HEADERS "display message with full headers" OP_DISPLAY_MESSAGE "display a message" +OP_EDIT_MESSAGE "edit the current message for resending" OP_EDITOR_BACKSPACE "delete the char in front of the cursor" OP_EDITOR_BACKWARD_CHAR "move the cursor one character to the left" OP_EDITOR_BOL "jump to the beginning of the line" @@ -414,7 +414,7 @@ static void update_idx (MUTTMENU *menu, ATTACHPTR **idx, short idxlen) * 0 normal exit * -1 abort message */ -int mutt_send_menu (HEADER *msg, /* structure for new message */ +int mutt_compose_menu (HEADER *msg, /* structure for new message */ char *fcc, /* where to save a copy of the message */ size_t fcclen, HEADER *cur) /* current message */ @@ -1055,7 +1055,26 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ mutt_update_encoding(msg->content); break; - + case OP_COMPOSE_WRITE_MESSAGE: + + fname[0] = '\0'; + if (idxlen) + msg->content = idx[0]->content; + if (mutt_enter_fname ("Write message to mailbox", fname, sizeof (fname), + &menu->redraw, 1) != -1 && fname[0]) + { + mutt_message ("Writing message to %s ...", fname); + mutt_expand_path (fname, sizeof (fname)); + + if (msg->content->next) + msg->content = mutt_make_multipart (msg->content); + + if (mutt_write_fcc (NONULL (fname), msg, NULL, 2) < 0) + msg->content = mutt_remove_multipart (msg->content); + else + mutt_message ("Message written."); + } + break; #ifdef _PGPPATH case OP_COMPOSE_PGP_MENU: diff --git a/curs_main.c b/curs_main.c index 2fcad670..ec8652bd 100644 --- a/curs_main.c +++ b/curs_main.c @@ -1481,6 +1481,15 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */) unset_option (OPTFORCEREDRAWPAGER); break; + case OP_EDIT_MESSAGE: + + CHECK_MSGCOUNT; + CHECK_READONLY; + + ci_send_message (SENDEDITMSG, NULL, NULL, Context, CURHDR); + menu->redraw = REDRAW_FULL; + break; + case OP_FORWARD_MESSAGE: CHECK_MSGCOUNT; diff --git a/functions.h b/functions.h index 5a23db62..6b967116 100644 --- a/functions.h +++ b/functions.h @@ -77,6 +77,7 @@ struct binding_t OpMain[] = { { "delete-pattern", OP_MAIN_DELETE_PATTERN, "D" }, { "delete-thread", OP_DELETE_THREAD, "\004" }, { "delete-subthread", OP_DELETE_SUBTHREAD, "\033d" }, + { "edit-message", OP_EDIT_MESSAGE, "e" }, { "forward-message", OP_FORWARD_MESSAGE, "f" }, { "flag-message", OP_FLAG_MESSAGE, "F" }, { "group-reply", OP_GROUP_REPLY, "g" }, @@ -152,6 +153,7 @@ struct binding_t OpPager[] = { { "delete-message", OP_DELETE, "d" }, { "delete-thread", OP_DELETE_THREAD, "\004" }, { "delete-subthread", OP_DELETE_SUBTHREAD, "\033d" }, + { "edit-message", OP_EDIT_MESSAGE, "e" }, { "forward-message", OP_FORWARD_MESSAGE, "f" }, { "flag-message", OP_FLAG_MESSAGE, "F" }, { "group-reply", OP_GROUP_REPLY, "g" }, @@ -282,6 +284,7 @@ struct binding_t OpCompose[] = { { "edit-subject", OP_COMPOSE_EDIT_SUBJECT, "s" }, { "edit-to", OP_COMPOSE_EDIT_TO, "t" }, { "edit-type", OP_COMPOSE_EDIT_TYPE, "\024" }, + { "write-fcc", OP_COMPOSE_WRITE_MESSAGE, "w" }, { "toggle-unlink", OP_COMPOSE_TOGGLE_UNLINK, "u" }, { "update-encoding", OP_COMPOSE_UPDATE_ENCODING, "U" }, { "view-attach", OP_VIEW_ATTACH, M_ENTER_S }, @@ -454,6 +454,7 @@ void mutt_free_envelope (ENVELOPE **p) rfc822_free_address (&(*p)->mail_followup_to); safe_free ((void **) &(*p)->subject); safe_free ((void **) &(*p)->message_id); + safe_free ((void **) &(*p)->date); mutt_free_list (&(*p)->references); mutt_free_list (&(*p)->userhdrs); safe_free ((void **) p); @@ -233,6 +233,7 @@ enum #define SENDBATCH (1<<5) #define SENDMAILX (1<<6) #define SENDKEY (1<<7) +#define SENDEDITMSG (1<<8) /* boolean vars */ enum @@ -397,6 +398,7 @@ typedef struct envelope char *real_subj; /* offset of the real subject */ char *message_id; char *supersedes; + char *date; LIST *references; /* message references (in reverse order) */ LIST *userhdrs; /* user defined headers */ } ENVELOPE; @@ -969,6 +969,8 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr) case 'd': if (!strcasecmp ("ate", line + 1)) { + safe_free((void **)&e->date); + e->date = safe_strdup(p); if (hdr) hdr->date_sent = parse_date (p, hdr); matched = 1; @@ -1067,7 +1069,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr) if (d) hdr->received = parse_date (d + 1, NULL); } - matched = 1; } break; @@ -1151,11 +1152,8 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr) break; } - /* if hdr==NULL, then we are using this to parse either a postponed - * message, or a outgoing message (edit_hdrs), so we want to keep - * track of the user-defined headers - */ - if (!matched && !hdr) + /* Keep track of the user-defined headers */ + if (!matched) { if (last) { @@ -166,12 +166,10 @@ static HEADER *select_msg (void) int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur) { HEADER *h; - MESSAGE *msg; int code = SENDPOSTPONED; LIST *tmp; LIST *last = NULL; LIST *next; - char file[_POSIX_PATH_MAX]; char *p; int opt_delete; @@ -206,83 +204,13 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur) return (-1); } - if ((msg = mx_open_message (PostContext, h->msgno)) == NULL) - { - mx_close_mailbox (PostContext); - safe_free ((void **) &PostContext); - return (-1); - } - - fseek (msg->fp, h->offset, 0); - hdr->env = mutt_read_rfc822_header (msg->fp, NULL); - - if (h->content->type == TYPEMESSAGE || h->content->type == TYPEMULTIPART) - { - BODY *b; - - fseek (msg->fp, h->content->offset, 0); - - if (h->content->type == TYPEMULTIPART) - { - h->content->parts = mutt_parse_multipart (msg->fp, - mutt_get_parameter ("boundary", h->content->parameter), - h->content->offset + h->content->length, - strcasecmp ("digest", h->content->subtype) == 0); - } - else - h->content->parts = mutt_parse_messageRFC822 (msg->fp, h->content); - - /* Now that we know what was in the other message, convert to the new - * message. - */ - hdr->content = h->content->parts; - b = h->content->parts; - while (b != NULL) - { - file[0] = '\0'; - if (b->filename) - strfcpy (file, b->filename, sizeof (file)); - else - /* avoid Content-Disposition: header with temporary filename */ - b->use_disp = 0; - - mutt_adv_mktemp (file, sizeof(file)); - if (mutt_save_attachment (msg->fp, b, file, 0, NULL) == -1) - { - mutt_free_envelope (&hdr->env); - mutt_free_body (&hdr->content); - mx_close_message (&msg); - mx_fastclose_mailbox (PostContext); - safe_free ((void **) &PostContext); - return (-1); - } - safe_free ((void *) &b->filename); - b->filename = safe_strdup (file); - b->unlink = 1; - mutt_free_body (&b->parts); - mutt_stamp_attachment(b); - b = b->next; - } - h->content->parts = NULL; - } - else + if (mutt_edit_message (PostContext, hdr, h) < 0) { - mutt_mktemp (file); - if (mutt_save_attachment (msg->fp, h->content, file, 0, NULL) == -1) - { - mutt_free_envelope (&hdr->env); - mx_close_message (&msg); mx_fastclose_mailbox (PostContext); safe_free ((void **) &PostContext); return (-1); - } - hdr->content = mutt_make_file_attach (file); - hdr->content->use_disp = 0; /* no content-disposition */ - hdr->content->unlink = 1; /* delete when we are done */ } - mx_close_message (&msg); - /* finished with this message, so delete it. */ mutt_set_flag (PostContext, h, M_DELETE, 1); @@ -438,3 +366,79 @@ int mutt_parse_pgp_hdr (char *p, int set_signas) return pgp; } #endif /* _PGPPATH */ + + + +int mutt_edit_message (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr) +{ + MESSAGE *msg = mx_open_message (ctx, hdr->msgno); + char file[_POSIX_PATH_MAX]; + + if (msg == NULL) + return (-1); + + fseek (msg->fp, hdr->offset, 0); + newhdr->env = mutt_read_rfc822_header (msg->fp, newhdr); + + if (hdr->content->type == TYPEMESSAGE || hdr->content->type == TYPEMULTIPART) + { + BODY *b; + + fseek (msg->fp, hdr->content->offset, 0); + + if (hdr->content->type == TYPEMULTIPART) + { + hdr->content->parts = mutt_parse_multipart (msg->fp, + mutt_get_parameter ("boundary", hdr->content->parameter), + hdr->content->offset + hdr->content->length, + strcasecmp ("digest", hdr->content->subtype) == 0); + } + else + hdr->content->parts = mutt_parse_messageRFC822 (msg->fp, hdr->content); + + /* Now that we know what was in the other message, convert to the new + * message. + */ + newhdr->content = hdr->content->parts; + b = hdr->content->parts; + while (b != NULL) + { + file[0] = '\0'; + if (b->filename) + strfcpy (file, b->filename, sizeof (file)); + else + /* avoid Content-Disposition: header with temporary filename */ + b->use_disp = 0; + mutt_adv_mktemp (file, sizeof(file)); + if (mutt_save_attachment (msg->fp, b, file, 0, NULL) == -1) + { + mutt_free_envelope (&newhdr->env); + mutt_free_body (&newhdr->content); + mx_close_message (&msg); + return (-1); + } + safe_free ((void *) &b->filename); + b->filename = safe_strdup (file); + b->unlink = 1; + mutt_free_body (&b->parts); + b = b->next; + } + hdr->content->parts = NULL; + } + else + { + mutt_mktemp (file); + if (mutt_save_attachment (msg->fp, hdr->content, file, 0, NULL) == -1) + { + mutt_free_envelope (&newhdr->env); + mx_close_message (&msg); + return (-1); + } + newhdr->content = mutt_make_file_attach (file); + newhdr->content->use_disp = 0; /* no content-disposition */ + newhdr->content->unlink = 1; /* delete when we are done */ + } + + mx_close_message (&msg); + return 0; +} @@ -79,6 +79,7 @@ ADDRESS *mutt_parse_adrlist (ADDRESS *, const char *); BODY *mutt_dup_body (BODY *); BODY *mutt_make_file_attach (const char *); BODY *mutt_make_message_attach (CONTEXT *, HEADER *, int); +BODY *mutt_remove_multipart (BODY *); BODY *mutt_make_multipart (BODY *); BODY *mutt_new_body (void); BODY *mutt_parse_multipart (FILE *, const char *, long, int); @@ -218,6 +219,7 @@ int mutt_copy_stream (FILE *, FILE *); int mutt_decode_save_attachment (FILE *, BODY *, char *, int, int); int mutt_display_message (HEADER *h, const char *); int mutt_edit_attachment(BODY *); +int mutt_edit_message(CONTEXT *, HEADER *, HEADER *); int mutt_enter_fname (const char *, char *, size_t, int *, int); int mutt_enter_string (unsigned char *, size_t, int, int, int); int mutt_get_field (char *, char *, size_t, int); @@ -254,7 +256,7 @@ int mutt_query_complete (char *, size_t); int mutt_save_attachment (FILE *, BODY *, char *, int, HEADER *); int mutt_save_message (HEADER *, int, int, int, int *); int mutt_search_command (int, int); -int mutt_send_menu (HEADER *, char *, size_t, HEADER *); +int mutt_compose_menu (HEADER *, char *, size_t, HEADER *); int mutt_strcmp (const char *, const char *); int mutt_thread_set_flag (HEADER *, int, int, int); int mutt_view_attachment (FILE*, BODY *, int); @@ -731,20 +731,6 @@ void mutt_set_followup_to (ENVELOPE *e) } } -/* remove the multipart body if it exists */ -static BODY *remove_multipart (BODY *b) -{ - BODY *t; - - if (b->parts) - { - t = b; - b = b->parts; - t->parts = NULL; - mutt_free_body (&t); - } - return b; -} /* look through the recipients of the message we are replying to, and if we find an address that matches $alternates, we use that as the default @@ -884,7 +870,12 @@ ci_send_message (int flags, /* send mode */ { msg = mutt_new_header (); - if (flags == SENDPOSTPONED) + if (flags == SENDEDITMSG) + { + if (mutt_edit_message(ctx, msg, cur) < 0) + goto cleanup; + } + else if (flags == SENDPOSTPONED) { if ((flags = mutt_get_postponed (ctx, msg, &cur)) < 0) goto cleanup; @@ -904,7 +895,7 @@ ci_send_message (int flags, /* send mode */ } } - if (flags & SENDPOSTPONED) + if (flags & (SENDPOSTPONED | SENDEDITMSG)) { if ((tempfp = safe_fopen (msg->content->filename, "a+")) == NULL) { @@ -917,7 +908,7 @@ ci_send_message (int flags, /* send mode */ msg->env = mutt_new_envelope (); } - if (! (flags & (SENDKEY | SENDPOSTPONED))) + if (! (flags & (SENDKEY | SENDPOSTPONED | SENDEDITMSG))) { pbody = mutt_new_body (); pbody->next = msg->content; /* don't kill command-line attachments */ @@ -949,7 +940,7 @@ ci_send_message (int flags, /* send mode */ } /* this is handled here so that the user can match ~f in send-hook */ - if (cur && option (OPTREVNAME)) + if (cur && option (OPTREVNAME) && !(flags & (SENDPOSTPONED | SENDEDITMSG))) { /* we shouldn't have to worry about freeing `msg->env->from' before setting it here since this code will only execute when doing some @@ -958,7 +949,7 @@ ci_send_message (int flags, /* send mode */ msg->env->from = set_reverse_name (cur->env); } - if (!msg->env->from && option (OPTUSEFROM)) + if (!msg->env->from && option (OPTUSEFROM) && !(flags & SENDEDITMSG)) msg->env->from = mutt_default_from (); if (flags & SENDBATCH) @@ -970,7 +961,7 @@ ci_send_message (int flags, /* send mode */ process_user_header (msg->env); } } - else if (! (flags & SENDPOSTPONED)) + else if (! (flags & (SENDPOSTPONED | SENDEDITMSG))) { if ((flags & (SENDREPLY | SENDFORWARD)) && envelope_defaults (msg->env, ctx, cur, flags) == -1) @@ -1036,7 +1027,7 @@ ci_send_message (int flags, /* send mode */ } /* wait until now to set the real name portion of our return address so that $realname can be set in a send-hook */ - if (msg->env->from && !msg->env->from->personal) + if (msg->env->from && !msg->env->from->personal && !(flags & (SENDEDITMSG | SENDPOSTPONED))) msg->env->from->personal = safe_strdup (Realname); @@ -1091,7 +1082,7 @@ ci_send_message (int flags, /* send mode */ mutt_edit_file (Editor, msg->content->filename); } - if (! (flags & (SENDPOSTPONED | SENDFORWARD | SENDKEY))) + if (! (flags & (SENDPOSTPONED | SENDEDITMSG | SENDFORWARD | SENDKEY))) { if (stat (msg->content->filename, &st) == 0) { @@ -1133,7 +1124,8 @@ ci_send_message (int flags, /* send mode */ { main_loop: - if ((i = mutt_send_menu (msg, fcc, sizeof (fcc), cur)) == -1) + i = mutt_compose_menu (msg, fcc, sizeof (fcc), cur); + if (i == -1) { /* abort */ mutt_message ("Mail not sent."); @@ -1144,9 +1136,9 @@ main_loop: /* postpone the message until later. */ if (msg->content->next) msg->content = mutt_make_multipart (msg->content); - if (!Postponed || mutt_write_fcc (Postponed, msg, (cur && (flags & SENDREPLY)) ? cur->env->message_id : NULL, 1) < 0) + if (!Postponed || mutt_write_fcc (NONULL (Postponed), msg, (cur && (flags & SENDREPLY)) ? cur->env->message_id : NULL, 1) < 0) { - msg->content = remove_multipart (msg->content); + msg->content = mutt_remove_multipart (msg->content); goto main_loop; } mutt_message ("Message postponed."); @@ -1210,6 +1202,13 @@ main_loop: } #endif /* _PGPPATH */ + if (flags & SENDEDITMSG) + { + int really_send = mutt_yesorno ("Message edited. Really send?", 1); + if (really_send != M_YES) + goto main_loop; + } + if (!option (OPTNOCURSES) && !(flags & SENDMAILX)) mutt_message ("Sending message..."); @@ -1273,7 +1272,9 @@ main_loop: msg->content = msg->content->parts; } +#ifdef _PGPPATH full_fcc: +#endif /* _PGPPATH */ if (msg->content) mutt_write_fcc (fcc, msg, NULL, 0); msg->content = tmpbody; @@ -1304,16 +1305,13 @@ full_fcc: if (send_message (msg) == -1) { - msg->content = remove_multipart (msg->content); + msg->content = mutt_remove_multipart (msg->content); goto main_loop; } if (!option (OPTNOCURSES) && ! (flags & SENDMAILX)) mutt_message ("Mail sent."); - /* now free up the memory used to generate this message. */ - mutt_free_header (&msg); - if (flags & SENDREPLY) { if (cur) @@ -1326,23 +1324,6 @@ full_fcc: } } - - -#ifdef _PGPPATH - if (flags == SENDPOSTPONED) - { - safe_free((void **) &PgpSignAs); - safe_free((void **) &PgpSignMicalg); - - PgpSignAs = signas; - PgpSignMicalg = signmic; - } -#endif /* _PGPPATH */ - - - - return; /* all done */ - cleanup: @@ -1084,7 +1084,22 @@ BODY *mutt_make_multipart (BODY *b) return new; } -static char *mutt_make_date (char *s) +/* remove the multipart body if it exists */ +BODY *mutt_remove_multipart (BODY *b) +{ + BODY *t; + + if (b->parts) + { + t = b; + b = b->parts; + t->parts = NULL; + mutt_free_body (&t); + } + return b; +} + +static char *mutt_make_date (char *s, size_t len) { time_t t = time (NULL); struct tm *l = gmtime(&t); @@ -1098,7 +1113,7 @@ static char *mutt_make_date (char *s) if (yday != 0) tz += yday * 24 * 60; /* GMT is next or previous day! */ - sprintf (s, "Date: %s, %d %s %d %02d:%02d:%02d %+03d%02d\n", + snprintf (s, len, "Date: %s, %d %s %d %02d:%02d:%02d %+03d%02d\n", Weekdays[l->tm_wday], l->tm_mday, Months[l->tm_mon], l->tm_year+1900, l->tm_hour, l->tm_min, l->tm_sec, tz/60, abs(tz) % 60); return (s); @@ -1186,6 +1201,7 @@ static void write_references (LIST *r, FILE *f) * mode == 1 => "lite" mode (used for edit_hdrs) * mode == 0 => normal mode. write full header + MIME headers * mode == -1 => write just the envelope info (used for postponing messages) + * mode == -2 => just like -1, but write the Date: from the message (used for edit-message support) */ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode) @@ -1194,7 +1210,15 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode) LIST *tmp = env->userhdrs; if (mode == 0) - fputs (mutt_make_date (buffer), fp); + fputs (mutt_make_date (buffer, sizeof(buffer)), fp); + else if (mode == 2) + { + if(env->date) + fprintf(fp, "Date: %s\n", env->date); + else + fputs (mutt_make_date(buffer, sizeof(buffer)), fp); + } + /* OPTUSEFROM is not consulted here so that we can still write a From: * field if the user sets it with the `my_hdr' command @@ -1758,7 +1782,7 @@ void mutt_bounce_message (HEADER *h, ADDRESS *to) fprintf (f, "Resent-From: %s", NONULL(Username)); if((fqdn = mutt_fqdn(1))) fprintf (f, "@%s", fqdn); - fprintf (f, "\nResent-%s", mutt_make_date (date)); + fprintf (f, "\nResent-%s", mutt_make_date (date, sizeof(date))); fputs ("Resent-To: ", f); mutt_write_address_list (to, f, 11); fputc ('\n', f); @@ -1847,7 +1871,12 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post) return (-1); } - mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, (post ? -1 : 0)); + /* post == 1 => postpone message. Set mode = -1 in mutt_write_rfc822_header() + * post == 2 => Editing this message. + * Set mode = -2 in mutt_write_rfc822_header() + * post == 0 => Normal mode. Set mode = 0 in mutt_write_rfc822_header() + * */ + mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, post ? -post : 0); /* (postponment) if this was a reply of some sort, <msgid> contians the * Message-ID: of message replied to. Save it using a special X-Mutt- |