NeoMutt  2018-07-16 +2225-8687db
Teaching an old dog new tricks
DOXYGEN
send.c File Reference

Prepare and send an email. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "mutt.h"
#include "send.h"
#include "alias.h"
#include "compose.h"
#include "context.h"
#include "copy.h"
#include "core/lib.h"
#include "curs_lib.h"
#include "edit.h"
#include "filter.h"
#include "globals.h"
#include "handler.h"
#include "hdrline.h"
#include "hook.h"
#include "mutt_attach.h"
#include "mutt_body.h"
#include "mutt_header.h"
#include "mutt_logging.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "ncrypt/ncrypt.h"
#include "options.h"
#include "pattern.h"
#include "protos.h"
#include "recvattach.h"
#include "rfc3676.h"
#include "sendlib.h"
#include "smtp.h"
#include "sort.h"
#include "mx.h"
#include "nntp/nntp.h"
#include "notmuch/mutt_notmuch.h"
#include "imap/imap.h"

Go to the source code of this file.

Functions

static void append_signature (FILE *fp)
 Append a signature to an email. More...
 
static void remove_user (struct AddressList *al, bool leave_only)
 Remove any address which matches the current user. More...
 
static void add_mailing_lists (struct AddressList *out, const struct AddressList *t, const struct AddressList *c)
 Search Address lists for mailing lists. More...
 
static int edit_address (struct AddressList *al, const char *field)
 Edit an email address. More...
 
static int edit_envelope (struct Envelope *en, SendFlags flags)
 Edit Envelope fields. More...
 
static char * nntp_get_header (const char *s)
 Get the trimmed header. More...
 
static void process_user_recips (struct Envelope *env)
 Process the user headers. More...
 
static void process_user_header (struct Envelope *env)
 Process the user headers. More...
 
void mutt_forward_intro (struct Mailbox *m, struct Email *e, FILE *fp)
 Add the "start of forwarded message" text. More...
 
void mutt_forward_trailer (struct Mailbox *m, struct Email *e, FILE *fp)
 Add a "end of forwarded message" text. More...
 
static int include_forward (struct Mailbox *m, struct Email *e, FILE *fp_out)
 Write out a forwarded message. More...
 
static int inline_forward_attachments (struct Mailbox *m, struct Email *e, struct Body ***plast, int *forwardq)
 Add attachments to an email, inline. More...
 
int mutt_inline_forward (struct Mailbox *m, struct Email *e_edit, struct Email *e_cur, FILE *out)
 Forward attachments, inline. More...
 
void mutt_make_attribution (struct Mailbox *m, struct Email *e, FILE *fp_out)
 Add "on DATE, PERSON wrote" header. More...
 
void mutt_make_post_indent (struct Mailbox *m, struct Email *e, FILE *fp_out)
 Add suffix to replied email text. More...
 
static int include_reply (struct Mailbox *m, struct Email *e, FILE *fp_out)
 Generate the reply text for an email. More...
 
static int default_to (struct AddressList *to, struct Envelope *env, SendFlags flags, int hmfupto)
 Generate default email addresses. More...
 
int mutt_fetch_recips (struct Envelope *out, struct Envelope *in, SendFlags flags)
 Generate recpients for a reply email. More...
 
static void add_references (struct ListHead *head, struct Envelope *env)
 Add the email's references to a list. More...
 
static void add_message_id (struct ListHead *head, struct Envelope *env)
 Add the email's message ID to a list. More...
 
void mutt_fix_reply_recipients (struct Envelope *env)
 Remove duplicate recipients. More...
 
void mutt_make_forward_subject (struct Envelope *env, struct Mailbox *m, struct Email *e)
 Create a subject for a forwarded email. More...
 
void mutt_make_misc_reply_headers (struct Envelope *env, struct Envelope *curenv)
 Set subject for a reply. More...
 
void mutt_add_to_reference_headers (struct Envelope *env, struct Envelope *curenv)
 Generate references for a reply email. More...
 
static void make_reference_headers (struct EmailList *el, struct Envelope *env)
 Generate reference headers for an email. More...
 
static int envelope_defaults (struct Envelope *env, struct Mailbox *m, struct EmailList *el, SendFlags flags)
 Fill in some defaults for a new email. More...
 
static int generate_body (FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailList *el)
 Create a new email body. More...
 
void mutt_set_followup_to (struct Envelope *env)
 Set followup-to field. More...
 
static void set_reverse_name (struct AddressList *al, struct Envelope *env)
 Try to set the 'from' field from the recipients. More...
 
struct Addressmutt_default_from (void)
 Get a default 'from' Address. More...
 
static int send_message (struct Email *e)
 Send an email. More...
 
void mutt_encode_descriptions (struct Body *b, bool recurse)
 rfc2047 encode the content-descriptions More...
 
static void decode_descriptions (struct Body *b)
 rfc2047 decode them in case of an error More...
 
static void fix_end_of_file (const char *data)
 Ensure a file ends with a linefeed. More...
 
int mutt_resend_message (FILE *fp, struct Context *ctx, struct Email *e_cur)
 Resend an email. More...
 
static bool is_reply (struct Email *reply, struct Email *orig)
 Is one email a reply to another? More...
 
static bool search_attach_keyword (char *filename)
 Search an email for 'attachment' keywords. More...
 
static int save_fcc (struct Email *e, char *fcc, size_t fcc_len, struct Body *clear_content, char *pgpkeylist, SendFlags flags, char **finalpath)
 Save an Email to a 'sent mail' folder. More...
 
static int postpone_message (struct Email *e_post, struct Email *e_cur, char *fcc, SendFlags flags)
 Save an Email for another day. More...
 
int ci_send_message (SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el)
 Send an email. More...
 

Variables

unsigned char C_AbortNoattach
 Config: Abort sending the email if attachments are missing. More...
 
struct RegexC_AbortNoattachRegex
 Config: Regex to match text indicating attachments are expected. More...
 
unsigned char C_AbortNosubject
 Config: Abort creating the email if subject is missing. More...
 
unsigned char C_AbortUnmodified
 Config: Abort the sending if the message hasn't been edited. More...
 
bool C_AskFollowUp
 Config: (nntp) Ask the user for follow-up groups before editing. More...
 
bool C_AskXCommentTo
 Config: (nntp) Ask the user for the 'X-Comment-To' field before editing. More...
 
char * C_ContentType
 Config: Default "Content-Type" for newly composed messages. More...
 
bool C_CryptAutoencrypt
 Config: Automatically PGP encrypt all outgoing mail. More...
 
bool C_CryptAutopgp
 Config: Allow automatic PGP functions. More...
 
bool C_CryptAutosign
 Config: Automatically PGP sign all outgoing mail. More...
 
bool C_CryptAutosmime
 Config: Allow automatic SMIME functions. More...
 
bool C_CryptReplyencrypt
 Config: Encrypt replies to encrypted messages. More...
 
bool C_CryptReplysign
 Config: Sign replies to signed messages. More...
 
bool C_CryptReplysignencrypted
 Config: Sign replies to encrypted messages. More...
 
char * C_EmptySubject
 Config: Subject to use when replying to an email with none. More...
 
bool C_FastReply
 Config: Don't prompt for the recipients and subject when replying/forwarding. More...
 
unsigned char C_FccAttach
 Config: Save send message with all their attachments. More...
 
bool C_FccBeforeSend
 Config: Save FCCs before sending the message. More...
 
bool C_FccClear
 Config: Save sent messages unencrypted and unsigned. More...
 
bool C_FollowupTo
 Config: Add the 'Mail-Followup-To' header is generated when sending mail. More...
 
char * C_ForwardAttributionIntro
 Config: Prefix message for forwarded messages. More...
 
char * C_ForwardAttributionTrailer
 Config: Suffix message for forwarded messages. More...
 
unsigned char C_ForwardEdit
 Config: Automatically start the editor when forwarding a message. More...
 
char * C_ForwardFormat
 Config: printf-like format string to control the subject when forwarding a message. More...
 
bool C_ForwardReferences
 Config: Set the 'In-Reply-To' and 'References' headers when forwarding a message. More...
 
bool C_Hdrs
 Config: Add custom headers to outgoing mail. More...
 
unsigned char C_HonorFollowupTo
 Config: Honour the 'Mail-Followup-To' header when group replying. More...
 
bool C_IgnoreListReplyTo
 Config: Ignore the 'Reply-To' header when using <reply> on a mailing list. More...
 
unsigned char C_Include
 Config: Include a copy of the email that's being replied to. More...
 
bool C_Metoo
 Config: Remove the user's address from the list of recipients. More...
 
bool C_NmRecord
 Config: (notmuch) If the 'record' mailbox (sent mail) should be indexed. More...
 
bool C_PgpReplyinline
 Config: Reply using old-style inline PGP messages (not recommended) More...
 
char * C_PostIndentString
 Config: Suffix message to add after reply text. More...
 
bool C_PostponeEncrypt
 Config: Self-encrypt postponed messages. More...
 
char * C_PostponeEncryptAs
 Config: Fallback encryption key for postponed messages. More...
 
unsigned char C_Recall
 Config: Recall postponed mesaages when asked to compose a message. More...
 
bool C_ReplySelf
 Config: Really reply to yourself, when replying to your own email. More...
 
unsigned char C_ReplyTo
 Config: Address to use as a 'Reply-To' header. More...
 
bool C_ReplyWithXorig
 Config: Create 'From' header from 'X-Original-To' header. More...
 
bool C_ReverseName
 Config: Set the 'From' from the address the email was sent to. More...
 
bool C_ReverseRealname
 Config: Set the 'From' from the full 'To' address the email was sent to. More...
 
bool C_SigDashes
 Config: Insert '– ' before the signature. More...
 
char * C_Signature
 Config: File containing a signature to append to all mail. More...
 
bool C_SigOnTop
 Config: Insert the signature before the quoted text. More...
 
bool C_UseFrom
 Config: Set the 'From' header for outgoing mail. More...
 

Detailed Description

Prepare and send an email.

Authors
  • Michael R. Elkins
  • Pietro Cerutti

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, see http://www.gnu.org/licenses/.

Definition in file send.c.

Function Documentation

static void append_signature ( FILE *  fp)
static

Append a signature to an email.

Parameters
fpFile to write to

Definition at line 139 of file send.c.

140 {
141  FILE *fp_tmp = NULL;
142  pid_t pid;
143 
144  if (C_Signature && (fp_tmp = mutt_open_read(C_Signature, &pid)))
145  {
146  if (C_SigDashes)
147  fputs("\n-- \n", fp);
148  mutt_file_copy_stream(fp_tmp, fp);
149  mutt_file_fclose(&fp_tmp);
150  if (pid != -1)
151  mutt_wait_filter(pid);
152  }
153 }
bool C_SigDashes
Config: Insert &#39;– &#39; before the signature.
Definition: send.c:130
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:267
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Definition: muttlib.c:1366
char * C_Signature
Config: File containing a signature to append to all mail.
Definition: send.c:131
static void remove_user ( struct AddressList *  al,
bool  leave_only 
)
static

Remove any address which matches the current user.

Parameters
alList of addresses
leave_onlyIf set, don't remove the user's address if it it the only one in the list

Definition at line 161 of file send.c.

162 {
163  struct Address *a = NULL, *tmp = NULL;
164  TAILQ_FOREACH_SAFE(a, al, entries, tmp)
165  {
166  if (mutt_addr_is_user(a) && (!leave_only || TAILQ_NEXT(a, entries)))
167  {
168  TAILQ_REMOVE(al, a, entries);
169  mutt_addr_free(&a);
170  }
171  }
172 }
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:729
An email address.
Definition: address.h:34
void mutt_addr_free(struct Address **a)
Free a single Address.
Definition: address.c:439
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:821
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:669
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
static void add_mailing_lists ( struct AddressList *  out,
const struct AddressList *  t,
const struct AddressList *  c 
)
static

Search Address lists for mailing lists.

Parameters
outAddress list where to append matching mailing lists
t'To' Address list
c'Cc' Address list

Definition at line 180 of file send.c.

182 {
183  const struct AddressList *const als[] = { t, c };
184 
185  for (size_t i = 0; i < mutt_array_size(als); ++i)
186  {
187  const struct AddressList *al = als[i];
188  struct Address *a = NULL;
189  TAILQ_FOREACH(a, al, entries)
190  {
191  if (!a->group && mutt_is_mail_list(a))
192  {
194  }
195  }
196  }
197 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:102
An email address.
Definition: address.h:34
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:703
#define mutt_array_size(x)
Definition: memory.h:33
bool group
Group mailbox?
Definition: address.h:38
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1371
static int edit_address ( struct AddressList *  al,
const char *  field 
)
static

Edit an email address.

Parameters
[in,out]alAddressList to edit
[in]fieldPrompt for user
Return values
0Success
-1Failure

Definition at line 206 of file send.c.

207 {
208  char buf[8192];
209  char *err = NULL;
210  int idna_ok = 0;
211 
212  do
213  {
214  buf[0] = '\0';
216  mutt_addrlist_write(buf, sizeof(buf), al, false);
217  if (mutt_get_field(field, buf, sizeof(buf), MUTT_ALIAS) != 0)
218  return -1;
220  mutt_addrlist_parse2(al, buf);
222  idna_ok = mutt_addrlist_to_intl(al, &err);
223  if (idna_ok != 0)
224  {
225  mutt_error(_("Bad IDN: '%s'"), err);
226  FREE(&err);
227  }
228  } while (idna_ok != 0);
229  return 0;
230 }
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:290
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:63
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1268
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1351
#define _(a)
Definition: message.h:28
size_t mutt_addrlist_write(char *buf, size_t buflen, const struct AddressList *al, bool display)
Write an Address to a buffer.
Definition: address.c:1134
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:603
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1186
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
static int edit_envelope ( struct Envelope en,
SendFlags  flags 
)
static

Edit Envelope fields.

Parameters
enEnvelope to edit
flagsFlags, see SendFlags
Return values
0Success
-1Failure

Definition at line 239 of file send.c.

240 {
241  char buf[8192];
242 
243 #ifdef USE_NNTP
244  if (OptNewsSend)
245  {
246  if (en->newsgroups)
247  mutt_str_strfcpy(buf, en->newsgroups, sizeof(buf));
248  else
249  buf[0] = '\0';
250  if (mutt_get_field("Newsgroups: ", buf, sizeof(buf), 0) != 0)
251  return -1;
252  FREE(&en->newsgroups);
253  en->newsgroups = mutt_str_strdup(buf);
254 
255  if (en->followup_to)
256  mutt_str_strfcpy(buf, en->followup_to, sizeof(buf));
257  else
258  buf[0] = '\0';
259  if (C_AskFollowUp && (mutt_get_field("Followup-To: ", buf, sizeof(buf), 0) != 0))
260  {
261  return -1;
262  }
263  FREE(&en->followup_to);
264  en->followup_to = mutt_str_strdup(buf);
265 
266  if (en->x_comment_to)
267  mutt_str_strfcpy(buf, en->x_comment_to, sizeof(buf));
268  else
269  buf[0] = '\0';
270  if (C_XCommentTo && C_AskXCommentTo &&
271  (mutt_get_field("X-Comment-To: ", buf, sizeof(buf), 0) != 0))
272  {
273  return -1;
274  }
275  FREE(&en->x_comment_to);
276  en->x_comment_to = mutt_str_strdup(buf);
277  }
278  else
279 #endif
280  {
281  if ((edit_address(&en->to, _("To: ")) == -1) || TAILQ_EMPTY(&en->to))
282  return -1;
283  if (C_Askcc && (edit_address(&en->cc, _("Cc: ")) == -1))
284  return -1;
285  if (C_Askbcc && (edit_address(&en->bcc, _("Bcc: ")) == -1))
286  return -1;
288  (edit_address(&en->from, "From: ") == -1))
289  {
290  return -1;
291  }
292  }
293 
294  if (en->subject)
295  {
296  if (C_FastReply)
297  return 0;
298  else
299  mutt_str_strfcpy(buf, en->subject, sizeof(buf));
300  }
301  else
302  {
303  const char *p = NULL;
304 
305  buf[0] = '\0';
306  struct ListNode *uh = NULL;
307  STAILQ_FOREACH(uh, &UserHeader, entries)
308  {
309  size_t plen = mutt_str_startswith(uh->data, "subject:", CASE_IGNORE);
310  if (plen)
311  {
312  p = mutt_str_skip_email_wsp(uh->data + plen);
313  mutt_str_strfcpy(buf, p, sizeof(buf));
314  }
315  }
316  }
317 
318  if ((mutt_get_field(_("Subject: "), buf, sizeof(buf), 0) != 0) ||
319  (!buf[0] &&
320  (query_quadoption(C_AbortNosubject, _("No subject, abort?")) != MUTT_NO)))
321  {
322  mutt_message(_("No subject, aborting"));
323  return -1;
324  }
325  mutt_str_replace(&en->subject, buf);
326 
327  return 0;
328 }
static int edit_address(struct AddressList *al, const char *field)
Edit an email address.
Definition: send.c:206
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
#define mutt_message(...)
Definition: logging.h:83
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:46
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
#define _(a)
Definition: message.h:28
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
unsigned char C_AbortNosubject
Config: Abort creating the email if subject is missing.
Definition: send.c:91
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:89
bool C_FastReply
Config: Don&#39;t prompt for the recipients and subject when replying/forwarding.
Definition: send.c:104
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:64
bool C_AskXCommentTo
Config: (nntp) Ask the user for the &#39;X-Comment-To&#39; field before editing.
Definition: send.c:94
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
Ignore case when comparing strings.
Definition: string2.h:68
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define SEND_REPLY
Reply to sender.
Definition: send.h:87
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
bool C_AskFollowUp
Config: (nntp) Ask the user for follow-up groups before editing.
Definition: send.c:93
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:88
char * data
Definition: list.h:35
char * subject
Email&#39;s subject.
Definition: envelope.h:52
char * newsgroups
List of newsgroups.
Definition: envelope.h:61
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:281
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:63
#define FREE(x)
Definition: memory.h:40
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
A List node for strings.
Definition: list.h:33
WHERE bool C_Askbcc
Config: Ask the user for the blind-carbon-copy recipients.
Definition: globals.h:197
WHERE bool C_Askcc
Config: Ask the user for the carbon-copy recipients.
Definition: globals.h:198
bool C_ReplyWithXorig
Config: Create &#39;From&#39; header from &#39;X-Original-To&#39; header.
Definition: send.c:127
static char* nntp_get_header ( const char *  s)
static

Get the trimmed header.

Parameters
sHeader line with leading whitespace
Return values
ptrCopy of string
Note
The caller should free the returned string.

Definition at line 338 of file send.c.

339 {
340  SKIPWS(s);
341  return mutt_str_strdup(s);
342 }
#define SKIPWS(ch)
Definition: string2.h:47
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
static void process_user_recips ( struct Envelope env)
static

Process the user headers.

Parameters
envEnvelope to populate

Definition at line 349 of file send.c.

350 {
351  struct ListNode *uh = NULL;
352  STAILQ_FOREACH(uh, &UserHeader, entries)
353  {
354  size_t plen;
355  if ((plen = mutt_str_startswith(uh->data, "to:", CASE_IGNORE)))
356  mutt_addrlist_parse(&env->to, uh->data + plen);
357  else if ((plen = mutt_str_startswith(uh->data, "cc:", CASE_IGNORE)))
358  mutt_addrlist_parse(&env->cc, uh->data + plen);
359  else if ((plen = mutt_str_startswith(uh->data, "bcc:", CASE_IGNORE)))
360  mutt_addrlist_parse(&env->bcc, uh->data + plen);
361 #ifdef USE_NNTP
362  else if ((plen = mutt_str_startswith(uh->data, "newsgroups:", CASE_IGNORE)))
363  env->newsgroups = nntp_get_header(uh->data + plen);
364  else if ((plen = mutt_str_startswith(uh->data, "followup-to:", CASE_IGNORE)))
365  env->followup_to = nntp_get_header(uh->data + plen);
366  else if ((plen = mutt_str_startswith(uh->data, "x-comment-to:", CASE_IGNORE)))
367  env->x_comment_to = nntp_get_header(uh->data + plen);
368 #endif
369  }
370 }
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:454
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:46
static char * nntp_get_header(const char *s)
Get the trimmed header.
Definition: send.c:338
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:64
Ignore case when comparing strings.
Definition: string2.h:68
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
char * data
Definition: list.h:35
char * newsgroups
List of newsgroups.
Definition: envelope.h:61
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:63
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
A List node for strings.
Definition: list.h:33
static void process_user_header ( struct Envelope env)
static

Process the user headers.

Parameters
envEnvelope to populate

Definition at line 376 of file send.c.

377 {
378  struct ListNode *uh = NULL;
379  STAILQ_FOREACH(uh, &UserHeader, entries)
380  {
381  size_t plen;
382  if ((plen = mutt_str_startswith(uh->data, "from:", CASE_IGNORE)))
383  {
384  /* User has specified a default From: address. Remove default address */
385  mutt_addrlist_clear(&env->from);
386  mutt_addrlist_parse(&env->from, uh->data + plen);
387  }
388  else if ((plen = mutt_str_startswith(uh->data, "reply-to:", CASE_IGNORE)))
389  {
391  mutt_addrlist_parse(&env->reply_to, uh->data + plen);
392  }
393  else if ((plen = mutt_str_startswith(uh->data, "message-id:", CASE_IGNORE)))
394  {
395  char *tmp = mutt_extract_message_id(uh->data + plen, NULL);
396  if (mutt_addr_valid_msgid(tmp))
397  {
398  FREE(&env->message_id);
399  env->message_id = tmp;
400  }
401  else
402  FREE(&tmp);
403  }
404  else if (!mutt_str_startswith(uh->data, "to:", CASE_IGNORE) &&
405  !mutt_str_startswith(uh->data, "cc:", CASE_IGNORE) &&
406  !mutt_str_startswith(uh->data, "bcc:", CASE_IGNORE) &&
407 #ifdef USE_NNTP
408  !mutt_str_startswith(uh->data, "newsgroups:", CASE_IGNORE) &&
409  !mutt_str_startswith(uh->data, "followup-to:", CASE_IGNORE) &&
410  !mutt_str_startswith(uh->data, "x-comment-to:", CASE_IGNORE) &&
411 #endif
412  !mutt_str_startswith(uh->data, "supersedes:", CASE_IGNORE) &&
413  !mutt_str_startswith(uh->data, "subject:", CASE_IGNORE) &&
414  !mutt_str_startswith(uh->data, "return-path:", CASE_IGNORE))
415  {
417  }
418  }
419 }
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:48
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:454
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1351
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
struct ListHead userhdrs
user defined headers
Definition: envelope.h:69
char * message_id
Message ID.
Definition: envelope.h:55
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
Ignore case when comparing strings.
Definition: string2.h:68
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
char * data
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition: address.c:751
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:33
char * mutt_extract_message_id(const char *s, const char **saveptr)
Find a message-id.
Definition: parse.c:336
void mutt_forward_intro ( struct Mailbox m,
struct Email e,
FILE *  fp 
)

Add the "start of forwarded message" text.

Parameters
mMailbox
eEmail
fpFile to write to

Definition at line 427 of file send.c.

428 {
429  if (!C_ForwardAttributionIntro || !fp)
430  return;
431 
432  char buf[1024];
433  setlocale(LC_TIME, NONULL(C_AttributionLocale));
434  mutt_make_string(buf, sizeof(buf), C_ForwardAttributionIntro, NULL, m, e);
435  setlocale(LC_TIME, "");
436  fputs(buf, fp);
437  fputs("\n\n", fp);
438 }
#define NONULL(x)
Definition: string2.h:37
char * C_ForwardAttributionIntro
Config: Prefix message for forwarded messages.
Definition: send.c:109
WHERE char * C_AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:97
#define mutt_make_string(BUF, BUFLEN, S, CTX, M, E)
Definition: hdrline.h:60
void mutt_forward_trailer ( struct Mailbox m,
struct Email e,
FILE *  fp 
)

Add a "end of forwarded message" text.

Parameters
mMailbox
eEmail
fpFile to write to

Definition at line 446 of file send.c.

447 {
448  if (!C_ForwardAttributionTrailer || !fp)
449  return;
450 
451  char buf[1024];
452  setlocale(LC_TIME, NONULL(C_AttributionLocale));
453  mutt_make_string(buf, sizeof(buf), C_ForwardAttributionTrailer, NULL, m, e);
454  setlocale(LC_TIME, "");
455  fputc('\n', fp);
456  fputs(buf, fp);
457  fputc('\n', fp);
458 }
#define NONULL(x)
Definition: string2.h:37
WHERE char * C_AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:97
char * C_ForwardAttributionTrailer
Config: Suffix message for forwarded messages.
Definition: send.c:110
#define mutt_make_string(BUF, BUFLEN, S, CTX, M, E)
Definition: hdrline.h:60
static int include_forward ( struct Mailbox m,
struct Email e,
FILE *  fp_out 
)
static

Write out a forwarded message.

Parameters
mMailbox
eEmail
fp_outFile to write to
Return values
0Success
-1Failure

Definition at line 468 of file send.c.

469 {
470  CopyHeaderFlags chflags = CH_DECODE;
472 
475 
476  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) && C_ForwardDecode)
477  {
478  /* make sure we have the user's passphrase before proceeding... */
480  return -1;
481  }
482 
483  mutt_forward_intro(m, e, fp_out);
484 
485  if (C_ForwardDecode)
486  {
487  cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
488  if (C_Weed)
489  {
490  chflags |= CH_WEED | CH_REORDER;
491  cmflags |= MUTT_CM_WEED;
492  }
493  }
494  if (C_ForwardQuote)
495  cmflags |= MUTT_CM_PREFIX;
496 
497  /* wrapping headers for forwarding is considered a display
498  * rather than send action */
499  chflags |= CH_DISPLAY;
500 
501  mutt_copy_message(fp_out, m, e, cmflags, chflags);
502  mutt_forward_trailer(m, e, fp_out);
503  return 0;
504 }
WHERE bool C_ForwardDecode
Config: Decode the message when forwarding it.
Definition: globals.h:210
void mutt_forward_intro(struct Mailbox *m, struct Email *e, FILE *fp)
Add the "start of forwarded message" text.
Definition: send.c:427
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:40
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Copy a message from a Mailbox.
Definition: copy.c:802
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:51
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:143
#define CH_WEED
Weed the headers?
Definition: copy.h:52
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:36
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
void mutt_forward_trailer(struct Mailbox *m, struct Email *e, FILE *fp)
Add a "end of forwarded message" text.
Definition: send.c:446
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
WHERE bool C_ForwardQuote
Config: Automatically quote a forwarded message using C_IndentString.
Definition: globals.h:211
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:579
#define WithCrypto
Definition: ncrypt.h:156
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
static int inline_forward_attachments ( struct Mailbox m,
struct Email e,
struct Body ***  plast,
int *  forwardq 
)
static

Add attachments to an email, inline.

Parameters
[in]mMailbox
[in]eCurrent Email
[out]plastPointer to the last Attachment
[out]forwardqResult of asking the user to forward the attachments, e.g. MUTT_YES
Return values
0Success
-1Error

Definition at line 515 of file send.c.

517 {
518  struct Body **last = *plast;
519  struct Body *body = NULL;
520  struct Message *msg = NULL;
521  struct AttachCtx *actx = NULL;
522  int rc = 0, i;
523 
526 
527  msg = mx_msg_open(m, e->msgno);
528  if (!msg)
529  return -1;
530 
531  actx = mutt_mem_calloc(1, sizeof(*actx));
532  actx->email = e;
533  actx->fp_root = msg->fp;
534 
535  mutt_generate_recvattach_list(actx, actx->email, actx->email->content,
536  actx->fp_root, -1, 0, 0);
537 
538  for (i = 0; i < actx->idxlen; i++)
539  {
540  body = actx->idx[i]->content;
541  if ((body->type != TYPE_MULTIPART) && !mutt_can_decode(body) &&
542  !((body->type == TYPE_APPLICATION) &&
543  ((mutt_str_strcasecmp(body->subtype, "pgp-signature") == 0) ||
544  (mutt_str_strcasecmp(body->subtype, "x-pkcs7-signature") == 0) ||
545  (mutt_str_strcasecmp(body->subtype, "pkcs7-signature") == 0))))
546  {
547  /* Ask the quadoption only once */
548  if (*forwardq == -1)
549  {
551  /* L10N:
552  This is the prompt for $forward_attachments.
553  When inline forwarding ($mime_forward answered "no"), this prompts
554  whether to add non-decodable attachments from the original email.
555  Text/plain parts and the like will already be included in the
556  message contents, but other attachment, such as PDF files, will also
557  be added as attachments to the new mail, if this is answered yes.
558  */
559  _("Forward attachments?"));
560  if (*forwardq != MUTT_YES)
561  {
562  if (*forwardq == -1)
563  rc = -1;
564  goto cleanup;
565  }
566  }
567  if (mutt_body_copy(actx->idx[i]->fp, last, body) == -1)
568  {
569  rc = -1;
570  goto cleanup;
571  }
572  last = &((*last)->next);
573  }
574  }
575 
576 cleanup:
577  *plast = last;
578  mx_msg_close(m, &msg);
579  mutt_actx_free(&actx);
580  return rc;
581 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
void mutt_generate_recvattach_list(struct AttachCtx *actx, struct Email *e, struct Body *parts, FILE *fp, int parent_type, int level, bool decrypted)
Create a list of attachments.
Definition: recvattach.c:1214
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
struct Email * email
Used by recvattach for updating.
Definition: attach.h:51
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
struct Body * content
List of MIME parts.
Definition: email.h:90
FILE * fp_root
Used by recvattach for updating.
Definition: attach.h:52
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
#define _(a)
Definition: message.h:28
short idxlen
Number of attachmentes.
Definition: attach.h:55
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:51
The body of an email.
Definition: body.h:34
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1092
int mutt_body_copy(FILE *fp, struct Body **tgt, struct Body *src)
Create a send-mode duplicate from a receive-mode body.
Definition: mutt_body.c:48
char * subtype
content-type subtype
Definition: body.h:37
void mutt_actx_free(struct AttachCtx **pactx)
Free an Attachment Context.
Definition: attach.c:131
A local copy of an email.
Definition: mx.h:82
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1748
FILE * fp
Used in the recvattach menu.
Definition: attach.h:37
unsigned int type
content-type primary type
Definition: body.h:65
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
struct Body * content
Attachment.
Definition: attach.h:36
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
FILE * fp
pointer to the message data
Definition: mx.h:84
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:579
A set of attachments.
Definition: attach.h:49
struct AttachPtr ** idx
Array of attachments.
Definition: attach.h:54
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1044
Type: &#39;application/*&#39;.
Definition: mime.h:33
int msgno
Number displayed to the user.
Definition: email.h:86
WHERE unsigned char C_ForwardAttachments
Config: Forward attachments when forwarding a message.
Definition: globals.h:183
int mutt_inline_forward ( struct Mailbox m,
struct Email e_edit,
struct Email e_cur,
FILE *  out 
)

Forward attachments, inline.

Parameters
mMailbox
e_editEmail to alter
e_curCurrent Email
outFile
Return values
0Success
-1Error

Definition at line 592 of file send.c.

594 {
595  int i, forwardq = -1;
596  struct Body **last = NULL;
597 
598  if (e_cur)
599  include_forward(m, e_cur, out);
600  else
601  for (i = 0; i < m->vcount; i++)
602  if (m->emails[m->v2r[i]]->tagged)
603  include_forward(m, m->emails[m->v2r[i]], out);
604 
606  {
607  last = &e_edit->content;
608  while (*last)
609  last = &((*last)->next);
610 
611  if (e_cur)
612  {
613  if (inline_forward_attachments(m, e_cur, &last, &forwardq) != 0)
614  return -1;
615  }
616  else
617  for (i = 0; i < m->vcount; i++)
618  if (m->emails[m->v2r[i]]->tagged)
619  {
620  if (inline_forward_attachments(m, m->emails[m->v2r[i]], &last, &forwardq) != 0)
621  return -1;
622  if (forwardq == MUTT_NO)
623  break;
624  }
625  }
626 
627  return 0;
628 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
WHERE bool C_ForwardDecode
Config: Decode the message when forwarding it.
Definition: globals.h:210
struct Body * content
List of MIME parts.
Definition: email.h:90
static int inline_forward_attachments(struct Mailbox *m, struct Email *e, struct Body ***plast, int *forwardq)
Add attachments to an email, inline.
Definition: send.c:515
int vcount
The number of virtual messages.
Definition: mailbox.h:114
The body of an email.
Definition: body.h:34
bool tagged
Email is tagged.
Definition: email.h:44
static int include_forward(struct Mailbox *m, struct Email *e, FILE *fp_out)
Write out a forwarded message.
Definition: send.c:468
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
WHERE unsigned char C_ForwardAttachments
Config: Forward attachments when forwarding a message.
Definition: globals.h:183
void mutt_make_attribution ( struct Mailbox m,
struct Email e,
FILE *  fp_out 
)

Add "on DATE, PERSON wrote" header.

Parameters
mMailbox
eEmail
fp_outFile to write to

Definition at line 636 of file send.c.

637 {
638  if (!C_Attribution || !fp_out)
639  return;
640 
641  char buf[1024];
642  setlocale(LC_TIME, NONULL(C_AttributionLocale));
643  mutt_make_string(buf, sizeof(buf), C_Attribution, NULL, m, e);
644  setlocale(LC_TIME, "");
645  fputs(buf, fp_out);
646  fputc('\n', fp_out);
647 }
#define NONULL(x)
Definition: string2.h:37
WHERE char * C_AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:97
#define mutt_make_string(BUF, BUFLEN, S, CTX, M, E)
Definition: hdrline.h:60
WHERE char * C_Attribution
Config: Message to start a reply, "On DATE, PERSON wrote:".
Definition: globals.h:96
void mutt_make_post_indent ( struct Mailbox m,
struct Email e,
FILE *  fp_out 
)

Add suffix to replied email text.

Parameters
mMailbox
eEmail
fp_outFile to write to

Definition at line 655 of file send.c.

656 {
657  if (!C_PostIndentString || !fp_out)
658  return;
659 
660  char buf[256];
661  mutt_make_string(buf, sizeof(buf), C_PostIndentString, NULL, m, e);
662  fputs(buf, fp_out);
663  fputc('\n', fp_out);
664 }
#define mutt_make_string(BUF, BUFLEN, S, CTX, M, E)
Definition: hdrline.h:60
char * C_PostIndentString
Config: Suffix message to add after reply text.
Definition: send.c:121
static int include_reply ( struct Mailbox m,
struct Email e,
FILE *  fp_out 
)
static

Generate the reply text for an email.

Parameters
mMailbox
eEmail
fp_outFile to write to
Return values
0Success
-1Failure

Definition at line 674 of file send.c.

675 {
676  CopyMessageFlags cmflags =
678  CopyHeaderFlags chflags = CH_DECODE;
679 
680  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT))
681  {
682  /* make sure we have the user's passphrase before proceeding... */
684  return -1;
685  }
686 
689 
690  mutt_make_attribution(m, e, fp_out);
691 
692  if (!C_Header)
693  cmflags |= MUTT_CM_NOHEADER;
694  if (C_Weed)
695  {
696  chflags |= CH_WEED | CH_REORDER;
697  cmflags |= MUTT_CM_WEED;
698  }
699 
700  mutt_copy_message(fp_out, m, e, cmflags, chflags);
701 
702  mutt_make_post_indent(m, e, fp_out);
703 
704  return 0;
705 }
#define MUTT_CM_WEED
Weed message/rfc822 attachment headers.
Definition: copy.h:40
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Copy a message from a Mailbox.
Definition: copy.c:802
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:51
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:31
void mutt_make_post_indent(struct Mailbox *m, struct Email *e, FILE *fp_out)
Add suffix to replied email text.
Definition: send.c:655
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
#define MUTT_CM_REPLYING
Replying the message.
Definition: copy.h:43
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:143
#define CH_WEED
Weed the headers?
Definition: copy.h:52
WHERE bool C_Header
Config: Include the message headers in the reply email (Weed applies)
Definition: globals.h:217
#define MUTT_CM_PREFIX
Quote the header and body.
Definition: copy.h:36
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define CH_REORDER
Re-order output of headers (specified by &#39;hdr_order&#39;)
Definition: copy.h:58
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:579
#define MUTT_CM_NOHEADER
Don&#39;t copy the message header.
Definition: copy.h:35
#define WithCrypto
Definition: ncrypt.h:156
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
void mutt_make_attribution(struct Mailbox *m, struct Email *e, FILE *fp_out)
Add "on DATE, PERSON wrote" header.
Definition: send.c:636
static int default_to ( struct AddressList *  to,
struct Envelope env,
SendFlags  flags,
int  hmfupto 
)
static

Generate default email addresses.

Parameters
[in,out]to'To' address
[in]envEnvelope to populate
[in]flagsFlags, see SendFlags
[in]hmfuptoIf true, add 'followup-to' address to 'to' address
Return values
0Success
-1Aborted

Definition at line 716 of file send.c.

717 {
718  char prompt[256];
719  const struct Address *from = TAILQ_FIRST(&env->from);
720  const struct Address *reply_to = TAILQ_FIRST(&env->reply_to);
721 
722  if (flags && !TAILQ_EMPTY(&env->mail_followup_to) && (hmfupto == MUTT_YES))
723  {
724  mutt_addrlist_copy(to, &env->mail_followup_to, true);
725  return 0;
726  }
727 
728  /* Exit now if we're setting up the default Cc list for list-reply
729  * (only set if Mail-Followup-To is present and honoured). */
730  if (flags & SEND_LIST_REPLY)
731  return 0;
732 
733  if (!C_ReplySelf && mutt_addr_is_user(from))
734  {
735  /* mail is from the user, assume replying to recipients */
736  mutt_addrlist_copy(to, &env->to, true);
737  }
738  else if (reply_to)
739  {
740  const bool from_is_reply_to = mutt_addr_cmp(from, reply_to);
741  const bool multiple_reply_to =
742  reply_to && TAILQ_NEXT(TAILQ_FIRST(&env->reply_to), entries);
743  if ((from_is_reply_to && !multiple_reply_to && !reply_to->personal) ||
744  (C_IgnoreListReplyTo && mutt_is_mail_list(reply_to) &&
745  (mutt_addrlist_search(reply_to, &env->to) ||
746  mutt_addrlist_search(reply_to, &env->cc))))
747  {
748  /* If the Reply-To: address is a mailing list, assume that it was
749  * put there by the mailing list, and use the From: address
750  *
751  * We also take the from header if our correspondent has a reply-to
752  * header which is identical to the electronic mail address given
753  * in his From header, and the reply-to has no display-name. */
754  mutt_addrlist_copy(to, &env->from, false);
755  }
756  else if (!(from_is_reply_to && !multiple_reply_to) && (C_ReplyTo != MUTT_YES))
757  {
758  /* There are quite a few mailing lists which set the Reply-To:
759  * header field to the list address, which makes it quite impossible
760  * to send a message to only the sender of the message. This
761  * provides a way to do that. */
762  /* L10N: Asks whether the user respects the reply-to header.
763  If she says no, neomutt will reply to the from header's address instead. */
764  snprintf(prompt, sizeof(prompt), _("Reply to %s%s?"), reply_to->mailbox,
765  multiple_reply_to ? ",..." : "");
766  switch (query_quadoption(C_ReplyTo, prompt))
767  {
768  case MUTT_YES:
769  mutt_addrlist_copy(to, &env->reply_to, false);
770  break;
771 
772  case MUTT_NO:
773  mutt_addrlist_copy(to, &env->from, false);
774  break;
775 
776  default:
777  return -1; /* abort */
778  }
779  }
780  else
781  mutt_addrlist_copy(to, &env->reply_to, false);
782  }
783  else
784  mutt_addrlist_copy(to, &env->from, false);
785 
786  return 0;
787 }
#define TAILQ_FIRST(head)
Definition: queue.h:717
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:49
bool C_ReplySelf
Config: Really reply to yourself, when replying to your own email.
Definition: send.c:125
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:48
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:102
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
bool C_IgnoreListReplyTo
Config: Ignore the &#39;Reply-To&#39; header when using <reply> on a mailing list.
Definition: send.c:116
unsigned char C_ReplyTo
Config: Address to use as a &#39;Reply-To&#39; header.
Definition: send.c:126
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:89
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
bool mutt_addr_cmp(const struct Address *a, const struct Address *b)
Compare two e-mail addresses.
Definition: address.c:851
char * personal
Real name of address.
Definition: address.h:36
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:669
bool mutt_addrlist_search(const struct Address *needle, const struct AddressList *haystack)
Search for an e-mail address in a list.
Definition: address.c:868
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
#define TAILQ_EMPTY(head)
Definition: queue.h:715
int mutt_fetch_recips ( struct Envelope out,
struct Envelope in,
SendFlags  flags 
)

Generate recpients for a reply email.

Parameters
outEnvelope to populate
inEnvelope of source email
flagsFlags, see SendFlags
Return values
0Success
-1Failure

Definition at line 797 of file send.c.

798 {
799  enum QuadOption hmfupto = MUTT_ABORT;
800  const struct Address *followup_to = TAILQ_FIRST(&in->mail_followup_to);
801 
802  if ((flags & (SEND_LIST_REPLY | SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY)) && followup_to)
803  {
804  char prompt[256];
805  snprintf(prompt, sizeof(prompt), _("Follow-up to %s%s?"), followup_to->mailbox,
806  TAILQ_NEXT(TAILQ_FIRST(&in->mail_followup_to), entries) ? ",..." : "");
807 
808  hmfupto = query_quadoption(C_HonorFollowupTo, prompt);
809  if (hmfupto == MUTT_ABORT)
810  return -1;
811  }
812 
813  if (flags & SEND_LIST_REPLY)
814  {
815  add_mailing_lists(&out->to, &in->to, &in->cc);
816 
817  if (followup_to && (hmfupto == MUTT_YES) &&
818  (default_to(&out->cc, in, flags & SEND_LIST_REPLY, (hmfupto == MUTT_YES)) == MUTT_ABORT))
819  {
820  return -1; /* abort */
821  }
822  }
823  else if (flags & SEND_TO_SENDER)
824  {
825  mutt_addrlist_copy(&out->to, &in->from, false);
826  }
827  else
828  {
829  if (default_to(&out->to, in, flags & (SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY),
830  (hmfupto == MUTT_YES)) == -1)
831  return -1; /* abort */
832 
833  if ((flags & (SEND_GROUP_REPLY | SEND_GROUP_CHAT_REPLY)) &&
834  (!followup_to || (hmfupto != MUTT_YES)))
835  {
836  /* if(!mutt_addr_is_user(in->to)) */
837  if (flags & SEND_GROUP_REPLY)
838  mutt_addrlist_copy(&out->cc, &in->to, true);
839  else
840  mutt_addrlist_copy(&out->to, &in->cc, true);
841  mutt_addrlist_copy(&out->cc, &in->cc, true);
842  }
843  }
844  return 0;
845 }
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:99
#define TAILQ_FIRST(head)
Definition: queue.h:717
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:49
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
static int default_to(struct AddressList *to, struct Envelope *env, SendFlags flags, int hmfupto)
Generate default email addresses.
Definition: send.c:716
unsigned char C_HonorFollowupTo
Config: Honour the &#39;Mail-Followup-To&#39; header when group replying.
Definition: send.c:115
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:89
#define SEND_GROUP_REPLY
Reply to all.
Definition: send.h:88
static void add_mailing_lists(struct AddressList *out, const struct AddressList *t, const struct AddressList *c)
Search Address lists for mailing lists.
Definition: send.c:180
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
#define TAILQ_NEXT(elm, field)
Definition: queue.h:816
#define SEND_GROUP_CHAT_REPLY
Reply to all recipients preserving To/Cc.
Definition: send.h:100
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
static void add_references ( struct ListHead *  head,
struct Envelope env 
)
static

Add the email's references to a list.

Parameters
headList of references
envEnvelope of message

Definition at line 852 of file send.c.

853 {
854  struct ListNode *np = NULL;
855 
856  struct ListHead *src = !STAILQ_EMPTY(&env->references) ? &env->references : &env->in_reply_to;
857  STAILQ_FOREACH(np, src, entries)
858  {
860  }
861 }
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:68
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct ListHead references
message references (in reverse order)
Definition: envelope.h:67
A List node for strings.
Definition: list.h:33
static void add_message_id ( struct ListHead *  head,
struct Envelope env 
)
static

Add the email's message ID to a list.

Parameters
headList of message IDs
envEnvelope of message

Definition at line 868 of file send.c.

869 {
870  if (env->message_id)
871  {
873  }
874 }
char * message_id
Message ID.
Definition: envelope.h:55
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:46
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
void mutt_fix_reply_recipients ( struct Envelope env)

Remove duplicate recipients.

Parameters
envEnvelope to fix

Definition at line 880 of file send.c.

881 {
882  if (!C_Metoo)
883  {
884  /* the order is important here. do the CC: first so that if the
885  * the user is the only recipient, it ends up on the TO: field */
886  remove_user(&env->cc, TAILQ_EMPTY(&env->to));
887  remove_user(&env->to, TAILQ_EMPTY(&env->cc) || C_ReplySelf);
888  }
889 
890  /* the CC field can get cluttered, especially with lists */
891  mutt_addrlist_dedupe(&env->to);
892  mutt_addrlist_dedupe(&env->cc);
893  mutt_addrlist_remove_xrefs(&env->to, &env->cc);
894 
895  if (!TAILQ_EMPTY(&env->cc) && TAILQ_EMPTY(&env->to))
896  {
897  TAILQ_SWAP(&env->to, &env->cc, Address, entries);
898  }
899 }
bool C_ReplySelf
Config: Really reply to yourself, when replying to your own email.
Definition: send.c:125
An email address.
Definition: address.h:34
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1288
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
bool C_Metoo
Config: Remove the user&#39;s address from the list of recipients.
Definition: send.c:118
void mutt_addrlist_remove_xrefs(const struct AddressList *a, struct AddressList *b)
Remove cross-references.
Definition: address.c:1324
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
#define TAILQ_EMPTY(head)
Definition: queue.h:715
static void remove_user(struct AddressList *al, bool leave_only)
Remove any address which matches the current user.
Definition: send.c:161
#define TAILQ_SWAP(head1, head2, type, field)
Definition: queue.h:839
void mutt_make_forward_subject ( struct Envelope env,
struct Mailbox m,
struct Email e 
)

Create a subject for a forwarded email.

Parameters
envEnvelope for result
mMailbox
eEmail

Definition at line 907 of file send.c.

908 {
909  if (!env)
910  return;
911 
912  char buf[256];
913 
914  /* set the default subject for the message. */
915  mutt_make_string(buf, sizeof(buf), NONULL(C_ForwardFormat), NULL, m, e);
916  mutt_str_replace(&env->subject, buf);
917 }
#define NONULL(x)
Definition: string2.h:37
char * C_ForwardFormat
Config: printf-like format string to control the subject when forwarding a message.
Definition: send.c:112
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
char * subject
Email&#39;s subject.
Definition: envelope.h:52
#define mutt_make_string(BUF, BUFLEN, S, CTX, M, E)
Definition: hdrline.h:60
void mutt_make_misc_reply_headers ( struct Envelope env,
struct Envelope curenv 
)

Set subject for a reply.

Parameters
envEnvelope for result
curenvEnvelope of source email

Definition at line 924 of file send.c.

925 {
926  if (!env || !curenv)
927  return;
928 
929  /* This takes precedence over a subject that might have
930  * been taken from a List-Post header. Is that correct? */
931  if (curenv->real_subj)
932  {
933  FREE(&env->subject);
934  env->subject = mutt_mem_malloc(mutt_str_strlen(curenv->real_subj) + 5);
935  sprintf(env->subject, "Re: %s", curenv->real_subj);
936  }
937  else if (!env->subject)
939 }
char * real_subj
Offset of the real subject.
Definition: envelope.h:53
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * subject
Email&#39;s subject.
Definition: envelope.h:52
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
char * C_EmptySubject
Config: Subject to use when replying to an email with none.
Definition: send.c:103
void mutt_add_to_reference_headers ( struct Envelope env,
struct Envelope curenv 
)

Generate references for a reply email.

Parameters
envEnvelope for result
curenvEnvelope of source email

Definition at line 946 of file send.c.

947 {
948  add_references(&env->references, curenv);
949  add_message_id(&env->references, curenv);
950  add_message_id(&env->in_reply_to, curenv);
951 
952 #ifdef USE_NNTP
953  if (OptNewsSend && C_XCommentTo && !TAILQ_EMPTY(&curenv->from))
955 #endif
956 }
#define TAILQ_FIRST(head)
Definition: queue.h:717
static void add_references(struct ListHead *head, struct Envelope *env)
Add the email&#39;s references to a list.
Definition: send.c:852
static void add_message_id(struct ListHead *head, struct Envelope *env)
Add the email&#39;s message ID to a list.
Definition: send.c:868
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:68
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
char * x_comment_to
List of &#39;X-comment-to&#39; fields.
Definition: envelope.h:64
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
WHERE bool C_XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:281
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct ListHead references
message references (in reverse order)
Definition: envelope.h:67
const char * mutt_get_name(const struct Address *a)
Pick the best name to display from an address.
Definition: sort.c:156
static void make_reference_headers ( struct EmailList *  el,
struct Envelope env 
)
static

Generate reference headers for an email.

Parameters
elList of source Emails
envEnvelope for result

Definition at line 963 of file send.c.

964 {
965  if (!el || !env || STAILQ_EMPTY(el))
966  return;
967 
968  struct EmailNode *en = STAILQ_FIRST(el);
969  bool single = !STAILQ_NEXT(en, entries);
970 
971  if (!single)
972  {
973  STAILQ_FOREACH(en, el, entries)
974  {
976  }
977  }
978  else
980 
981  /* if there's more than entry in In-Reply-To (i.e. message has multiple
982  * parents), don't generate a References: header as it's discouraged by
983  * RFC2822, sect. 3.6.4 */
984  if (!single && !STAILQ_EMPTY(&env->in_reply_to) &&
985  STAILQ_NEXT(STAILQ_FIRST(&env->in_reply_to), entries))
986  {
987  mutt_list_free(&env->references);
988  }
989 }
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:68
struct Envelope * env
Envelope information.
Definition: email.h:89
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
struct Email * email
Email in the list.
Definition: email.h:119
#define STAILQ_EMPTY(head)
Definition: queue.h:346
List of Emails.
Definition: email.h:117
struct ListHead references
message references (in reverse order)
Definition: envelope.h:67
#define STAILQ_FIRST(head)
Definition: queue.h:348
void mutt_add_to_reference_headers(struct Envelope *env, struct Envelope *curenv)
Generate references for a reply email.
Definition: send.c:946
static int envelope_defaults ( struct Envelope env,
struct Mailbox m,
struct EmailList *  el,
SendFlags  flags 
)
static

Fill in some defaults for a new email.

Parameters
envEnvelope for result
mMailbox
elList of Emails to use
flagsFlags, see SendFlags
Return values
0Success
-1Failure

Definition at line 1000 of file send.c.

1002 {
1003  if (!el || STAILQ_EMPTY(el))
1004  return -1;
1005 
1006  struct EmailNode *en = STAILQ_FIRST(el);
1007  bool single = !STAILQ_NEXT(en, entries);
1008 
1009  struct Envelope *curenv = en->email->env;
1010  if (!curenv)
1011  return -1;
1012 
1013  if (flags & (SEND_REPLY | SEND_TO_SENDER))
1014  {
1015 #ifdef USE_NNTP
1016  if ((flags & SEND_NEWS))
1017  {
1018  /* in case followup set Newsgroups: with Followup-To: if it present */
1019  if (!env->newsgroups &&
1020  (mutt_str_strcasecmp(curenv->followup_to, "poster") != 0))
1021  {
1022  env->newsgroups = mutt_str_strdup(curenv->followup_to);
1023  }
1024  }
1025  else
1026 #endif
1027  if (!single)
1028  {
1029  STAILQ_FOREACH(en, el, entries)
1030  {
1031  if (mutt_fetch_recips(env, en->email->env, flags) == -1)
1032  return -1;
1033  }
1034  }
1035  else if (mutt_fetch_recips(env, curenv, flags) == -1)
1036  return -1;
1037 
1038  if ((flags & SEND_LIST_REPLY) && TAILQ_EMPTY(&env->to))
1039  {
1040  mutt_error(_("No mailing lists found"));
1041  return -1;
1042  }
1043 
1044  if (flags & SEND_REPLY)
1045  {
1046  mutt_make_misc_reply_headers(env, curenv);
1047  make_reference_headers(el, env);
1048  }
1049  }
1050  else if (flags & SEND_FORWARD)
1051  {
1052  mutt_make_forward_subject(env, m, en->email);
1053  if (C_ForwardReferences)
1054  make_reference_headers(el, env);
1055  }
1056 
1057  return 0;
1058 }
static void make_reference_headers(struct EmailList *el, struct Envelope *env)
Generate reference headers for an email.
Definition: send.c:963
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:99
#define SEND_FORWARD
Forward email.
Definition: send.h:90
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, SendFlags flags)
Generate recpients for a reply email.
Definition: send.c:797
#define _(a)
Definition: message.h:28
void mutt_make_misc_reply_headers(struct Envelope *env, struct Envelope *curenv)
Set subject for a reply.
Definition: send.c:924
struct Envelope * env
Envelope information.
Definition: email.h:89
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:89
#define SEND_NEWS
Reply to a news article.
Definition: send.h:101
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
#define SEND_REPLY
Reply to sender.
Definition: send.h:87
char * newsgroups
List of newsgroups.
Definition: envelope.h:61
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
struct Email * email
Email in the list.
Definition: email.h:119
#define mutt_error(...)
Definition: logging.h:84
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:63
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
void mutt_make_forward_subject(struct Envelope *env, struct Mailbox *m, struct Email *e)
Create a subject for a forwarded email.
Definition: send.c:907
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
List of Emails.
Definition: email.h:117
bool C_ForwardReferences
Config: Set the &#39;In-Reply-To&#39; and &#39;References&#39; headers when forwarding a message. ...
Definition: send.c:113
#define TAILQ_EMPTY(head)
Definition: queue.h:715
#define STAILQ_FIRST(head)
Definition: queue.h:348
The header of an Email.
Definition: envelope.h:40
static int generate_body ( FILE *  fp_tmp,
struct Email e,
SendFlags  flags,
struct Mailbox m,
struct EmailList *  el 
)
static

Create a new email body.

Parameters
fp_tmpStream for outgoing message
eEmail for outgoing message
flagsCompose mode, see SendFlags
mMailbox
elList of Emails to use
Return values
0Success
-1Error

Definition at line 1070 of file send.c.

1072 {
1073  struct Body *tmp = NULL;
1074  struct EmailNode *en = NULL;
1075  bool single = true;
1076 
1077  if (el)
1078  en = STAILQ_FIRST(el);
1079  if (en)
1080  single = !STAILQ_NEXT(en, entries);
1081 
1082  /* An EmailList is required for replying and forwarding */
1083  if (!el && (flags & (SEND_REPLY | SEND_FORWARD)))
1084  return -1;
1085 
1086  if (flags & SEND_REPLY)
1087  {
1088  enum QuadOption ans =
1089  query_quadoption(C_Include, _("Include message in reply?"));
1090  if (ans == MUTT_ABORT)
1091  return -1;
1092 
1093  if (ans == MUTT_YES)
1094  {
1095  mutt_message(_("Including quoted message..."));
1096  if (!single)
1097  {
1098  STAILQ_FOREACH(en, el, entries)
1099  {
1100  if (include_reply(m, en->email, fp_tmp) == -1)
1101  {
1102  mutt_error(_("Could not include all requested messages"));
1103  return -1;
1104  }
1105  fputc('\n', fp_tmp);
1106  }
1107  }
1108  else
1109  include_reply(m, en->email, fp_tmp);
1110  }
1111  }
1112  else if (flags & SEND_FORWARD)
1113  {
1114  enum QuadOption ans =
1115  query_quadoption(C_MimeForward, _("Forward as attachment?"));
1116  if (ans == MUTT_YES)
1117  {
1118  struct Body *last = e->content;
1119 
1120  mutt_message(_("Preparing forwarded message..."));
1121 
1122  while (last && last->next)
1123  last = last->next;
1124 
1125  if (single)
1126  {
1127  tmp = mutt_make_message_attach(m, en->email, false);
1128  if (last)
1129  last->next = tmp;
1130  else
1131  e->content = tmp;
1132  }
1133  else
1134  {
1135  STAILQ_FOREACH(en, el, entries)
1136  {
1137  tmp = mutt_make_message_attach(m, en->email, false);
1138  if (last)
1139  {
1140  last->next = tmp;
1141  last = tmp;
1142  }
1143  else
1144  {
1145  last = tmp;
1146  e->content = tmp;
1147  }
1148  }
1149  }
1150  }
1151  else if (ans != MUTT_ABORT)
1152  {
1153  if (mutt_inline_forward(m, e, en->email, fp_tmp) != 0)
1154  return -1;
1155  }
1156  else
1157  return -1;
1158  }
1159  /* if (WithCrypto && (flags & SEND_KEY)) */
1160  else if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY))
1161  {
1162  struct Body *b = NULL;
1163 
1164  if (((WithCrypto & APPLICATION_PGP) != 0) && !(b = crypt_pgp_make_key_attachment()))
1165  {
1166  return -1;
1167  }
1168 
1169  b->next = e->content;
1170  e->content = b;
1171  }
1172 
1173  mutt_clear_error();
1174 
1175  return 0;
1176 }
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg)
Create a message attachment.
Definition: sendlib.c:1477
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
#define mutt_message(...)
Definition: logging.h:83
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define SEND_FORWARD
Forward email.
Definition: send.h:90
struct Body * content
List of MIME parts.
Definition: email.h:90
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
unsigned char C_Include
Config: Include a copy of the email that&#39;s being replied to.
Definition: send.c:117
The body of an email.
Definition: body.h:34
WHERE unsigned char C_MimeForward
Config: Forward a message as a &#39;message/RFC822&#39; MIME part.
Definition: globals.h:184
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:94
static int include_reply(struct Mailbox *m, struct Email *e, FILE *fp_out)
Generate the reply text for an email.
Definition: send.c:674
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
#define SEND_REPLY
Reply to sender.
Definition: send.h:87
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition: cryptglue.c:261
struct Email * email
Email in the list.
Definition: email.h:119
#define mutt_error(...)
Definition: logging.h:84
List of Emails.
Definition: email.h:117
#define STAILQ_FIRST(head)
Definition: queue.h:348
#define WithCrypto
Definition: ncrypt.h:156
int mutt_inline_forward(struct Mailbox *m, struct Email *e_edit, struct Email *e_cur, FILE *out)
Forward attachments, inline.
Definition: send.c:592
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
void mutt_set_followup_to ( struct Envelope env)

Set followup-to field.

Parameters
envEnvelope to modify

Definition at line 1182 of file send.c.

1183 {
1184  /* Only generate the Mail-Followup-To if the user has requested it, and
1185  * it hasn't already been set */
1186 
1187  if (!C_FollowupTo)
1188  return;
1189 #ifdef USE_NNTP
1190  if (OptNewsSend)
1191  {
1192  if (!env->followup_to && env->newsgroups && (strrchr(env->newsgroups, ',')))
1193  env->followup_to = mutt_str_strdup(env->newsgroups);
1194  return;
1195  }
1196 #endif
1197 
1198  if (TAILQ_EMPTY(&env->mail_followup_to))
1199  {
1200  if (mutt_is_list_recipient(false, env))
1201  {
1202  /* this message goes to known mailing lists, so create a proper
1203  * mail-followup-to header */
1204 
1205  mutt_addrlist_copy(&env->mail_followup_to, &env->to, false);
1206  mutt_addrlist_copy(&env->mail_followup_to, &env->cc, true);
1207  }
1208 
1209  /* remove ourselves from the mail-followup-to header */
1210  remove_user(&env->mail_followup_to, false);
1211 
1212  /* If we are not subscribed to any of the lists in question, re-add
1213  * ourselves to the mail-followup-to header. The mail-followup-to header
1214  * generated is a no-op with group-reply, but makes sure list-reply has the
1215  * desired effect. */
1216 
1217  if (!TAILQ_EMPTY(&env->mail_followup_to) &&
1218  !mutt_is_subscribed_list_recipient(false, env))
1219  {
1220  struct AddressList *al = NULL;
1221  if (!TAILQ_EMPTY(&env->reply_to))
1222  al = &env->reply_to;
1223  else if (!TAILQ_EMPTY(&env->from))
1224  al = &env->from;
1225 
1226  if (al)
1227  {
1228  struct Address *a = NULL;
1229  TAILQ_FOREACH_REVERSE(a, al, AddressList, entries)
1230  {
1232  }
1233  }
1234  else
1235  {
1237  }
1238  }
1239 
1241  }
1242 }
struct AddressList mail_followup_to
Email&#39;s &#39;mail-followup-to&#39;.
Definition: envelope.h:49
struct AddressList reply_to
Email&#39;s &#39;reply-to&#39;.
Definition: envelope.h:48
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
int mutt_is_list_recipient(bool alladdr, struct Envelope *e)
Matches known mailing lists.
Definition: pattern.c:1783
An email address.
Definition: address.h:34
bool C_FollowupTo
Config: Add the &#39;Mail-Followup-To&#39; header is generated when sending mail.
Definition: send.c:108
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:703
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1288
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
Definition: queue.h:739
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
int mutt_is_subscribed_list_recipient(bool alladdr, struct Envelope *e)
Matches subscribed mailing lists.
Definition: pattern.c:1771
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1302
void mutt_addrlist_prepend(struct AddressList *al, struct Address *a)
Prepend an Address to an AddressList.
Definition: address.c:1382
char * newsgroups
List of newsgroups.
Definition: envelope.h:61
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * followup_to
List of &#39;followup-to&#39; fields.
Definition: envelope.h:63
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
static void remove_user(struct AddressList *al, bool leave_only)
Remove any address which matches the current user.
Definition: send.c:161
static void set_reverse_name ( struct AddressList *  al,
struct Envelope env 
)
static

Try to set the 'from' field from the recipients.

Parameters
alAddressList to prepend the found address
envEnvelope to use

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 from field

Definition at line 1253 of file send.c.

1254 {
1255  struct Address *a = NULL;
1256  if (TAILQ_EMPTY(al))
1257  {
1258  TAILQ_FOREACH(a, &env->to, entries)
1259  {
1260  if (mutt_addr_is_user(a))
1261  {
1263  break;
1264  }
1265  }
1266  }
1267 
1268  if (TAILQ_EMPTY(al))
1269  {
1270  TAILQ_FOREACH(a, &env->cc, entries)
1271  {
1272  if (mutt_addr_is_user(a))
1273  {
1275  break;
1276  }
1277  }
1278  }
1279 
1280  if (TAILQ_EMPTY(al))
1281  {
1282  struct Address *from = TAILQ_FIRST(&env->from);
1283  if (from && mutt_addr_is_user(from))
1284  {
1286  }
1287  }
1288 
1289  if (!TAILQ_EMPTY(al))
1290  {
1291  /* when $reverse_realname is not set, clear the personal name so that it
1292  * may be set via a reply- or send-hook. */
1293  if (!C_ReverseRealname)
1294  FREE(&TAILQ_FIRST(al)->personal);
1295  }
1296 }
#define TAILQ_FIRST(head)
Definition: queue.h:717
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:703
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
bool C_ReverseRealname
Config: Set the &#39;From&#39; from the full &#39;To&#39; address the email was sent to.
Definition: send.c:129
char * personal
Real name of address.
Definition: address.h:36
#define FREE(x)
Definition: memory.h:40
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:669
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
#define TAILQ_EMPTY(head)
Definition: queue.h:715
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1371
struct Address* mutt_default_from ( void  )

Get a default 'from' Address.

Return values
ptrNewly allocated Address

Definition at line 1302 of file send.c.

1303 {
1304  /* Note: We let $from override $realname here.
1305  * Is this the right thing to do?
1306  */
1307 
1308  if (C_From)
1309  {
1310  return mutt_addr_copy(C_From);
1311  }
1312  else if (C_UseDomain)
1313  {
1314  struct Address *addr = mutt_addr_new();
1315  mutt_str_asprintf(&addr->mailbox, "%s@%s", NONULL(Username), NONULL(mutt_fqdn(true)));
1316  return addr;
1317  }
1318  else
1319  {
1320  return mutt_addr_create(NULL, Username);
1321  }
1322 }
WHERE char * Username
User&#39;s login name.
Definition: globals.h:51
#define NONULL(x)
Definition: string2.h:37
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:384
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:703
struct Address * mutt_addr_create(const char *personal, const char *mailbox)
Create and populate a new Address.
Definition: address.c:397
WHERE bool C_UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:257
WHERE struct Address * C_From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:93
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2449
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1230
static int send_message ( struct Email e)
static

Send an email.

Parameters
eEmail
Return values
0Success
-1Failure

Definition at line 1330 of file send.c.

1331 {
1332  char tempfile[PATH_MAX];
1333  int i;
1334 #ifdef USE_SMTP
1335  short old_write_bcc;
1336 #endif
1337 
1338  /* Write out the message in MIME form. */
1339  mutt_mktemp(tempfile, sizeof(tempfile));
1340  FILE *fp_tmp = mutt_file_fopen(tempfile, "w");
1341  if (!fp_tmp)
1342  return -1;
1343 
1344 #ifdef USE_SMTP
1345  old_write_bcc = C_WriteBcc;
1346  if (C_SmtpUrl)
1347  C_WriteBcc = false;
1348 #endif
1349 #ifdef MIXMASTER
1351  !STAILQ_EMPTY(&e->chain),
1353 #endif
1354 #ifndef MIXMASTER
1357 #endif
1358 #ifdef USE_SMTP
1359  if (old_write_bcc)
1360  C_WriteBcc = true;
1361 #endif
1362 
1363  fputc('\n', fp_tmp); /* tie off the header. */
1364 
1365  if ((mutt_write_mime_body(e->content, fp_tmp) == -1))
1366  {
1367  mutt_file_fclose(&fp_tmp);
1368  unlink(tempfile);
1369  return -1;
1370  }
1371 
1372  if (fclose(fp_tmp) != 0)
1373  {
1374  mutt_perror(tempfile);
1375  unlink(tempfile);
1376  return -1;
1377  }
1378 
1379 #ifdef MIXMASTER
1380  if (!STAILQ_EMPTY(&e->chain))
1381  return mix_send_message(&e->chain, tempfile);
1382 #endif
1383 
1384 #ifdef USE_SMTP
1385 #ifdef USE_NNTP
1386  if (!OptNewsSend)
1387 #endif
1388  if (C_SmtpUrl)
1389  {
1390  return mutt_smtp_send(&e->env->from, &e->env->to, &e->env->cc, &e->env->bcc,
1391  tempfile, (e->content->encoding == ENC_8BIT));
1392  }
1393 #endif /* USE_SMTP */
1394 
1395  i = mutt_invoke_sendmail(&e->env->from, &e->env->to, &e->env->cc, &e->env->bcc,
1396  tempfile, (e->content->encoding == ENC_8BIT));
1397  return i;
1398 }
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:140
WHERE bool C_WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:260
#define mutt_perror(...)
Definition: logging.h:85
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:46
A normal Email, write full header + MIME headers.
Definition: sendlib.h:64
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1037
struct Body * content
List of MIME parts.
Definition: email.h:90
8-bit text
Definition: mime.h:50
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, enum MuttWriteHeaderMode mode, bool privacy, bool hide_protected_subject)
Write out one RFC822 header line.
Definition: sendlib.c:2229
int mutt_invoke_sendmail(struct AddressList *from, struct AddressList *to, struct AddressList *cc, struct AddressList *bcc, const char *msg, int eightbit)
Run sendmail.
Definition: sendlib.c:2741
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
struct Envelope * env
Envelope information.
Definition: email.h:89
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#define PATH_MAX
Definition: mutt.h:50
int mutt_write_mime_body(struct Body *a, FILE *fp)
Write a MIME part.
Definition: sendlib.c:511
int mix_send_message(struct ListHead *chain, const char *tempfile)
Send an email via Mixmaster.
Definition: remailer.c:828
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
int mutt_smtp_send(const struct AddressList *from, const struct AddressList *to, const struct AddressList *cc, const struct AddressList *bcc, const char *msgfile, bool eightbit)
Send a message using SMTP.
Definition: smtp.c:730
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
void mutt_encode_descriptions ( struct Body b,
bool  recurse 
)

rfc2047 encode the content-descriptions

Parameters
bBody of email
recurseIf true, encode children parts

Definition at line 1405 of file send.c.

1406 {
1407  for (struct Body *t = b; t; t = t->next)
1408  {
1409  if (t->description)
1410  {
1411  rfc2047_encode(&t->description, NULL, sizeof("Content-Description:"), C_SendCharset);
1412  }
1413  if (recurse && t->parts)
1414  mutt_encode_descriptions(t->parts, recurse);
1415  }
1416 }
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: email_globals.c:38
void mutt_encode_descriptions(struct Body *b, bool recurse)
rfc2047 encode the content-descriptions
Definition: send.c:1405
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:625
static void decode_descriptions ( struct Body b)
static

rfc2047 decode them in case of an error

Parameters
bMIME parts to decode

Definition at line 1422 of file send.c.

1423 {
1424  for (struct Body *t = b; t; t = t->next)
1425  {
1426  if (t->description)
1427  {
1428  rfc2047_decode(&t->description);
1429  }
1430  if (t->parts)
1431  decode_descriptions(t->parts);
1432  }
1433 }
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:649
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1422
static void fix_end_of_file ( const char *  data)
static

Ensure a file ends with a linefeed.

Parameters
dataName of file to fix

Definition at line 1439 of file send.c.

1440 {
1441  FILE *fp = mutt_file_fopen(data, "a+");
1442  if (!fp)
1443  return;
1444  if (fseek(fp, -1, SEEK_END) >= 0)
1445  {
1446  int c = fgetc(fp);
1447  if (c != '\n')
1448  fputc('\n', fp);
1449  }
1450  mutt_file_fclose(&fp);
1451 }
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
int mutt_resend_message ( FILE *  fp,
struct Context ctx,
struct Email e_cur 
)

Resend an email.

Parameters
fpFile containing email
ctxMailbox
e_curEmail to resend
Return values
0Message was successfully sent
-1Message was aborted or an error occurred
1Message was postponed

Definition at line 1462 of file send.c.

1463 {
1464  struct Email *e_new = mutt_email_new();
1465 
1466  if (mutt_prepare_template(fp, ctx->mailbox, e_new, e_cur, true) < 0)
1467  {
1468  mutt_email_free(&e_new);
1469  return -1;
1470  }
1471 
1472  if (WithCrypto)
1473  {
1474  /* mutt_prepare_template doesn't always flip on an application bit.
1475  * so fix that here */
1476  if (!(e_new->security & (APPLICATION_SMIME | APPLICATION_PGP)))
1477  {
1478  if (((WithCrypto & APPLICATION_SMIME) != 0) && C_SmimeIsDefault)
1479  e_new->security |= APPLICATION_SMIME;
1480  else if (WithCrypto & APPLICATION_PGP)
1481  e_new->security |= APPLICATION_PGP;
1482  else
1483  e_new->security |= APPLICATION_SMIME;
1484  }
1485 
1487  {
1488  e_new->security |= SEC_OPPENCRYPT;
1490  }
1491  }
1492 
1493  struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
1494  el_add_email(&el, e_cur);
1495  int rc = ci_send_message(SEND_RESEND, e_new, NULL, ctx, &el);
1496  mutt_emaillist_free(&el);
1497 
1498  return rc;
1499 }
The envelope/body of an email.
Definition: email.h:37
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
WHERE bool C_SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:271
struct Mailbox * mailbox
Definition: context.h:53
int el_add_email(struct EmailList *el, struct Email *e)
Get a list of the selected Emails.
Definition: context.c:374
#define SEND_RESEND
Reply using the current email as a template.
Definition: send.h:95
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:267
void mutt_emaillist_free(struct EmailList *el)
Drop a private list of Emails.
Definition: email.c:122
int ci_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el)
Send an email.
Definition: send.c:1830
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
void mutt_email_free(struct Email **e)
Free an Email.
Definition: email.c:41
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:129
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:985
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:322
#define WithCrypto
Definition: ncrypt.h:156
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:582
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:131
static bool is_reply ( struct Email reply,
struct Email orig 
)
static

Is one email a reply to another?

Parameters
replyEmail to test
origOriginal email
Return values
trueIt is a reply
falseIt is not a reply

Definition at line 1508 of file send.c.

1509 {
1510  if (!reply || !reply->env || !orig || !orig->env)
1511  return false;
1512  return mutt_list_find(&orig->env->references, reply->env->message_id) ||
1513  mutt_list_find(&orig->env->in_reply_to, reply->env->message_id);
1514 }
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:68
char * message_id
Message ID.
Definition: envelope.h:55
struct Envelope * env
Envelope information.
Definition: email.h:89
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:103
struct ListHead references
message references (in reverse order)
Definition: envelope.h:67
static bool search_attach_keyword ( char *  filename)
static

Search an email for 'attachment' keywords.

Parameters
filenameFilename
Return values
trueIf the regex matches in the email

Search an email for the regex in $abort_noattach_regex. A match might indicate that the user should have attached something.

Note
Quoted lines (as defined by $quote_regex) are ignored

Definition at line 1526 of file send.c.

1527 {
1528  /* Search for the regex in C_AbortNoattachRegex within a file */
1530  !C_QuoteRegex->regex)
1531  {
1532  return false;
1533  }
1534 
1535  FILE *fp_att = mutt_file_fopen(filename, "r");
1536  if (!fp_att)
1537  return false;
1538 
1539  char *inputline = mutt_mem_malloc(1024);
1540  bool found = false;
1541  while (!feof(fp_att))
1542  {
1543  fgets(inputline, 1024, fp_att);
1544  if (!mutt_is_quote_line(inputline, NULL) &&
1545  (regexec(C_AbortNoattachRegex->regex, inputline, 0, NULL, 0) == 0))
1546  {
1547  found = true;
1548  break;
1549  }
1550  }
1551  FREE(&inputline);
1552  mutt_file_fclose(&fp_att);
1553  return found;
1554 }
struct Regex * C_AbortNoattachRegex
Config: Regex to match text indicating attachments are expected.
Definition: send.c:90
regex_t * regex
compiled expression
Definition: regex3.h:60
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
WHERE struct Regex * C_QuoteRegex
Config: Regex to match quoted text in a reply.
Definition: globals.h:177
#define FREE(x)
Definition: memory.h:40
int mutt_is_quote_line(char *line, regmatch_t *pmatch)
Is a line of message text a quote?
Definition: pager.c:878
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
static int save_fcc ( struct Email e,
char *  fcc,
size_t  fcc_len,
struct Body clear_content,
char *  pgpkeylist,
SendFlags  flags,
char **  finalpath 
)
static

Save an Email to a 'sent mail' folder.

Parameters
[in]eEmail to save
[in]fccFolder to save to (can be comma-separated list)
[in]fcc_lenLength of fcc buffer
[in]clear_contentCleartext content of Email
[in]pgpkeylistList of pgp keys
[in]flagsSend mode, see SendFlags
[out]finalpathPath of final folder
Return values
0Success
-1Error

Definition at line 1568 of file send.c.

1570 {
1571  int rc = 0;
1572  struct Body *save_content = NULL;
1573 
1574  mutt_expand_path(fcc, fcc_len);
1575 
1576  /* Don't save a copy when we are in batch-mode, and the FCC
1577  * folder is on an IMAP server: This would involve possibly lots
1578  * of user interaction, which is not available in batch mode.
1579  *
1580  * Note: A patch to fix the problems with the use of IMAP servers
1581  * from non-curses mode is available from Brendan Cully. However,
1582  * I'd like to think a bit more about this before including it. */
1583 
1584 #ifdef USE_IMAP
1585  if ((flags & SEND_BATCH) && (fcc[0] != '\0') && (imap_path_probe(fcc, NULL) == MUTT_IMAP))
1586  {
1587  fcc[0] = '\0';
1588  mutt_error(_("Fcc to an IMAP mailbox is not supported in batch mode"));
1589  return rc;
1590  }
1591 #endif
1592 
1593  if (!(*fcc && mutt_str_strcmp("/dev/null", fcc)))
1594  return rc;
1595 
1596  struct Body *tmpbody = e->content;
1597  struct Body *save_sig = NULL;
1598  struct Body *save_parts = NULL;
1599 
1600  /* Before sending, we don't allow message manipulation because it
1601  * will break message signatures. This is especially complicated by
1602  * Protected Headers. */
1603  if (!C_FccBeforeSend)
1604  {
1605  if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN)) && C_FccClear)
1606  {
1607  e->content = clear_content;
1608  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
1610  }
1611 
1612  /* check to see if the user wants copies of all attachments */
1613  if (e->content->type == TYPE_MULTIPART)
1614  {
1615  if ((WithCrypto != 0) && (e->security & (SEC_ENCRYPT | SEC_SIGN)) &&
1616  ((mutt_str_strcmp(e->content->subtype, "encrypted") == 0) ||
1617  (mutt_str_strcmp(e->content->subtype, "signed") == 0)))
1618  {
1619  if ((clear_content->type == TYPE_MULTIPART) &&
1620  (query_quadoption(C_FccAttach, _("Save attachments in Fcc?")) == MUTT_NO))
1621  {
1622  if (!(e->security & SEC_ENCRYPT) && (e->security & SEC_SIGN))
1623  {
1624  /* save initial signature and attachments */
1625  save_sig = e->content->parts->next;
1626  save_parts = clear_content->parts->next;
1627  }
1628 
1629  /* this means writing only the main part */
1630  e->content = clear_content->parts;
1631 
1632  if (mutt_protect(e, pgpkeylist) == -1)
1633  {
1634  /* we can't do much about it at this point, so
1635  * fallback to saving the whole thing to fcc */
1636  e->content = tmpbody;
1637  save_sig = NULL;
1638  goto full_fcc;
1639  }
1640 
1641  save_content = e->content;
1642  }
1643  }
1644  else
1645  {
1646  if (query_quadoption(C_FccAttach, _("Save attachments in Fcc?")) == MUTT_NO)
1647  e->content = e->content->parts;
1648  }
1649  }
1650  }
1651 
1652 full_fcc:
1653  if (e->content)
1654  {
1655  /* update received time so that when storing to a mbox-style folder
1656  * the From_ line contains the current time instead of when the
1657  * message was first postponed. */
1658  e->received = time(NULL);
1659  rc = mutt_write_multiple_fcc(fcc, e, NULL, false, NULL, finalpath);
1660  while (rc && !(flags & SEND_BATCH))
1661  {
1662  mutt_clear_error();
1663  int choice = mutt_multi_choice(
1664  /* L10N: Called when saving to $record or Fcc failed after sending.
1665  (r)etry tries the same mailbox again.
1666  alternate (m)ailbox prompts for a different mailbox to try.
1667  (s)kip aborts saving. */
1668  _("Fcc failed. (r)etry, alternate (m)ailbox, or (s)kip?"),
1669  /* L10N: These correspond to the "Fcc failed" multi-choice prompt
1670  (r)etry, alternate (m)ailbox, or (s)kip.
1671  Any similarity to famous leaders of the FSF is coincidental. */
1672  _("rms"));
1673  switch (choice)
1674  {
1675  case 2: /* alternate (m)ailbox */
1676  /* L10N: This is the prompt to enter an "alternate (m)ailbox" when the
1677  initial Fcc fails. */
1678  rc = mutt_enter_fname(_("Fcc mailbox"), fcc, fcc_len, true);
1679  if ((rc == -1) || (fcc[0] == '\0'))
1680  {
1681  rc = 0;
1682  break;
1683  }
1684  /* fall through */
1685 
1686  case 1: /* (r)etry */
1687  rc = mutt_write_multiple_fcc(fcc, e, NULL, false, NULL, finalpath);
1688  break;
1689 
1690  case -1: /* abort */
1691  case 3: /* (s)kip */
1692  rc = 0;
1693  break;
1694  }
1695  }
1696  }
1697 
1698  if (!C_FccBeforeSend)
1699  {
1700  e->content = tmpbody;
1701 
1702  if ((WithCrypto != 0) && save_sig)
1703  {
1704  /* cleanup the second signature structures */
1705  if (save_content->parts)
1706  {
1707  mutt_body_free(&save_content->parts->next);
1708  save_content->parts = NULL;
1709  }
1710  mutt_body_free(&save_content);
1711 
1712  /* restore old signature and attachments */
1713  e->content->parts->next = save_sig;
1714  e->content->parts->parts->next = save_parts;
1715  }
1716  else if ((WithCrypto != 0) && save_content)
1717  {
1718  /* destroy the new encrypted body. */
1719  mutt_body_free(&save_content);
1720  }
1721  }
1722 
1723  return 0;
1724 }
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2432
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
bool C_FccBeforeSend
Config: Save FCCs before sending the message.
Definition: send.c:106
struct Body * content
List of MIME parts.
Definition: email.h:90
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
The body of an email.
Definition: body.h:34
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
int mutt_write_multiple_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath)
Handle FCC with multiple, comma separated entries.
Definition: sendlib.c:3121
char * subtype
content-type subtype
Definition: body.h:37
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:839
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:122
unsigned char C_FccAttach
Config: Save send message with all their attachments.
Definition: send.c:105
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
bool C_FccClear
Config: Save sent messages unencrypted and unsigned.
Definition: send.c:107
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
unsigned int type
content-type primary type
Definition: body.h:65
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
#define mutt_error(...)
Definition: logging.h:84
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:63
#define mutt_enter_fname(prompt, buf, buflen, mailbox)
Definition: curs_lib.h:85
int mutt_protect(struct Email *e, char *keylist)
Encrypt and/or sign a message.
Definition: crypt.c:167
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
#define WithCrypto
Definition: ncrypt.h:156
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:82
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:92
static int postpone_message ( struct Email e_post,
struct Email e_cur,
char *  fcc,
SendFlags  flags 
)
static

Save an Email for another day.

Parameters
e_postEmail to postpone
e_curCurrent Email in the index
fccFolder for 'sent mail'
flagsSend mode, see SendFlags
Return values
0Success
-1Error

Definition at line 1735 of file send.c.

1736 {
1737  char *pgpkeylist = NULL;
1738  char *encrypt_as = NULL;
1739  struct Body *clear_content = NULL;
1740 
1741  if (!C_Postponed)
1742  {
1743  mutt_error(_("Can't postpone. $postponed is unset"));
1744  return -1;
1745  }
1746 
1747  if (e_post->content->next)
1748  e_post->content = mutt_make_multipart(e_post->content);
1749 
1750  mutt_encode_descriptions(e_post->content, true);
1751 
1752  if ((WithCrypto != 0) && C_PostponeEncrypt && (e_post->security & SEC_ENCRYPT))
1753  {
1754  if (((WithCrypto & APPLICATION_PGP) != 0) && (e_post->security & APPLICATION_PGP))
1755  encrypt_as = C_PgpDefaultKey;
1756  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (e_post->security & APPLICATION_SMIME))
1757  encrypt_as = C_SmimeDefaultKey;
1758  if (!(encrypt_as && *encrypt_as))
1759  encrypt_as = C_PostponeEncryptAs;
1760 
1761  if (encrypt_as && *encrypt_as)
1762  {
1763  bool is_signed = (e_post->security & SEC_SIGN);
1764  if (is_signed)
1765  e_post->security &= ~SEC_SIGN;
1766 
1767  pgpkeylist = mutt_str_strdup(encrypt_as);
1768  clear_content = e_post->content;
1769  if (mutt_protect(e_post, pgpkeylist) == -1)
1770  {
1771  if (is_signed)
1772  e_post->security |= SEC_SIGN;
1773  FREE(&pgpkeylist);
1774  e_post->content = mutt_remove_multipart(e_post->content);
1775  decode_descriptions(e_post->content);
1776  return -1;
1777  }
1778 
1779  if (is_signed)
1780  e_post->security |= SEC_SIGN;
1781  FREE(&pgpkeylist);
1782 
1783  mutt_encode_descriptions(e_post->content, false);
1784  }
1785  }
1786 
1787  /* make sure the message is written to the right part of a maildir
1788  * postponed folder. */
1789  e_post->read = false;
1790  e_post->old = false;
1791 
1792  mutt_prepare_envelope(e_post->env, false);
1793  mutt_env_to_intl(e_post->env, NULL, NULL); /* Handle bad IDNAs the next time. */
1794 
1795  if (mutt_write_fcc(NONULL(C_Postponed), e_post,
1796  (e_cur && (flags & SEND_REPLY)) ? e_cur->env->message_id : NULL,
1797  true, fcc, NULL) < 0)
1798  {
1799  if (clear_content)
1800  {
1801  mutt_body_free(&e_post->content);
1802  e_post->content = clear_content;
1803  }
1804  mutt_env_free(&e_post->content->mime_headers); /* protected headers */
1805  e_post->content = mutt_remove_multipart(e_post->content);
1806  decode_descriptions(e_post->content);
1807  mutt_unprepare_envelope(e_post->env);
1808  return -1;
1809  }
1810 
1812 
1813  if (clear_content)
1814  mutt_body_free(&clear_content);
1815 
1816  return 0;
1817 }
char * C_PostponeEncryptAs
Config: Fallback encryption key for postponed messages.
Definition: send.c:123
#define NONULL(x)
Definition: string2.h:37
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1733
WHERE char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: globals.h:166
struct Body * content
List of MIME parts.
Definition: email.h:90
bool C_PostponeEncrypt
Config: Self-encrypt postponed messages.
Definition: send.c:122
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:53
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:260
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
The body of an email.
Definition: body.h:34
void mutt_prepare_envelope(struct Envelope *env, bool final)
Prepare an email header.
Definition: sendlib.c:2919
bool read
Email is read.
Definition: email.h:51
char * message_id
Message ID.
Definition: envelope.h:55
bool old
Email is seen, but unread.
Definition: email.h:50
struct Envelope * env
Envelope information.
Definition: email.h:89
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1422
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: sendlib.c:1707
void mutt_unprepare_envelope(struct Envelope *env)
Undo the encodings of mutt_prepare_envelope()
Definition: sendlib.c:2958
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:122
void mutt_encode_descriptions(struct Body *b, bool recurse)
rfc2047 encode the content-descriptions
Definition: send.c:1405
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:195
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
#define SEND_REPLY
Reply to sender.
Definition: send.h:87
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:63
int mutt_protect(struct Email *e, char *keylist)
Encrypt and/or sign a message.
Definition: crypt.c:167
WHERE char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: globals.h:162
#define FREE(x)
Definition: memory.h:40
WHERE char * C_Postponed
Config: Folder to store postponed messages.
Definition: globals.h:132
#define WithCrypto
Definition: ncrypt.h:156
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:131
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid, bool post, char *fcc, char **finalpath)
Write email to FCC mailbox.
Definition: sendlib.c:3168
int ci_send_message ( SendFlags  flags,
struct Email e_templ,
const char *  tempfile,
struct Context ctx,
struct EmailList *  el 
)

Send an email.

Parameters
flagsSend mode, see SendFlags
e_templTemplate to use for new message
tempfileFile specified by -i or -H
ctxCurrent mailbox
elList of Emails to send
Return values
0Message was successfully sent
-1Message was aborted or an error occurred
1Message was postponed

Definition at line 1830 of file send.c.

1832 {
1833  char buf[1024];
1834  char fcc[PATH_MAX] = { 0 }; /* where to copy this message */
1835  FILE *fp_tmp = NULL;
1836  struct Body *pbody = NULL;
1837  int i;
1838  bool free_clear_content = false;
1839 
1840  struct Body *clear_content = NULL;
1841  char *pgpkeylist = NULL;
1842  /* save current value of "pgp_sign_as" and "smime_default_key" */
1843  char *pgp_signas = NULL;
1844  char *smime_signas = NULL;
1845  const char *tag = NULL;
1846  char *err = NULL;
1847  char *ctype = NULL;
1848  char *finalpath = NULL;
1849  struct EmailNode *en = NULL;
1850  struct Email *e_cur = NULL;
1851 
1852  if (el)
1853  en = STAILQ_FIRST(el);
1854  if (en)
1855  e_cur = STAILQ_NEXT(en, entries) ? NULL : en->email;
1856 
1857  int rc = -1;
1858 
1859 #ifdef USE_NNTP
1860  if (flags & SEND_NEWS)
1861  OptNewsSend = true;
1862  else
1863  OptNewsSend = false;
1864 #endif
1865 
1866  if (!flags && !e_templ && (C_Recall != MUTT_NO) &&
1867  mutt_num_postponed(ctx ? ctx->mailbox : NULL, true))
1868  {
1869  /* If the user is composing a new message, check to see if there
1870  * are any postponed messages first. */
1871  enum QuadOption ans =
1872  query_quadoption(C_Recall, _("Recall postponed message?"));
1873  if (ans == MUTT_ABORT)
1874  return rc;
1875 
1876  if (ans == MUTT_YES)
1877  flags |= SEND_POSTPONED;
1878  }
1879 
1880  if (flags & SEND_POSTPONED)
1881  {
1883  pgp_signas = mutt_str_strdup(C_PgpSignAs);
1885  smime_signas = mutt_str_strdup(C_SmimeSignAs);
1886  }
1887 
1888  /* Delay expansion of aliases until absolutely necessary--shouldn't
1889  * be necessary unless we are prompting the user or about to execute a
1890  * send-hook. */
1891 
1892  if (!e_templ)
1893  {
1894  e_templ = mutt_email_new();
1895 
1896  if (flags == SEND_POSTPONED)
1897  {
1898  rc = mutt_get_postponed(ctx, e_templ, &e_cur, fcc, sizeof(fcc));
1899  if (rc < 0)
1900  {
1901  flags = SEND_POSTPONED;
1902  goto cleanup;
1903  }
1904  flags = rc;
1905 #ifdef USE_NNTP
1906  /* If postponed message is a news article, it have
1907  * a "Newsgroups:" header line, then set appropriate flag. */
1908  if (e_templ->env->newsgroups)
1909  {
1910  flags |= SEND_NEWS;
1911  OptNewsSend = true;
1912  }
1913  else
1914  {
1915  flags &= ~SEND_NEWS;
1916  OptNewsSend = false;
1917  }
1918 #endif
1919  }
1920 
1921  if (flags & (SEND_POSTPONED | SEND_RESEND))
1922  {
1923  fp_tmp = mutt_file_fopen(e_templ->content->filename, "a+");
1924  if (!fp_tmp)
1925  {
1926  mutt_perror(e_templ->content->filename);
1927  goto cleanup;
1928  }
1929  }
1930 
1931  if (!e_templ->env)
1932  e_templ->env = mutt_env_new();
1933  }
1934 
1935  /* Parse and use an eventual list-post header */
1936  if ((flags & SEND_LIST_REPLY) && e_cur && e_cur->env && e_cur->env->list_post)
1937  {
1938  /* Use any list-post header as a template */
1939  mutt_parse_mailto(e_templ->env, NULL, e_cur->env->list_post);
1940  /* We don't let them set the sender's address. */
1941  mutt_addrlist_clear(&e_templ->env->from);
1942  }
1943 
1944  if (!(flags & (SEND_KEY | SEND_POSTPONED | SEND_RESEND)))
1945  {
1946  /* When SEND_DRAFT_FILE is set, the caller has already
1947  * created the "parent" body structure. */
1948  if (!(flags & SEND_DRAFT_FILE))
1949  {
1950  pbody = mutt_body_new();
1951  pbody->next = e_templ->content; /* don't kill command-line attachments */
1952  e_templ->content = pbody;
1953 
1954  ctype = mutt_str_strdup(C_ContentType);
1955  if (!ctype)
1956  ctype = mutt_str_strdup("text/plain");
1957  mutt_parse_content_type(ctype, e_templ->content);
1958  FREE(&ctype);
1959  e_templ->content->unlink = true;
1960  e_templ->content->use_disp = false;
1961  e_templ->content->disposition = DISP_INLINE;
1962 
1963  if (!tempfile)
1964  {
1965  mutt_mktemp(buf, sizeof(buf));
1966  fp_tmp = mutt_file_fopen(buf, "w+");
1967  e_templ->content->filename = mutt_str_strdup(buf);
1968  }
1969  else
1970  {
1971  fp_tmp = mutt_file_fopen(tempfile, "a+");
1972  e_templ->content->filename = mutt_str_strdup(tempfile);
1973  }
1974  }
1975  else
1976  fp_tmp = mutt_file_fopen(e_templ->content->filename, "a+");
1977 
1978  if (!fp_tmp)
1979  {
1980  mutt_debug(LL_DEBUG1, "can't create tempfile %s (errno=%d)\n",
1981  e_templ->content->filename, errno);
1982  mutt_perror(e_templ->content->filename);
1983  goto cleanup;
1984  }
1985  }
1986 
1987  /* this is handled here so that the user can match ~f in send-hook */
1988  if (e_cur && C_ReverseName && !(flags & (SEND_POSTPONED | SEND_RESEND)))
1989  {
1990  /* We shouldn't have to worry about alias expansion here since we are
1991  * either replying to a real or postponed message, therefore no aliases
1992  * should exist since the user has not had the opportunity to add
1993  * addresses to the list. We just have to ensure the postponed messages
1994  * have their aliases expanded. */
1995 
1996  if (!TAILQ_EMPTY(&e_templ->env->from))
1997  {
1998  mutt_debug(LL_DEBUG5, "e_templ->env->from before set_reverse_name: %s\n",
1999  TAILQ_FIRST(&e_templ->env->from)->mailbox);
2000  mutt_addrlist_clear(&e_templ->env->from);
2001  }
2002  set_reverse_name(&e_templ->env->from, e_cur->env);
2003  }
2004  if (e_cur && C_ReplyWithXorig && !(flags & (SEND_POSTPONED | SEND_RESEND | SEND_FORWARD)))
2005  {
2006  /* We shouldn't have to worry about freeing 'e_templ->env->from' before
2007  * setting it here since this code will only execute when doing some
2008  * sort of reply. The pointer will only be set when using the -H command
2009  * line option.
2010  *
2011  * If there is already a from address recorded in 'e_templ->env->from',
2012  * then it theoretically comes from C_ReverseName handling, and we don't use
2013  * the 'X-Orig-To header'. */
2014  if (!TAILQ_EMPTY(&e_cur->env->x_original_to) && TAILQ_EMPTY(&e_templ->env->from))
2015  {
2016  mutt_addrlist_copy(&e_templ->env->from, &e_cur->env->x_original_to, false);
2017  mutt_debug(LL_DEBUG5, "e_templ->env->from extracted from X-Original-To: header: %s\n",
2018  TAILQ_FIRST(&e_templ->env->from)->mailbox);
2019  }
2020  }
2021 
2022  if (!(flags & (SEND_POSTPONED | SEND_RESEND)) &&
2023  !((flags & SEND_DRAFT_FILE) && C_ResumeDraftFiles))
2024  {
2025  if ((flags & (SEND_REPLY | SEND_FORWARD | SEND_TO_SENDER)) && ctx &&
2026  (envelope_defaults(e_templ->env, ctx->mailbox, el, flags) == -1))
2027  {
2028  goto cleanup;
2029  }
2030 
2031  if (C_Hdrs)
2032  process_user_recips(e_templ->env);
2033 
2034  /* Expand aliases and remove duplicates/crossrefs */
2035  mutt_expand_aliases_env(e_templ->env);
2036 
2037  if (flags & SEND_REPLY)
2038  mutt_fix_reply_recipients(e_templ->env);
2039 
2040 #ifdef USE_NNTP
2041  if ((flags & SEND_NEWS) && ctx && (ctx->mailbox->magic == MUTT_NNTP) &&
2042  !e_templ->env->newsgroups)
2043  {
2044  e_templ->env->newsgroups =
2045  mutt_str_strdup(((struct NntpMboxData *) ctx->mailbox->mdata)->group);
2046  }
2047 #endif
2048 
2049  if (!(flags & (SEND_MAILX | SEND_BATCH)) &&
2050  !(C_Autoedit && C_EditHeaders) && !((flags & SEND_REPLY) && C_FastReply))
2051  {
2052  if (edit_envelope(e_templ->env, flags) == -1)
2053  goto cleanup;
2054  }
2055 
2056  /* the from address must be set here regardless of whether or not
2057  * $use_from is set so that the '~P' (from you) operator in send-hook
2058  * patterns will work. if $use_from is unset, the from address is killed
2059  * after send-hooks are evaluated */
2060 
2061  const bool killfrom = TAILQ_EMPTY(&e_templ->env->from);
2062  if (killfrom)
2063  {
2065  }
2066 
2067  if ((flags & SEND_REPLY) && e_cur)
2068  {
2069  /* change setting based upon message we are replying to */
2070  mutt_message_hook(ctx ? ctx->mailbox : NULL, e_cur, MUTT_REPLY_HOOK);
2071 
2072  /* set the replied flag for the message we are generating so that the
2073  * user can use ~Q in a send-hook to know when reply-hook's are also
2074  * being used. */
2075  e_templ->replied = true;
2076  }
2077 
2078  /* change settings based upon recipients */
2079 
2080  mutt_message_hook(NULL, e_templ, MUTT_SEND_HOOK);
2081 
2082  /* Unset the replied flag from the message we are composing since it is
2083  * no longer required. This is done here because the FCC'd copy of
2084  * this message was erroneously get the 'R'eplied flag when stored in
2085  * a maildir-style mailbox. */
2086  e_templ->replied = false;
2087 
2088  if (!(flags & SEND_KEY))
2089  {
2090  if (C_TextFlowed && (e_templ->content->type == TYPE_TEXT) &&
2091  (mutt_str_strcasecmp(e_templ->content->subtype, "plain") == 0))
2092  {
2093  mutt_param_set(&e_templ->content->parameter, "format", "flowed");
2094  }
2095  }
2096 
2097  /* $use_from and/or $from might have changed in a send-hook */
2098  if (killfrom)
2099  {
2100  mutt_addrlist_clear(&e_templ->env->from);
2101  if (C_UseFrom && !(flags & (SEND_POSTPONED | SEND_RESEND)))
2103  }
2104 
2105  if (C_Hdrs)
2106  process_user_header(e_templ->env);
2107 
2108  if (flags & SEND_BATCH)
2109  mutt_file_copy_stream(stdin, fp_tmp);
2110 
2111  if (C_SigOnTop && !(flags & (SEND_MAILX | SEND_KEY | SEND_BATCH)) &&
2112  C_Editor && (mutt_str_strcmp(C_Editor, "builtin") != 0))
2113  {
2114  append_signature(fp_tmp);
2115  }
2116 
2117  /* include replies/forwarded messages, unless we are given a template */
2118  if (!tempfile && (ctx || !(flags & (SEND_REPLY | SEND_FORWARD))) &&
2119  (generate_body(fp_tmp, e_templ, flags, ctx ? ctx->mailbox : NULL, el) == -1))
2120  {
2121  goto cleanup;
2122  }
2123 
2124  if (!C_SigOnTop && !(flags & (SEND_MAILX | SEND_KEY | SEND_BATCH)) &&
2125  C_Editor && (mutt_str_strcmp(C_Editor, "builtin") != 0))
2126  {
2127  append_signature(fp_tmp);
2128  }
2129  }
2130 
2131  /* This hook is even called for postponed messages, and can, e.g., be
2132  * used for setting the editor, the sendmail path, or the
2133  * envelope sender. */
2134  mutt_message_hook(NULL, e_templ, MUTT_SEND2_HOOK);
2135 
2136  /* wait until now to set the real name portion of our return address so
2137  * that $realname can be set in a send-hook */
2138  {
2139  struct Address *from = TAILQ_FIRST(&e_templ->env->from);
2140  if (from && !from->personal && !(flags & (SEND_RESEND | SEND_POSTPONED)))
2142  }
2143 
2144  if (!(((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY)))
2145  mutt_file_fclose(&fp_tmp);
2146 
2147  if (flags & SEND_MAILX)
2148  {
2149  if (mutt_builtin_editor(e_templ->content->filename, e_templ, e_cur) == -1)
2150  goto cleanup;
2151  }
2152  else if (!(flags & SEND_BATCH))
2153  {
2154  struct stat st;
2155  time_t mtime = mutt_file_decrease_mtime(e_templ->content->filename, NULL);
2156 
2157  mutt_update_encoding(e_templ->content);
2158 
2159  /* Select whether or not the user's editor should be called now. We
2160  * don't want to do this when:
2161  * 1) we are sending a key/cert
2162  * 2) we are forwarding a message and the user doesn't want to edit it.
2163  * This is controlled by the quadoption $forward_edit. However, if
2164  * both $edit_headers and $autoedit are set, we want to ignore the
2165  * setting of $forward_edit because the user probably needs to add the
2166  * recipients. */
2167  if (!(flags & SEND_KEY) &&
2168  (((flags & SEND_FORWARD) == 0) || (C_EditHeaders && C_Autoedit) ||
2169  (query_quadoption(C_ForwardEdit, _("Edit forwarded message?")) == MUTT_YES)))
2170  {
2171  /* If the this isn't a text message, look for a mailcap edit command */
2172  if (mutt_needs_mailcap(e_templ->content))
2173  {
2174  if (!mutt_edit_attachment(e_templ->content))
2175  goto cleanup;
2176  }
2177  else if (!C_Editor || (mutt_str_strcmp("builtin", C_Editor) == 0))
2178  mutt_builtin_editor(e_templ->content->filename, e_templ, e_cur);
2179  else if (C_EditHeaders)
2180  {
2181  mutt_env_to_local(e_templ->env);
2182  mutt_edit_headers(C_Editor, e_templ->content->filename, e_templ, fcc, sizeof(fcc));
2183  mutt_env_to_intl(e_templ->env, NULL, NULL);
2184  }
2185  else
2186  {
2188  if (stat(e_templ->content->filename, &st) == 0)
2189  {
2190  if (mtime != st.st_mtime)
2191  fix_end_of_file(e_templ->content->filename);
2192  }
2193  else
2194  mutt_perror(e_templ->content->filename);
2195  }
2196 
2197  /* If using format=flowed, perform space stuffing. Avoid stuffing when
2198  * recalling a postponed message where the stuffing was already
2199  * performed. If it has already been performed, the format=flowed
2200  * parameter will be present. */
2201  if (C_TextFlowed && (e_templ->content->type == TYPE_TEXT) &&
2202  (mutt_str_strcasecmp("plain", e_templ->content->subtype) == 0))
2203  {
2204  char *p = mutt_param_get(&e_templ->content->parameter, "format");
2205  if (mutt_str_strcasecmp("flowed", p) != 0)
2206  rfc3676_space_stuff(e_templ);
2207  }
2208 
2209  mutt_message_hook(NULL, e_templ, MUTT_SEND2_HOOK);
2210  }
2211 
2212  if (!(flags & (SEND_POSTPONED | SEND_FORWARD | SEND_KEY | SEND_RESEND | SEND_DRAFT_FILE)))
2213  {
2214  if (stat(e_templ->content->filename, &st) == 0)
2215  {
2216  /* if the file was not modified, bail out now */
2217  if ((mtime == st.st_mtime) && !e_templ->content->next &&
2219  _("Abort unmodified message?")) == MUTT_YES))
2220  {
2221  mutt_message(_("Aborted unmodified message"));
2222  goto cleanup;
2223  }
2224  }
2225  else
2226  mutt_perror(e_templ->content->filename);
2227  }
2228  }
2229 
2230  /* Set the message security unless:
2231  * 1) crypto support is not enabled (WithCrypto==0)
2232  * 2) pgp: header field was present during message editing with $edit_headers (e_templ->security != 0)
2233  * 3) we are resending a message
2234  * 4) we are recalling a postponed message (don't override the user's saved settings)
2235  * 5) we are in mailx mode
2236  * 6) we are in batch mode
2237  *
2238  * This is done after allowing the user to edit the message so that security
2239  * settings can be configured with send2-hook and $edit_headers. */
2240  if ((WithCrypto != 0) && (e_templ->security == 0) &&
2241  !(flags & (SEND_BATCH | SEND_MAILX | SEND_POSTPONED | SEND_RESEND)))
2242  {
2243  if (C_CryptAutosign)
2244  e_templ->security |= SEC_SIGN;
2245  if (C_CryptAutoencrypt)
2246  e_templ->security |= SEC_ENCRYPT;
2247  if (C_CryptReplyencrypt && e_cur && (e_cur->security & SEC_ENCRYPT))
2248  e_templ->security |= SEC_ENCRYPT;
2249  if (C_CryptReplysign && e_cur && (e_cur->security & SEC_SIGN))
2250  e_templ->security |= SEC_SIGN;
2251  if (C_CryptReplysignencrypted && e_cur && (e_cur->security & SEC_ENCRYPT))
2252  e_templ->security |= SEC_SIGN;
2253  if (((WithCrypto & APPLICATION_PGP) != 0) &&
2255  {
2256  if (C_PgpAutoinline)
2257  e_templ->security |= SEC_INLINE;
2258  if (C_PgpReplyinline && e_cur && (e_cur->security & SEC_INLINE))
2259  e_templ->security |= SEC_INLINE;
2260  }
2261 
2262  if (e_templ->security || C_CryptOpportunisticEncrypt)
2263  {
2264  /* When replying / forwarding, use the original message's
2265  * crypto system. According to the documentation,
2266  * smime_is_default should be disregarded here.
2267  *
2268  * Problem: At least with forwarding, this doesn't really
2269  * make much sense. Should we have an option to completely
2270  * disable individual mechanisms at run-time? */
2271  if (e_cur)
2272  {
2273  if (((WithCrypto & APPLICATION_PGP) != 0) && C_CryptAutopgp &&
2274  (e_cur->security & APPLICATION_PGP))
2275  {
2276  e_templ->security |= APPLICATION_PGP;
2277  }
2278  else if (((WithCrypto & APPLICATION_SMIME) != 0) && C_CryptAutosmime &&
2279  (e_cur->security & APPLICATION_SMIME))
2280  {
2281  e_templ->security |= APPLICATION_SMIME;
2282  }
2283  }
2284 
2285  /* No crypto mechanism selected? Use availability + smime_is_default
2286  * for the decision. */
2287  if (!(e_templ->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2288  {
2289  if (((WithCrypto & APPLICATION_SMIME) != 0) && C_CryptAutosmime && C_SmimeIsDefault)
2290  {
2291  e_templ->security |= APPLICATION_SMIME;
2292  }
2293  else if (((WithCrypto & APPLICATION_PGP) != 0) && C_CryptAutopgp)
2294  {
2295  e_templ->security |= APPLICATION_PGP;
2296  }
2297  else if (((WithCrypto & APPLICATION_SMIME) != 0) && C_CryptAutosmime)
2298  {
2299  e_templ->security |= APPLICATION_SMIME;
2300  }
2301  }
2302  }
2303 
2304  /* opportunistic encrypt relies on SMIME or PGP already being selected */
2306  {
2307  /* If something has already enabled encryption, e.g. C_CryptAutoencrypt
2308  * or C_CryptReplyencrypt, then don't enable opportunistic encrypt for
2309  * the message. */
2310  if (!(e_templ->security & SEC_ENCRYPT))
2311  {
2312  e_templ->security |= SEC_OPPENCRYPT;
2313  crypt_opportunistic_encrypt(e_templ);
2314  }
2315  }
2316 
2317  /* No permissible mechanisms found. Don't sign or encrypt. */
2318  if (!(e_templ->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2319  e_templ->security = SEC_NO_FLAGS;
2320  }
2321 
2322  /* Deal with the corner case where the crypto module backend is not available.
2323  * This can happen if configured without pgp/smime and with gpgme, but
2324  * $crypt_use_gpgme is unset. */
2325  if (e_templ->security && !crypt_has_module_backend(e_templ->security))
2326  {
2327  mutt_error(_(
2328  "No crypto backend configured. Disabling message security setting."));
2329  e_templ->security = SEC_NO_FLAGS;
2330  }
2331 
2332  /* specify a default fcc. if we are in batchmode, only save a copy of
2333  * the message if the value of $copy is yes or ask-yes */
2334 
2335  if (!fcc[0] && !(flags & SEND_POSTPONED_FCC) && (!(flags & SEND_BATCH) || (C_Copy & 0x1)))
2336  {
2337  /* set the default FCC */
2338  const bool killfrom = TAILQ_EMPTY(&e_templ->env->from);
2339  if (killfrom)
2340  {
2342  }
2343  mutt_select_fcc(fcc, sizeof(fcc), e_templ);
2344  if (killfrom)
2345  {
2346  mutt_addrlist_clear(&e_templ->env->from);
2347  }
2348  }
2349 
2350  mutt_update_encoding(e_templ->content);
2351 
2352  if (!(flags & (SEND_MAILX | SEND_BATCH)))
2353  {
2354  main_loop:
2355 
2356  mutt_pretty_mailbox(fcc, sizeof(fcc));
2357  i = mutt_compose_menu(e_templ, fcc, sizeof(fcc), e_cur,
2359  if (i == -1)
2360  {
2361 /* abort */
2362 #ifdef USE_NNTP
2363  if (flags & SEND_NEWS)
2364  mutt_message(_("Article not posted"));
2365  else
2366 #endif
2367  mutt_message(_("Mail not sent"));
2368  goto cleanup;
2369  }
2370  else if (i == 1)
2371  {
2372  if (postpone_message(e_templ, e_cur, fcc, flags) != 0)
2373  goto main_loop;
2374  mutt_message(_("Message postponed"));
2375  rc = 1;
2376  goto cleanup;
2377  }
2378  }
2379 
2380 #ifdef USE_NNTP
2381  if (!(flags & SEND_NEWS))
2382 #endif
2383  if ((mutt_addrlist_count_recips(&e_templ->env->to) == 0) &&
2384  (mutt_addrlist_count_recips(&e_templ->env->cc) == 0) &&
2385  (mutt_addrlist_count_recips(&e_templ->env->bcc) == 0))
2386  {
2387  if (!(flags & SEND_BATCH))
2388  {
2389  mutt_error(_("No recipients specified"));
2390  goto main_loop;
2391  }
2392  else
2393  {
2394  puts(_("No recipients specified"));
2395  goto cleanup;
2396  }
2397  }
2398 
2399  if (mutt_env_to_intl(e_templ->env, &tag, &err))
2400  {
2401  mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
2402  FREE(&err);
2403  if (!(flags & SEND_BATCH))
2404  goto main_loop;
2405  else
2406  goto cleanup;
2407  }
2408 
2409  if (!e_templ->env->subject && !(flags & SEND_BATCH) &&
2410  (query_quadoption(C_AbortNosubject, _("No subject, abort sending?")) != MUTT_NO))
2411  {
2412  /* if the abort is automatic, print an error message */
2413  if (C_AbortNosubject == MUTT_YES)
2414  mutt_error(_("No subject specified"));
2415  goto main_loop;
2416  }
2417 #ifdef USE_NNTP
2418  if ((flags & SEND_NEWS) && !e_templ->env->subject)
2419  {
2420  mutt_error(_("No subject specified"));
2421  goto main_loop;
2422  }
2423 
2424  if ((flags & SEND_NEWS) && !e_templ->env->newsgroups)
2425  {
2426  mutt_error(_("No newsgroup specified"));
2427  goto main_loop;
2428  }
2429 #endif
2430 
2431  if (!(flags & SEND_BATCH) && (C_AbortNoattach != MUTT_NO) &&
2432  !e_templ->content->next && (e_templ->content->type == TYPE_TEXT) &&
2433  (mutt_str_strcasecmp(e_templ->content->subtype, "plain") == 0) &&
2434  search_attach_keyword(e_templ->content->filename) &&
2436  _("No attachments, cancel sending?")) != MUTT_NO))
2437  {
2438  /* if the abort is automatic, print an error message */
2439  if (C_AbortNoattach == MUTT_YES)
2440  {
2441  mutt_error(_("Message contains text matching "
2442  "\"$abort_noattach_regex\". Not sending."));
2443  }
2444  goto main_loop;
2445  }
2446 
2447  if (e_templ->content->next)
2448  e_templ->content = mutt_make_multipart(e_templ->content);
2449 
2450  /* Ok, we need to do it this way instead of handling all fcc stuff in
2451  * one place in order to avoid going to main_loop with encoded "env"
2452  * in case of error. Ugh. */
2453 
2454  mutt_encode_descriptions(e_templ->content, true);
2455 
2456  /* Make sure that clear_content and free_clear_content are
2457  * properly initialized -- we may visit this particular place in
2458  * the code multiple times, including after a failed call to
2459  * mutt_protect(). */
2460 
2461  clear_content = NULL;
2462  free_clear_content = false;
2463 
2464  if (WithCrypto)
2465  {
2466  if (e_templ->security & (SEC_ENCRYPT | SEC_SIGN))
2467  {
2468  /* save the decrypted attachments */
2469  clear_content = e_templ->content;
2470 
2471  if ((crypt_get_keys(e_templ, &pgpkeylist, 0) == -1) ||
2472  (mutt_protect(e_templ, pgpkeylist) == -1))
2473  {
2474  e_templ->content = mutt_remove_multipart(e_templ->content);
2475 
2476  FREE(&pgpkeylist);
2477 
2478  decode_descriptions(e_templ->content);
2479  goto main_loop;
2480  }
2481  mutt_encode_descriptions(e_templ->content, false);
2482  }
2483 
2484  /* at this point, e_templ->content is one of the following three things:
2485  * - multipart/signed. In this case, clear_content is a child
2486  * - multipart/encrypted. In this case, clear_content exists independently
2487  * - application/pgp. In this case, clear_content exists independently
2488  * - something else. In this case, it's the same as clear_content
2489  */
2490 
2491  /* This is ugly -- lack of "reporting back" from mutt_protect(). */
2492 
2493  if (clear_content && (e_templ->content != clear_content) &&
2494  (e_templ->content->parts != clear_content))
2495  free_clear_content = true;
2496  }
2497 
2498  if (!OptNoCurses && !(flags & SEND_MAILX))
2499  mutt_message(_("Sending message..."));
2500 
2501  mutt_prepare_envelope(e_templ->env, true);
2502 
2503  if (C_FccBeforeSend)
2504  save_fcc(e_templ, fcc, sizeof(fcc), clear_content, pgpkeylist, flags, &finalpath);
2505 
2506  i = send_message(e_templ);
2507  if (i < 0)
2508  {
2509  if (!(flags & SEND_BATCH))
2510  {
2511  if (!WithCrypto)
2512  ;
2513  else if ((e_templ->security & SEC_ENCRYPT) ||
2514  ((e_templ->security & SEC_SIGN) && (e_templ->content->type == TYPE_APPLICATION)))
2515  {
2516  mutt_body_free(&e_templ->content); /* destroy PGP data */
2517  e_templ->content = clear_content; /* restore clear text. */
2518  }
2519  else if ((e_templ->security & SEC_SIGN) && (e_templ->content->type == TYPE_MULTIPART))
2520  {
2521  mutt_body_free(&e_templ->content->parts->next); /* destroy sig */
2522  e_templ->content = mutt_remove_multipart(e_templ->content);
2523  }
2524 
2525  FREE(&pgpkeylist);
2526  mutt_env_free(&e_templ->content->mime_headers); /* protected headers */
2527  e_templ->content = mutt_remove_multipart(e_templ->content);
2528  decode_descriptions(e_templ->content);
2529  mutt_unprepare_envelope(e_templ->env);
2530  FREE(&finalpath);
2531  goto main_loop;
2532  }
2533  else
2534  {
2535  puts(_("Could not send the message"));
2536  goto cleanup;
2537  }
2538  }
2539 
2540  if (!C_FccBeforeSend)
2541  save_fcc(e_templ, fcc, sizeof(fcc), clear_content, pgpkeylist, flags, &finalpath);
2542 
2543  if (!OptNoCurses && !(flags & SEND_MAILX))
2544  {
2545  mutt_message((i != 0) ? _("Sending in background") :
2546  (flags & SEND_NEWS) ? _("Article posted") : /* USE_NNTP */
2547  _("Mail sent"));
2548 #ifdef USE_NOTMUCH
2549  if (C_NmRecord)
2550  nm_record_message(ctx ? ctx->mailbox : NULL, finalpath, e_cur);
2551 #endif
2552  mutt_sleep(0);
2553  }
2554 
2555  if (WithCrypto)
2556  FREE(&pgpkeylist);
2557 
2558  if ((WithCrypto != 0) && free_clear_content)
2559  mutt_body_free(&clear_content);
2560 
2561  /* set 'replied' flag only if the user didn't change/remove
2562  * In-Reply-To: and References: headers during edit */
2563  if (flags & SEND_REPLY)
2564  {
2565  if (!(flags & SEND_POSTPONED) && ctx && ctx->mailbox)
2566  {
2567  STAILQ_FOREACH(en, el, entries)
2568  {
2569  mutt_set_flag(ctx->mailbox, en->email, MUTT_REPLIED, is_reply(en->email, e_templ));
2570  }
2571  }
2572  }
2573 
2574  rc = 0;
2575 
2576 cleanup:
2577 
2578  if (flags & SEND_POSTPONED)
2579  {
2580  if (WithCrypto & APPLICATION_PGP)
2581  {
2582  FREE(&C_PgpSignAs);
2583  C_PgpSignAs = pgp_signas;
2584  }
2585  if (WithCrypto & APPLICATION_SMIME)
2586  {
2587  FREE(&C_SmimeSignAs);
2588  C_SmimeSignAs = smime_signas;
2589  }
2590  }
2591 
2592  mutt_file_fclose(&fp_tmp);
2593  if (!(flags & SEND_NO_FREE_HEADER))
2594  mutt_email_free(&e_templ);
2595 
2596  FREE(&finalpath);
2597  return rc;
2598 }
#define MUTT_SEND_HOOK
send-hook: when composing a new email
Definition: hook.h:46
void mutt_fix_reply_recipients(struct Envelope *env)
Remove duplicate recipients.
Definition: send.c:880
bool C_Hdrs
Config: Add custom headers to outgoing mail.
Definition: send.c:114
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1733
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:68
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:96
#define SEND_TO_SENDER
Compose new email to sender.
Definition: send.h:99
The envelope/body of an email.
Definition: email.h:37
#define TAILQ_FIRST(head)
Definition: queue.h:717
#define mutt_perror(...)
Definition: logging.h:85
static void fix_end_of_file(const char *data)
Ensure a file ends with a linefeed.
Definition: send.c:1439
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
unsigned char C_AbortNoattach
Config: Abort sending the email if attachments are missing.
Definition: send.c:89
static bool search_attach_keyword(char *filename)
Search an email for &#39;attachment&#39; keywords.
Definition: send.c:1526
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3321
#define mutt_message(...)
Definition: logging.h:83
int mutt_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: parse.c:1474
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:46
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1351
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:98
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:304
static int envelope_defaults(struct Envelope *env, struct Mailbox *m, struct EmailList *el, SendFlags flags)
Fill in some defaults for a new email.
Definition: send.c:1000
#define SEC_NO_FLAGS
No flags are set.
Definition: ncrypt.h:120
static void process_user_header(struct Envelope *env)
Process the user headers.
Definition: send.c:376
#define SEND_FORWARD
Forward email.
Definition: send.h:90
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
bool C_FccBeforeSend
Config: Save FCCs before sending the message.
Definition: send.c:106
struct Body * content
List of MIME parts.
Definition: email.h:90
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:256
static int save_fcc(struct Email *e, char *fcc, size_t fcc_len, struct Body *clear_content, char *pgpkeylist, SendFlags flags, char **finalpath)
Save an Email to a &#39;sent mail&#39; folder.
Definition: send.c:1568
#define _(a)
Definition: message.h:28
unsigned char C_AbortUnmodified
Config: Abort the sending if the message hasn&#39;t been edited.
Definition: send.c:92
WHERE bool C_PgpAutoinline
Config: Use old-style inline PGP messages (not recommended)
Definition: globals.h:275
struct Body * next
next attachment in the list
Definition: body.h:53
An email address.
Definition: address.h:34
WHERE unsigned char C_Copy
Config: Save outgoing emails to $record.
Definition: globals.h:181
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:45
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:128
bool C_CryptAutosign
Config: Automatically PGP sign all outgoing mail.
Definition: send.c:98
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:916
int mutt_env_to_intl(struct Envelope *env, const char **tag, char **err)
Convert an Envelope&#39;s Address fields to Punycode format.
Definition: envelope.c:260
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:91
bool C_CryptReplysign
Config: Sign replies to signed messages.
Definition: send.c:101
void mutt_select_fcc(char *path, size_t pathlen, struct Email *e)
Select the FCC path for an email.
Definition: hook.c:700
Messages that have been replied to.
Definition: mutt.h:99
The body of an email.
Definition: body.h:34
void mutt_prepare_envelope(struct Envelope *env, bool final)
Prepare an email header.
Definition: sendlib.c:2919
unsigned int disposition
content-disposition
Definition: body.h:67
int nm_record_message(struct Mailbox *m, char *path, struct Email *e)
Add a message to the Notmuch database.
WHERE bool C_SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:271
bool C_CryptAutosmime
Config: Allow automatic SMIME functions.
Definition: send.c:99
#define SEND_MAILX
Send email in Mailx compatibility mode.
Definition: send.h:93
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1505
WHERE bool C_EditHeaders
Config: Let the user edit the email headers whilst editing an email.
Definition: globals.h:208
struct Mailbox * mailbox
Definition: context.h:53
unsigned char C_Recall
Config: Recall postponed mesaages when asked to compose a message.
Definition: send.c:124
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
unsigned char C_AbortNosubject
Config: Abort creating the email if subject is missing.
Definition: send.c:91
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:117
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1446
static void process_user_recips(struct Envelope *env)
Process the user headers.
Definition: send.c:349
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
struct Envelope * env
Envelope information.
Definition: email.h:89
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1422
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
WHERE bool C_Autoedit
Config: Skip the initial compose menu and edit the email.
Definition: globals.h:199
#define SEND_LIST_REPLY
Reply to mailing list.
Definition: send.h:89
static bool is_reply(struct Email *reply, struct Email *orig)
Is one email a reply to another?
Definition: send.c:1508
void * mdata
Driver specific data.
Definition: mailbox.h:148
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:41
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: sendlib.c:1707
#define SEND_KEY
Mail a PGP public key.
Definition: send.h:94
char * subtype
content-type subtype
Definition: body.h:37
bool C_FastReply
Config: Don&#39;t prompt for the recipients and subject when replying/forwarding.
Definition: send.c:104
#define SEND_RESEND
Reply using the current email as a template.
Definition: send.h:95
void mutt_unprepare_envelope(struct Envelope *env)
Undo the encodings of mutt_prepare_envelope()
Definition: sendlib.c:2958
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:76
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:122
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1302
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:267
bool C_ReverseName
Config: Set the &#39;From&#39; from the address the email was sent to.
Definition: send.c:128
int mutt_compose_menu(struct Email *e, char *fcc, size_t fcclen, struct Email *e_cur, int flags)
Allow the user to edit the message envelope.
Definition: compose.c:885
#define PATH_MAX
Definition: mutt.h:50
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
void mutt_encode_descriptions(struct Body *b, bool recurse)
rfc2047 encode the content-descriptions
Definition: send.c:1405
Type: &#39;text/*&#39;.
Definition: mime.h:38
static int generate_body(FILE *fp_tmp, struct Email *e, SendFlags flags, struct Mailbox *m, struct EmailList *el)
Create a new email body.
Definition: send.c:1070
void mutt_param_set(struct ParameterList *p, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define SEND_NEWS
Reply to a news article.
Definition: send.h:101
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:615
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
static void set_reverse_name(struct AddressList *al, struct Envelope *env)
Try to set the &#39;from&#39; field from the recipients.
Definition: send.c:1253
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
bool C_PgpReplyinline
Config: Reply using old-style inline PGP messages (not recommended)
Definition: send.c:120
#define SEND_REPLY
Reply to sender.
Definition: send.h:87
NNTP-specific Mailbox data -.
Definition: nntp.h:139
bool C_SigOnTop
Config: Insert the signature before the quoted text.
Definition: send.c:132
void mutt_email_free(struct Email **e)
Free an Email.
Definition: email.c:41
#define SEND_NO_FREE_HEADER
Used by the -E flag.
Definition: send.h:97
void rfc3676_space_stuff(struct Email *e)
Perform required RFC3676 space stuffing.
Definition: rfc3676.c:398
unsigned char C_ForwardEdit
Config: Automatically start the editor when forwarding a message.
Definition: send.c:111
unsigned int type
content-type primary type
Definition: body.h:65
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:129
char * list_post
This stores a mailto URL, or nothing.
Definition: envelope.h:51
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
bool C_CryptReplyencrypt
Config: Encrypt replies to encrypted messages.
Definition: send.c:100
int mutt_addrlist_count_recips(const struct AddressList *al)
Count the number of Addresses with valid recipients.
Definition: address.c:831
bool crypt_has_module_backend(SecurityFlags type)
Is there a crypto backend for a given type?
Definition: cryptglue.c:153
char * personal
Real name of address.
Definition: address.h:36
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:85
WHERE bool C_TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: globals.h:255
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:434
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:222
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:985
WHERE bool C_ResumeDraftFiles
Config: Process draft files like postponed messages.
Definition: globals.h:245
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:57
char * subject
Email&#39;s subject.
Definition: envelope.h:52
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:56
char * newsgroups
List of newsgroups.
Definition: envelope.h:61
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:55
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:68
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:267
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
struct Email * email
Email in the list.
Definition: email.h:119
#define mutt_error(...)
Definition: logging.h:84
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:408
int mutt_builtin_editor(const char *path, struct Email *e_new, struct Email *e_cur)
Show the user the built-in editor.
Definition: edit.c:401
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
bool replied
Email has been replied to.
Definition: email.h:54
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:63
static int edit_envelope(struct Envelope *en, SendFlags flags)
Edit Envelope fields.
Definition: send.c:239
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: globals.h:104
void mutt_edit_headers(const char *editor, const char *body, struct Email *e, char *fcc, size_t fcclen)
Let the user edit the message header and body.
Definition: mutt_header.c:170
bool C_UseFrom
Config: Set the &#39;From&#39; header for outgoing mail.
Definition: send.c:133
time_t mutt_file_decrease_mtime(const char *fp, struct stat *st)
Decrease a file&#39;s modification time by 1 second.
Definition: file.c:960
#define MUTT_REPLY_HOOK
reply-hook: when replying to an email
Definition: hook.h:54
int mutt_protect(struct Email *e, char *keylist)
Encrypt and/or sign a message.
Definition: crypt.c:167
#define FREE(x)
Definition: memory.h:40
#define MUTT_COMPOSE_NOFREEHEADER
Definition: compose.h:36
static int postpone_message(struct Email *e_post, struct Email *e_cur, char *fcc, SendFlags flags)
Save an Email for another day.
Definition: send.c:1735
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
List of Emails.
Definition: email.h:117
WHERE char * C_Realname
Config: Real name of the user.
Definition: globals.h:136
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:579
#define TAILQ_EMPTY(head)
Definition: queue.h:715
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
Log at debug level 5.
Definition: logging.h:60
WHERE char * C_PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:163
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
WHERE char * C_SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:167
static void append_signature(FILE *fp)
Append a signature to an email.
Definition: send.c:139
char * C_ContentType
Config: Default "Content-Type" for newly composed messages.
Definition: send.c:95
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
struct AddressList x_original_to
Email&#39;s &#39;X-Orig-to&#39;.
Definition: envelope.h:50
#define STAILQ_FIRST(head)
Definition: queue.h:348
#define WithCrypto
Definition: ncrypt.h:156
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:308
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
static int send_message(struct Email *e)
Send an email.
Definition: send.c:1330
Type: &#39;application/*&#39;.
Definition: mime.h:33
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
#define SEND_BATCH
Send email in batch mode (without user interaction)
Definition: send.h:92
int mutt_get_postponed(struct Context *ctx, struct Email *hdr, struct Email **cur, char *fcc, size_t fcclen)
Recall a postponed message.
Definition: postpone.c:290
bool C_CryptReplysignencrypted
Config: Sign replies to encrypted messages.
Definition: send.c:102
bool C_NmRecord
Config: (notmuch) If the &#39;record&#39; mailbox (sent mail) should be indexed.
Definition: send.c:119
void mutt_addrlist_append(struct AddressList *al, struct Address *a)
Append an Address to an AddressList.
Definition: address.c:1371
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:131
bool C_CryptAutopgp
Config: Allow automatic PGP functions.
Definition: send.c:97
bool C_CryptAutoencrypt
Config: Automatically PGP encrypt all outgoing mail.
Definition: send.c:96
bool C_ReplyWithXorig
Config: Create &#39;From&#39; header from &#39;X-Original-To&#39; header.
Definition: send.c:127

Variable Documentation

unsigned char C_AbortNoattach

Config: Abort sending the email if attachments are missing.

Definition at line 89 of file send.c.

struct Regex* C_AbortNoattachRegex

Config: Regex to match text indicating attachments are expected.

Definition at line 90 of file send.c.

unsigned char C_AbortNosubject

Config: Abort creating the email if subject is missing.

Definition at line 91 of file send.c.

unsigned char C_AbortUnmodified

Config: Abort the sending if the message hasn't been edited.

Definition at line 92 of file send.c.

bool C_AskFollowUp

Config: (nntp) Ask the user for follow-up groups before editing.

Definition at line 93 of file send.c.

bool C_AskXCommentTo

Config: (nntp) Ask the user for the 'X-Comment-To' field before editing.

Definition at line 94 of file send.c.

char* C_ContentType

Config: Default "Content-Type" for newly composed messages.

Definition at line 95 of file send.c.

bool C_CryptAutoencrypt

Config: Automatically PGP encrypt all outgoing mail.

Definition at line 96 of file send.c.

bool C_CryptAutopgp

Config: Allow automatic PGP functions.

Definition at line 97 of file send.c.

bool C_CryptAutosign

Config: Automatically PGP sign all outgoing mail.

Definition at line 98 of file send.c.

bool C_CryptAutosmime

Config: Allow automatic SMIME functions.

Definition at line 99 of file send.c.

bool C_CryptReplyencrypt

Config: Encrypt replies to encrypted messages.

Definition at line 100 of file send.c.

bool C_CryptReplysign

Config: Sign replies to signed messages.

Definition at line 101 of file send.c.

bool C_CryptReplysignencrypted

Config: Sign replies to encrypted messages.

Definition at line 102 of file send.c.

char* C_EmptySubject

Config: Subject to use when replying to an email with none.

Definition at line 103 of file send.c.

bool C_FastReply

Config: Don't prompt for the recipients and subject when replying/forwarding.

Definition at line 104 of file send.c.

unsigned char C_FccAttach

Config: Save send message with all their attachments.

Definition at line 105 of file send.c.

bool C_FccBeforeSend

Config: Save FCCs before sending the message.

Definition at line 106 of file send.c.

bool C_FccClear

Config: Save sent messages unencrypted and unsigned.

Definition at line 107 of file send.c.

bool C_FollowupTo

Config: Add the 'Mail-Followup-To' header is generated when sending mail.

Definition at line 108 of file send.c.

char* C_ForwardAttributionIntro

Config: Prefix message for forwarded messages.

Definition at line 109 of file send.c.

char* C_ForwardAttributionTrailer

Config: Suffix message for forwarded messages.

Definition at line 110 of file send.c.

unsigned char C_ForwardEdit

Config: Automatically start the editor when forwarding a message.

Definition at line 111 of file send.c.

char* C_ForwardFormat

Config: printf-like format string to control the subject when forwarding a message.

Definition at line 112 of file send.c.

bool C_ForwardReferences

Config: Set the 'In-Reply-To' and 'References' headers when forwarding a message.

Definition at line 113 of file send.c.

bool C_Hdrs

Config: Add custom headers to outgoing mail.

Definition at line 114 of file send.c.

unsigned char C_HonorFollowupTo

Config: Honour the 'Mail-Followup-To' header when group replying.

Definition at line 115 of file send.c.

bool C_IgnoreListReplyTo

Config: Ignore the 'Reply-To' header when using <reply> on a mailing list.

Definition at line 116 of file send.c.

unsigned char C_Include

Config: Include a copy of the email that's being replied to.

Definition at line 117 of file send.c.

bool C_Metoo

Config: Remove the user's address from the list of recipients.

Definition at line 118 of file send.c.

bool C_NmRecord

Config: (notmuch) If the 'record' mailbox (sent mail) should be indexed.

Definition at line 119 of file send.c.

bool C_PgpReplyinline

Config: Reply using old-style inline PGP messages (not recommended)

Definition at line 120 of file send.c.

char* C_PostIndentString

Config: Suffix message to add after reply text.

Definition at line 121 of file send.c.

bool C_PostponeEncrypt

Config: Self-encrypt postponed messages.

Definition at line 122 of file send.c.

char* C_PostponeEncryptAs

Config: Fallback encryption key for postponed messages.

Definition at line 123 of file send.c.

unsigned char C_Recall

Config: Recall postponed mesaages when asked to compose a message.

Definition at line 124 of file send.c.

bool C_ReplySelf

Config: Really reply to yourself, when replying to your own email.

Definition at line 125 of file send.c.

unsigned char C_ReplyTo

Config: Address to use as a 'Reply-To' header.

Definition at line 126 of file send.c.

bool C_ReplyWithXorig

Config: Create 'From' header from 'X-Original-To' header.

Definition at line 127 of file send.c.

bool C_ReverseName

Config: Set the 'From' from the address the email was sent to.

Definition at line 128 of file send.c.

bool C_ReverseRealname

Config: Set the 'From' from the full 'To' address the email was sent to.

Definition at line 129 of file send.c.

bool C_SigDashes

Config: Insert '– ' before the signature.

Definition at line 130 of file send.c.

char* C_Signature

Config: File containing a signature to append to all mail.

Definition at line 131 of file send.c.

bool C_SigOnTop

Config: Insert the signature before the quoted text.

Definition at line 132 of file send.c.

bool C_UseFrom

Config: Set the 'From' header for outgoing mail.

Definition at line 133 of file send.c.