📄 sendlib.c
字号:
if (waitpid (pid, &st, 0) > 0) { st = WIFEXITED (st) ? WEXITSTATUS (st) : S_ERR; if (SendmailWait && st == (0xff & EX_OK)) { unlink (*tempfile); /* no longer needed */ FREE (tempfile); /* __FREE_CHECKED__ */ } } else { st = (SendmailWait > 0 && errno == EINTR && SigAlrm) ? S_BKG : S_ERR; if (SendmailWait > 0) { unlink (*tempfile); FREE (tempfile); /* __FREE_CHECKED__ */ } } /* reset alarm; not really needed, but... */ alarm (0); sigaction (SIGALRM, &oldalrm, NULL); if (kill (ppid, 0) == -1 && errno == ESRCH) { /* the parent is already dead */ unlink (*tempfile); FREE (tempfile); /* __FREE_CHECKED__ */ } _exit (st); } sigprocmask (SIG_UNBLOCK, &set, NULL); if (pid != -1 && waitpid (pid, &st, 0) > 0) st = WIFEXITED (st) ? WEXITSTATUS (st) : S_ERR; /* return child status */ else st = S_ERR; /* error */ mutt_unblock_signals_system (1); return (st);}static char **add_args (char **args, size_t *argslen, size_t *argsmax, ADDRESS *addr){ for (; addr; addr = addr->next) { /* weed out group mailboxes, since those are for display only */ if (addr->mailbox && !addr->group) { if (*argslen == *argsmax) safe_realloc (&args, (*argsmax += 5) * sizeof (char *)); args[(*argslen)++] = addr->mailbox; } } return (args);}static char **add_option (char **args, size_t *argslen, size_t *argsmax, char *s){ if (*argslen == *argsmax) safe_realloc (&args, (*argsmax += 5) * sizeof (char *)); args[(*argslen)++] = s; return (args);}intmutt_invoke_sendmail (ADDRESS *from, /* the sender */ ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, /* recips */ const char *msg, /* file containing message */ int eightbit) /* message contains 8bit chars */{ char *ps = NULL, *path = NULL, *s = safe_strdup (Sendmail), *childout = NULL; char **args = NULL; size_t argslen = 0, argsmax = 0; int i; ps = s; i = 0; while ((ps = strtok (ps, " "))) { if (argslen == argsmax) safe_realloc (&args, sizeof (char *) * (argsmax += 5)); if (i) args[argslen++] = ps; else { path = safe_strdup (ps); ps = strrchr (ps, '/'); if (ps) ps++; else ps = path; args[argslen++] = ps; } ps = NULL; i++; } if (eightbit && option (OPTUSE8BITMIME)) args = add_option (args, &argslen, &argsmax, "-B8BITMIME"); if (option (OPTENVFROM)) { if (EnvFrom) { args = add_option (args, &argslen, &argsmax, "-f"); args = add_args (args, &argslen, &argsmax, EnvFrom); } else if (from && !from->next) { args = add_option (args, &argslen, &argsmax, "-f"); args = add_args (args, &argslen, &argsmax, from); } } if (DsnNotify) { args = add_option (args, &argslen, &argsmax, "-N"); args = add_option (args, &argslen, &argsmax, DsnNotify); } if (DsnReturn) { args = add_option (args, &argslen, &argsmax, "-R"); args = add_option (args, &argslen, &argsmax, DsnReturn); } args = add_option (args, &argslen, &argsmax, "--"); args = add_args (args, &argslen, &argsmax, to); args = add_args (args, &argslen, &argsmax, cc); args = add_args (args, &argslen, &argsmax, bcc); if (argslen == argsmax) safe_realloc (&args, sizeof (char *) * (++argsmax)); args[argslen++] = NULL; if ((i = send_msg (path, args, msg, &childout)) != (EX_OK & 0xff)) { if (i != S_BKG) { const char *e = mutt_strsysexit (i); e = mutt_strsysexit (i); mutt_error (_("Error sending message, child exited %d (%s)."), i, NONULL (e)); if (childout) { struct stat st; if (stat (childout, &st) == 0 && st.st_size > 0) mutt_do_pager (_("Output of the delivery process"), childout, 0, NULL); } } } else unlink (childout); FREE (&childout); FREE (&path); FREE (&s); FREE (&args); if (i == (EX_OK & 0xff)) i = 0; else if (i == S_BKG) i = 1; else i = -1; return (i);}/* appends string 'b' to string 'a', and returns the pointer to the new string. */char *mutt_append_string (char *a, const char *b){ size_t la = mutt_strlen (a); safe_realloc (&a, la + mutt_strlen (b) + 1); strcpy (a + la, b); /* __STRCPY_CHECKED__ */ return (a);}/* returns 1 if char `c' needs to be quoted to protect from shell interpretation when executing commands in a subshell */#define INVALID_CHAR(c) (!isalnum ((unsigned char)c) && !strchr ("@.+-_,:", c))/* returns 1 if string `s' contains characters which could cause problems when used on a command line to execute a command */int mutt_needs_quote (const char *s){ while (*s) { if (INVALID_CHAR (*s)) return 1; s++; } return 0;}/* Quote a string to prevent shell escapes when this string is used on the command line to send mail. */char *mutt_quote_string (const char *s){ char *r, *pr; size_t rlen; rlen = mutt_strlen (s) + 3; pr = r = (char *) safe_malloc (rlen); *pr++ = '"'; while (*s) { if (INVALID_CHAR (*s)) { size_t o = pr - r; safe_realloc (&r, ++rlen); pr = r + o; *pr++ = '\\'; } *pr++ = *s++; } *pr++ = '"'; *pr = 0; return (r);}/* For postponing (!final) do the necessary encodings only */void mutt_prepare_envelope (ENVELOPE *env, int final){ char buffer[LONG_STRING]; if (final) { if (env->bcc && !(env->to || env->cc)) { /* some MTA's will put an Apparently-To: header field showing the Bcc: * recipients if there is no To: or Cc: field, so attempt to suppress * it by using an empty To: field. */ env->to = rfc822_new_address (); env->to->group = 1; env->to->next = rfc822_new_address (); buffer[0] = 0; rfc822_cat (buffer, sizeof (buffer), "undisclosed-recipients", RFC822Specials); env->to->mailbox = safe_strdup (buffer); } mutt_set_followup_to (env); if (!env->message_id) env->message_id = mutt_gen_msgid (); } /* Take care of 8-bit => 7-bit conversion. */ rfc2047_encode_adrlist (env->to, "To"); rfc2047_encode_adrlist (env->cc, "Cc"); rfc2047_encode_adrlist (env->bcc, "Bcc"); rfc2047_encode_adrlist (env->from, "From"); rfc2047_encode_adrlist (env->mail_followup_to, "Mail-Followup-To"); rfc2047_encode_adrlist (env->reply_to, "Reply-To"); if (env->subject) { rfc2047_encode_string (&env->subject); } encode_headers (env->userhdrs);}void mutt_unprepare_envelope (ENVELOPE *env){ LIST *item; for (item = env->userhdrs; item; item = item->next) rfc2047_decode (&item->data); rfc822_free_address (&env->mail_followup_to); /* back conversions */ rfc2047_decode_adrlist (env->to); rfc2047_decode_adrlist (env->cc); rfc2047_decode_adrlist (env->bcc); rfc2047_decode_adrlist (env->from); rfc2047_decode_adrlist (env->reply_to); rfc2047_decode (&env->subject);}static int _mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to, const char *resent_from, ADDRESS *env_from){ int i, ret = 0; FILE *f; char date[SHORT_STRING], tempfile[_POSIX_PATH_MAX]; MESSAGE *msg = NULL; if (!h) { /* Try to bounce each message out, aborting if we get any failures. */ for (i=0; i<Context->msgcount; i++) if (Context->hdrs[i]->tagged) ret |= _mutt_bounce_message (fp, Context->hdrs[i], to, resent_from, env_from); return ret; } /* If we failed to open a message, return with error */ if (!fp && (msg = mx_open_message (Context, h->msgno)) == NULL) return -1; if (!fp) fp = msg->fp; mutt_mktemp (tempfile); if ((f = safe_fopen (tempfile, "w")) != NULL) { int ch_flags = CH_XMIT | CH_NONEWLINE | CH_NOQFROM; if (!option (OPTBOUNCEDELIVERED)) ch_flags |= CH_WEED_DELIVERED; fseeko (fp, h->offset, 0); fprintf (f, "Resent-From: %s", resent_from); fprintf (f, "\nResent-%s", mutt_make_date (date, sizeof(date))); fprintf (f, "Resent-Message-ID: %s\n", mutt_gen_msgid()); fputs ("Resent-To: ", f); mutt_write_address_list (to, f, 11, 0); mutt_copy_header (fp, h, f, ch_flags, NULL); fputc ('\n', f); mutt_copy_bytes (fp, f, h->content->length); fclose (f); ret = mutt_invoke_sendmail (env_from, to, NULL, NULL, tempfile, h->content->encoding == ENC8BIT); } if (msg) mx_close_message (&msg); return ret;}int mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to){ ADDRESS *from; const char *fqdn = mutt_fqdn (1); char resent_from[STRING]; int ret; char *err; resent_from[0] = '\0'; from = mutt_default_from (); if (fqdn) rfc822_qualify (from, fqdn); rfc2047_encode_adrlist (from, "Resent-From"); if (mutt_addrlist_to_idna (from, &err)) { mutt_error (_("Bad IDN %s while preparing resent-from."), err); return -1; } rfc822_write_address (resent_from, sizeof (resent_from), from, 0); ret = _mutt_bounce_message (fp, h, to, resent_from, from); rfc822_free_address (&from); return ret;}/* given a list of addresses, return a list of unique addresses */ADDRESS *mutt_remove_duplicates (ADDRESS *addr){ ADDRESS *top = addr; ADDRESS **last = ⊤ ADDRESS *tmp; int dup; while (addr) { for (tmp = top, dup = 0; tmp && tmp != addr; tmp = tmp->next) { if (tmp->mailbox && addr->mailbox && !ascii_strcasecmp (addr->mailbox, tmp->mailbox)) { dup = 1; break; } } if (dup) { dprint (2, (debugfile, "mutt_remove_duplicates: Removing %s\n", addr->mailbox)); *last = addr->next; addr->next = NULL; rfc822_free_address(&addr); addr = *last; } else { last = &addr->next; addr = addr->next; } } return (top);}static void set_noconv_flags (BODY *b, short flag){ for(; b; b = b->next) { if (b->type == TYPEMESSAGE || b->type == TYPEMULTIPART) set_noconv_flags (b->parts, flag); else if (b->type == TYPETEXT && b->noconv) { if (flag) mutt_set_parameter ("x-mutt-noconv", "yes", &b->parameter); else mutt_delete_parameter ("x-mutt-noconv", &b->parameter); } }}int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post, char *fcc){ CONTEXT f; MESSAGE *msg; char tempfile[_POSIX_PATH_MAX]; FILE *tempfp = NULL; int r; if (post) set_noconv_flags (hdr->content, 1); if (mx_open_mailbox (path, M_APPEND | M_QUIET, &f) == NULL) { dprint (1, (debugfile, "mutt_write_fcc(): unable to open mailbox %s in append-mode, aborting.\n", path)); return (-1); } /* We need to add a Content-Length field to avoid problems where a line in * the message body begins with "From " */ if (f.magic == M_MMDF || f.magic == M_MBOX) { mutt_mktemp (tempfile); if ((tempfp = safe_fopen (tempfile, "w+")) == NULL) { mutt_perror (tempfile); mx_close_mailbox (&f, NULL); return (-1); } } hdr->read = !post; /* make sure to put it in the `cur' directory (maildir) */ if ((msg = mx_open_new_message (&f, hdr, M_ADD_FROM)) == NULL) { mx_close_mailbox (&f, NULL); return (-1); } /* post == 1 => postpone message. Set mode = -1 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, 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- * header so it can be picked up if the message is recalled at a later * point in time. This will allow the message to be marked as replied if * the same mailbox is still open. */ if (post && msgid) fprintf (msg->fp, "X-Mutt-References: %s\n", msgid); /* (postponment) save the Fcc: using a special X-Mutt- header so that * it can be picked up when the message is recalled */ if (post && fcc) fprintf (msg->fp, "X-Mutt-Fcc: %s\n", fcc); fprintf (msg->fp, "Status: RO\n"); /* (postponment) if the mail is to be signed or encrypted, save this info */ if ((WithCrypto & APPLICATION_PGP) && post && (hdr->security & APPLICATION_PGP)) { fputs ("X-Mutt-PGP: ", msg->fp); if (hdr->security & ENCRYPT) fputc ('E', msg->fp); if (hdr->security & SIGN) { fputc ('S', msg->fp); if (PgpSignAs && *PgpSignAs) fprintf (msg->fp, "<%s>", PgpSignAs); } if (hdr->security & INLINE) fputc ('I', msg->fp); fputc ('\n', msg->fp); } /* (postponment) if the mail is to be signed or encrypted, save this info */ if ((WithCrypto & APPLICATION_SMIME) && post && (hdr->security & APPLICATION_SMIME)) { fputs ("X-Mutt-SMIME: ", msg->fp); if (hdr->security & ENCRYPT) { fputc ('E', msg->fp); if (SmimeCryptAlg && *SmimeCryptAlg) fprintf (msg->fp, "C<%s>", SmimeCryptAlg); } if (hdr->security & SIGN) { fputc ('S', msg->fp); if (SmimeDefaultKey && *SmimeDefaultKey) fprintf (msg->fp, "<%s>", SmimeDefaultKey); } if (hdr->security & INLINE) fputc ('I', msg->fp); fputc ('\n', msg->fp); }#ifdef MIXMASTER /* (postponement) if the mail is to be sent through a mixmaster * chain, save that information */ if (post && hdr->chain && hdr->chain) { LIST *p; fputs ("X-Mutt-Mix:", msg->fp); for (p = hdr->chain; p; p = p->next) fprintf (msg->fp, " %s", (char *) p->data); fputc ('\n', msg->fp); }#endif if (tempfp) { char sasha[LONG_STRING]; int lines = 0; mutt_write_mime_body (hdr->content, tempfp); /* make sure the last line ends with a newline. Emacs doesn't ensure * this will happen, and it can cause problems parsing the mailbox * later. */ fseek (tempfp, -1, 2); if (fgetc (tempfp) != '\n') { fseek (tempfp, 0, 2); fputc ('\n', tempfp); } fflush (tempfp); if (ferror (tempfp)) { dprint (1, (debugfile, "mutt_write_fcc(): %s: write failed.\n", tempfile)); fclose (tempfp); unlink (tempfile); mx_commit_message (msg, &f); /* XXX - really? */ mx_close_message (&msg); mx_close_mailbox (&f, NULL); return -1; } /* count the number of lines */ rewind (tempfp); while (fgets (sasha, sizeof (sasha), tempfp) != NULL) lines++; fprintf (msg->fp, "Content-Length: " OFF_T_FMT "\n", ftello (tempfp)); fprintf (msg->fp, "Lines: %d\n\n", lines); /* copy the body and clean up */ rewind (tempfp); r = mutt_copy_stream (tempfp, msg->fp); if (fclose (tempfp) != 0) r = -1; /* if there was an error, leave the temp version */ if (!r) unlink (tempfile); } else { fputc ('\n', msg->fp); /* finish off the header */ r = mutt_write_mime_body (hdr->content, msg->fp); } if (mx_commit_message (msg, &f) != 0) r = -1; mx_close_message (&msg); mx_close_mailbox (&f, NULL); if (post) set_noconv_flags (hdr->content, 0); return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -