📄 send.c
字号:
/* * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mutt_curses.h"#include "rfc2047.h"#include "keymap.h"#include "mime.h"#include "mailbox.h"#include "copy.h"#include "mx.h"#include "mutt_crypt.h"#include "mutt_idna.h"#include "url.h"#include <ctype.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <sys/stat.h>#include <sys/wait.h>#include <dirent.h>#include <time.h>#include <sys/types.h>#include <utime.h>#ifdef MIXMASTER#include "remailer.h"#endifstatic void append_signature (FILE *f){ FILE *tmpfp; pid_t thepid; if (Signature && (tmpfp = mutt_open_read (Signature, &thepid))) { if (option (OPTSIGDASHES)) fputs ("\n-- \n", f); mutt_copy_stream (tmpfp, f); fclose (tmpfp); if (thepid != -1) mutt_wait_filter (thepid); }}/* compare two e-mail addresses and return 1 if they are equivalent */static int mutt_addrcmp (ADDRESS *a, ADDRESS *b){ if (!a->mailbox || !b->mailbox) return 0; if (ascii_strcasecmp (a->mailbox, b->mailbox)) return 0; return 1;}/* search an e-mail address in a list */static int mutt_addrsrc (ADDRESS *a, ADDRESS *lst){ for (; lst; lst = lst->next) { if (mutt_addrcmp (a, lst)) return (1); } return (0);}/* removes addresses from "b" which are contained in "a" */ADDRESS *mutt_remove_xrefs (ADDRESS *a, ADDRESS *b){ ADDRESS *top, *p, *prev = NULL; top = b; while (b) { for (p = a; p; p = p->next) { if (mutt_addrcmp (p, b)) break; } if (p) { if (prev) { prev->next = b->next; b->next = NULL; rfc822_free_address (&b); b = prev; } else { top = top->next; b->next = NULL; rfc822_free_address (&b); b = top; } } else { prev = b; b = b->next; } } return top;}/* remove any address which matches the current user. if `leave_only' is * nonzero, don't remove the user's address if it is the only one in the list */static ADDRESS *remove_user (ADDRESS *a, int leave_only){ ADDRESS *top = NULL, *last = NULL; while (a) { if (!mutt_addr_is_user (a)) { if (top) { last->next = a; last = last->next; } else last = top = a; a = a->next; last->next = NULL; } else { ADDRESS *tmp = a; a = a->next; if (!leave_only || a || last) { tmp->next = NULL; rfc822_free_address (&tmp); } else last = top = tmp; } } return top;}static ADDRESS *find_mailing_lists (ADDRESS *t, ADDRESS *c){ ADDRESS *top = NULL, *ptr = NULL; for (; t || c; t = c, c = NULL) { for (; t; t = t->next) { if (mutt_is_mail_list (t) && !t->group) { if (top) { ptr->next = rfc822_cpy_adr_real (t); ptr = ptr->next; } else ptr = top = rfc822_cpy_adr_real (t); } } } return top;}static int edit_address (ADDRESS **a, /* const */ char *field){ char buf[HUGE_STRING]; char *err = NULL; int idna_ok = 0; do { buf[0] = 0; mutt_addrlist_to_local (*a); rfc822_write_address (buf, sizeof (buf), *a, 0); if (mutt_get_field (field, buf, sizeof (buf), M_ALIAS) != 0) return (-1); rfc822_free_address (a); *a = mutt_expand_aliases (mutt_parse_adrlist (NULL, buf)); if ((idna_ok = mutt_addrlist_to_idna (*a, &err)) != 0) { mutt_error (_("Error: '%s' is a bad IDN."), err); mutt_refresh (); mutt_sleep (2); FREE (&err); } } while (idna_ok != 0); return 0;}static int edit_envelope (ENVELOPE *en){ char buf[HUGE_STRING]; LIST *uh = UserHeader; if (edit_address (&en->to, "To: ") == -1 || en->to == NULL) return (-1); if (option (OPTASKCC) && edit_address (&en->cc, "Cc: ") == -1) return (-1); if (option (OPTASKBCC) && edit_address (&en->bcc, "Bcc: ") == -1) return (-1); if (en->subject) { if (option (OPTFASTREPLY)) return (0); else strfcpy (buf, en->subject, sizeof (buf)); } else { char *p; buf[0] = 0; for (; uh; uh = uh->next) { if (ascii_strncasecmp ("subject:", uh->data, 8) == 0) { p = uh->data + 8; SKIPWS (p); strncpy (buf, p, sizeof (buf)); } } } if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) != 0 || (!buf[0] && query_quadoption (OPT_SUBJECT, _("No subject, abort?")) != M_NO)) { mutt_message _("No subject, aborting."); return (-1); } mutt_str_replace (&en->subject, buf); return 0;}static void process_user_recips (ENVELOPE *env){ LIST *uh = UserHeader; for (; uh; uh = uh->next) { if (ascii_strncasecmp ("to:", uh->data, 3) == 0) env->to = rfc822_parse_adrlist (env->to, uh->data + 3); else if (ascii_strncasecmp ("cc:", uh->data, 3) == 0) env->cc = rfc822_parse_adrlist (env->cc, uh->data + 3); else if (ascii_strncasecmp ("bcc:", uh->data, 4) == 0) env->bcc = rfc822_parse_adrlist (env->bcc, uh->data + 4); }}static void process_user_header (ENVELOPE *env){ LIST *uh = UserHeader; LIST *last = env->userhdrs; if (last) while (last->next) last = last->next; for (; uh; uh = uh->next) { if (ascii_strncasecmp ("from:", uh->data, 5) == 0) { /* User has specified a default From: address. Remove default address */ rfc822_free_address (&env->from); env->from = rfc822_parse_adrlist (env->from, uh->data + 5); } else if (ascii_strncasecmp ("reply-to:", uh->data, 9) == 0) { rfc822_free_address (&env->reply_to); env->reply_to = rfc822_parse_adrlist (env->reply_to, uh->data + 9); } else if (ascii_strncasecmp ("message-id:", uh->data, 11) == 0) mutt_str_replace (&env->message_id, uh->data + 11); else if (ascii_strncasecmp ("to:", uh->data, 3) != 0 && ascii_strncasecmp ("cc:", uh->data, 3) != 0 && ascii_strncasecmp ("bcc:", uh->data, 4) != 0 && ascii_strncasecmp ("subject:", uh->data, 8) != 0) { if (last) { last->next = mutt_new_list (); last = last->next; } else last = env->userhdrs = mutt_new_list (); last->data = safe_strdup (uh->data); } }}LIST *mutt_copy_list (LIST *p){ LIST *t, *r=NULL, *l=NULL; for (; p; p = p->next) { t = (LIST *) safe_malloc (sizeof (LIST)); t->data = safe_strdup (p->data); t->next = NULL; if (l) { r->next = t; r = r->next; } else l = r = t; } return (l);}void mutt_forward_intro (FILE *fp, HEADER *cur){ char buffer[STRING]; fputs ("----- Forwarded message from ", fp); buffer[0] = 0; rfc822_write_address (buffer, sizeof (buffer), cur->env->from, 1); fputs (buffer, fp); fputs (" -----\n\n", fp);}void mutt_forward_trailer (FILE *fp){ fputs ("\n----- End forwarded message -----\n", fp);}static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out){ int chflags = CH_DECODE, cmflags = 0; mutt_parse_mime_message (ctx, cur); mutt_message_hook (ctx, cur, M_MESSAGEHOOK); if (WithCrypto && (cur->security & ENCRYPT) && option (OPTFORWDECODE)) { /* make sure we have the user's passphrase before proceeding... */ crypt_valid_passphrase (cur->security); } mutt_forward_intro (out, cur); if (option (OPTFORWDECODE)) { cmflags |= M_CM_DECODE | M_CM_CHARCONV; if (option (OPTWEED)) { chflags |= CH_WEED | CH_REORDER; cmflags |= M_CM_WEED; } } if (option (OPTFORWQUOTE)) cmflags |= M_CM_PREFIX; mutt_copy_message (out, ctx, cur, cmflags, chflags); mutt_forward_trailer (out); return 0;}void mutt_make_attribution (CONTEXT *ctx, HEADER *cur, FILE *out){ char buffer[STRING]; if (Attribution) { mutt_make_string (buffer, sizeof (buffer), Attribution, ctx, cur); fputs (buffer, out); fputc ('\n', out); }}void mutt_make_post_indent (CONTEXT *ctx, HEADER *cur, FILE *out){ char buffer[STRING]; if (PostIndentString) { mutt_make_string (buffer, sizeof (buffer), PostIndentString, ctx, cur); fputs (buffer, out); fputc ('\n', out); }}static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out){ int cmflags = M_CM_PREFIX | M_CM_DECODE | M_CM_CHARCONV | M_CM_REPLYING; int chflags = CH_DECODE; if (WithCrypto && (cur->security & ENCRYPT)) { /* make sure we have the user's passphrase before proceeding... */ crypt_valid_passphrase (cur->security); } mutt_parse_mime_message (ctx, cur); mutt_message_hook (ctx, cur, M_MESSAGEHOOK); mutt_make_attribution (ctx, cur, out); if (!option (OPTHEADER)) cmflags |= M_CM_NOHEADER; if (option (OPTWEED)) { chflags |= CH_WEED | CH_REORDER; cmflags |= M_CM_WEED; } mutt_copy_message (out, ctx, cur, cmflags, chflags); mutt_make_post_indent (ctx, cur, out); return 0;}static int default_to (ADDRESS **to, ENVELOPE *env, int flags, int hmfupto){ char prompt[STRING]; if (flags && env->mail_followup_to && hmfupto == M_YES) { rfc822_append (to, env->mail_followup_to); return 0; } /* Exit now if we're setting up the default Cc list for list-reply * (only set if Mail-Followup-To is present and honoured). */ if (flags & SENDLISTREPLY) return 0; if (!option(OPTREPLYSELF) && mutt_addr_is_user (env->from)) { /* mail is from the user, assume replying to recipients */ rfc822_append (to, env->to); } else if (env->reply_to) { if ((mutt_addrcmp (env->from, env->reply_to) && !env->reply_to->next) || (option (OPTIGNORELISTREPLYTO) && mutt_is_mail_list (env->reply_to) && (mutt_addrsrc (env->reply_to, env->to) || mutt_addrsrc (env->reply_to, env->cc)))) { /* If the Reply-To: address is a mailing list, assume that it was * put there by the mailing list, and use the From: address * * We also take the from header if our correspondant has a reply-to * header which is identical to the electronic mail address given * in his From header. * */ rfc822_append (to, env->from); } else if (!(mutt_addrcmp (env->from, env->reply_to) && !env->reply_to->next) && quadoption (OPT_REPLYTO) != M_YES) { /* There are quite a few mailing lists which set the Reply-To: * header field to the list address, which makes it quite impossible * to send a message to only the sender of the message. This * provides a way to do that. */ snprintf (prompt, sizeof (prompt), _("Reply to %s%s?"), env->reply_to->mailbox, env->reply_to->next?",...":""); switch (query_quadoption (OPT_REPLYTO, prompt)) { case M_YES: rfc822_append (to, env->reply_to); break; case M_NO: rfc822_append (to, env->from); break; default: return (-1); /* abort */ } } else rfc822_append (to, env->reply_to); } else rfc822_append (to, env->from); return (0);}int mutt_fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags){ char prompt[STRING]; ADDRESS *tmp; int hmfupto = -1; if ((flags & (SENDLISTREPLY|SENDGROUPREPLY)) && in->mail_followup_to) { snprintf (prompt, sizeof (prompt), _("Follow-up to %s%s?"), in->mail_followup_to->mailbox, in->mail_followup_to->next ? ",..." : ""); if ((hmfupto = query_quadoption (OPT_MFUPTO, prompt)) == -1) return -1; } if (flags & SENDLISTREPLY) { tmp = find_mailing_lists (in->to, in->cc); rfc822_append (&out->to, tmp); rfc822_free_address (&tmp); if (in->mail_followup_to && hmfupto == M_YES && default_to (&out->cc, in, flags & SENDLISTREPLY, hmfupto) == -1) return (-1); /* abort */ } else { if (default_to (&out->to, in, flags & SENDGROUPREPLY, hmfupto) == -1) return (-1); /* abort */ if ((flags & SENDGROUPREPLY) && (!in->mail_followup_to || hmfupto != M_YES)) { /* if(!mutt_addr_is_user(in->to)) */ rfc822_append (&out->cc, in->to); rfc822_append (&out->cc, in->cc); } } return 0;}LIST *mutt_make_references(ENVELOPE *e){ LIST *t = NULL, *l = NULL; if (e->references) l = mutt_copy_list (e->references); else l = mutt_copy_list (e->in_reply_to); if (e->message_id) { t = mutt_new_list(); t->data = safe_strdup(e->message_id); t->next = l; l = t; } return l;}void mutt_fix_reply_recipients (ENVELOPE *env){ mutt_expand_aliases_env (env); if (! option (OPTMETOO)) { /* the order is important here. do the CC: first so that if the * the user is the only recipient, it ends up on the TO: field */ env->cc = remove_user (env->cc, (env->to == NULL)); env->to = remove_user (env->to, (env->cc == NULL)); } /* the CC field can get cluttered, especially with lists */ env->to = mutt_remove_duplicates (env->to); env->cc = mutt_remove_duplicates (env->cc); env->cc = mutt_remove_xrefs (env->to, env->cc); if (env->cc && !env->to) { env->to = env->cc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -