NeoMutt  2018-07-16 +952-a2da0a
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 "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 "curs_lib.h"
#include "edit.h"
#include "filter.h"
#include "globals.h"
#include "hdrline.h"
#include "hook.h"
#include "mailbox.h"
#include "mutt_attach.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 "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"
+ Include dependency graph for send.c:

Go to the source code of this file.

Functions

static void append_signature (FILE *f)
 Append a signature to an email. More...
 
struct Addressmutt_remove_xrefs (struct Address *a, struct Address *b)
 Remove cross-references. More...
 
static struct Addressremove_user (struct Address *a, bool leave_only)
 Remove any address which matches the current user. More...
 
static struct Addressfind_mailing_lists (struct Address *t, struct Address *c)
 Search Address lists for mailing lists. More...
 
static int edit_address (struct Address **a, const char *field)
 Edit an email address. More...
 
static int edit_envelope (struct Envelope *en, int 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 Context *ctx, struct Email *cur, FILE *fp)
 Add the "start of forwarded message" text. More...
 
void mutt_forward_trailer (struct Context *ctx, struct Email *cur, FILE *fp)
 Add a "end of forwarded message" text. More...
 
static int include_forward (struct Context *ctx, struct Email *cur, FILE *out)
 Write out a forwarded message. More...
 
void mutt_make_attribution (struct Context *ctx, struct Email *cur, FILE *out)
 Add "on DATE, PERSON wrote" header. More...
 
void mutt_make_post_indent (struct Context *ctx, struct Email *cur, FILE *out)
 Add suffix to replied email text. More...
 
static int include_reply (struct Context *ctx, struct Email *cur, FILE *out)
 Generate the reply text for an email. More...
 
static int default_to (struct Address **to, struct Envelope *env, int flags, int hmfupto)
 Generate default email addresses. More...
 
int mutt_fetch_recips (struct Envelope *out, struct Envelope *in, int 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 Context *ctx, struct Email *cur)
 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 Envelope *curenv, struct Envelope *env, struct Context *ctx)
 Generate reference headers for an email. More...
 
static int envelope_defaults (struct Envelope *env, struct Context *ctx, struct Email *cur, int flags)
 Fill in some defaults for a new email. More...
 
static int generate_body (FILE *tempfp, struct Email *msg, int flags, struct Context *ctx, struct Email *cur)
 Create a new email body. More...
 
void mutt_set_followup_to (struct Envelope *env)
 Set followup-to field. More...
 
static struct Addressset_reverse_name (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 *msg)
 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 *cur)
 Resend an email. More...
 
static int 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...
 
int ci_send_message (int flags, struct Email *msg, char *tempfile, struct Context *ctx, struct Email *cur)
 Send an email. More...
 

Variables

unsigned char AbortNoattach
 Config: Abort sending the email if attachments are missing. More...
 
struct RegexAbortNoattachRegex
 Config: Regex to match text indicating attachments are expected. More...
 
unsigned char AbortNosubject
 Config: Abort creating the email if subject is missing. More...
 
unsigned char AbortUnmodified
 Config: Abort the sending if the message hasn't been edited. More...
 
bool AskFollowUp
 Config: (nntp) Ask the user for follow-up groups before editing. More...
 
bool AskXCommentTo
 Config: (nntp) Ask the user for the 'X-Comment-To' field before editing. More...
 
char * ContentType
 Config: Default "Content-Type" for newly composed messages. More...
 
bool CryptAutoencrypt
 Config: Automatically PGP encrypt all outgoing mail. More...
 
bool CryptAutopgp
 Config: Allow automatic PGP functions. More...
 
bool CryptAutosign
 Config: Automatically PGP sign all outgoing mail. More...
 
bool CryptAutosmime
 Config: Allow automatic SMIME functions. More...
 
bool CryptReplyencrypt
 Config: Encrypt replies to encrypted messages. More...
 
bool CryptReplysign
 Config: Sign replies to signed messages. More...
 
bool CryptReplysignencrypted
 Config: Sign replies to encrypted messages. More...
 
char * EmptySubject
 Config: Subject to use when replying to an email with none. More...
 
bool FastReply
 Config: Don't prompt for the recipients and subject when replying/forwarding. More...
 
unsigned char FccAttach
 Config: Save send message with all their attachments. More...
 
bool FccClear
 Config: Save sent messages unencrypted and unsigned. More...
 
bool FollowupTo
 Config: Add the 'Mail-Followup-To' header is generated when sending mail. More...
 
char * ForwardAttributionIntro
 Config: Prefix message for forwarded messages. More...
 
char * ForwardAttributionTrailer
 Config: Suffix message for forwarded messages. More...
 
unsigned char ForwardEdit
 Config: Automatically start the editor when forwarding a message. More...
 
char * ForwardFormat
 Config: printf-like format string to control the subject when forwarding a message. More...
 
bool ForwardReferences
 Config: Set the 'In-Reply-To' and 'References' headers when forwarding a message. More...
 
bool Hdrs
 Config: Add custom headers to outgoing mail. More...
 
unsigned char HonorFollowupTo
 Config: Honour the 'Mail-Followup-To' header when group replying. More...
 
bool IgnoreListReplyTo
 Config: Ignore the 'Reply-To' header when using <reply> on a mailing list. More...
 
unsigned char Include
 Config: Include a copy of the email that's being replied to. More...
 
bool Metoo
 Config: Remove the user's address from the list of recipients. More...
 
bool NmRecord
 Config: (notmuch) If the 'record' mailbox (sent mail) should be indexed. More...
 
bool PgpReplyinline
 Config: Reply using old-style inline PGP messages (not recommended) More...
 
char * PostIndentString
 Config: Suffix message to add after reply text. More...
 
bool PostponeEncrypt
 Config: Self-encrypt postponed messages. More...
 
char * PostponeEncryptAs
 Config: Fallback encryption key for postponed messages. More...
 
unsigned char Recall
 Config: Recall postponed mesaages when asked to compose a message. More...
 
bool ReplySelf
 Config: Really reply to yourself, when replying to your own email. More...
 
unsigned char ReplyTo
 Config: Address to use as a 'Reply-To' header. More...
 
bool ReplyWithXorig
 Config: Create 'From' header from 'X-Original-To' header. More...
 
bool ReverseName
 Config: Set the 'From' from the address the email was sent to. More...
 
bool ReverseRealname
 Config: Set the 'From' from the full 'To' address the email was sent to. More...
 
bool SigDashes
 Config: Insert '– ' before the signature. More...
 
char * Signature
 Config: File containing a signature to append to all mail. More...
 
bool SigOnTop
 Config: Insert the signature before the quoted text. More...
 
bool UseFrom
 Config: Set the 'From' header for outgoing mail. More...
 

Detailed Description

Prepare and send an email.

Authors
  • Michael R. Elkins

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 *  f)
static

Append a signature to an email.

Parameters
fFile to write to

Definition at line 133 of file send.c.

134 {
135  FILE *tmpfp = NULL;
136  pid_t thepid;
137 
138  if (Signature && (tmpfp = mutt_open_read(Signature, &thepid)))
139  {
140  if (SigDashes)
141  fputs("\n-- \n", f);
142  mutt_file_copy_stream(tmpfp, f);
143  mutt_file_fclose(&tmpfp);
144  if (thepid != -1)
145  mutt_wait_filter(thepid);
146  }
147 }
bool SigDashes
Config: Insert &#39;– &#39; before the signature.
Definition: send.c:124
char * Signature
Config: File containing a signature to append to all mail.
Definition: send.c:125
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
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:1338

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* mutt_remove_xrefs ( struct Address a,
struct Address b 
)

Remove cross-references.

Parameters
aReference list of Addresses
bAddress list to trim
Return values
ptrUpdated Address list

Remove addresses from "b" which are contained in "a"

Definition at line 157 of file send.c.

158 {
159  struct Address *p = NULL, *prev = NULL;
160 
161  struct Address *top = b;
162  while (b)
163  {
164  for (p = a; p; p = p->next)
165  {
166  if (mutt_addr_cmp(p, b))
167  break;
168  }
169  if (p)
170  {
171  if (prev)
172  {
173  prev->next = b->next;
174  b->next = NULL;
175  mutt_addr_free(&b);
176  b = prev;
177  }
178  else
179  {
180  top = top->next;
181  b->next = NULL;
182  mutt_addr_free(&b);
183  b = top;
184  }
185  }
186  else
187  {
188  prev = b;
189  b = b->next;
190  }
191  }
192  return top;
193 }
An email address.
Definition: address.h:32
bool mutt_addr_cmp(struct Address *a, struct Address *b)
Compare two e-mail addresses.
Definition: address.c:883
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static struct Address* remove_user ( struct Address a,
bool  leave_only 
)
static

Remove any address which matches the current user.

Parameters
aList of addresses
leave_onlyIf set, don't remove the user's address if it it the only one in the list
Return values
ptrHead of the remaining Address List

Definition at line 202 of file send.c.

203 {
204  struct Address *top = NULL, *last = NULL;
205 
206  while (a)
207  {
208  if (!mutt_addr_is_user(a))
209  {
210  if (top)
211  {
212  last->next = a;
213  last = last->next;
214  }
215  else
216  {
217  last = a;
218  top = a;
219  }
220  a = a->next;
221  last->next = NULL;
222  }
223  else
224  {
225  struct Address *tmp = a;
226 
227  a = a->next;
228  if (!leave_only || a || last)
229  {
230  tmp->next = NULL;
231  mutt_addr_free(&tmp);
232  }
233  else
234  {
235  last = tmp;
236  top = tmp;
237  }
238  }
239  }
240  return top;
241 }
An email address.
Definition: address.h:32
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:676
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static struct Address* find_mailing_lists ( struct Address t,
struct Address c 
)
static

Search Address lists for mailing lists.

Parameters
t'To' Address list
c'Cc' Address list
Return values
ptrNewly allocated Address list of all mailing list matches

Definition at line 249 of file send.c.

250 {
251  struct Address *top = NULL, *ptr = NULL;
252 
253  for (; t || c; t = c, c = NULL)
254  {
255  for (; t; t = t->next)
256  {
257  if (mutt_is_mail_list(t) && !t->group)
258  {
259  if (top)
260  {
261  ptr->next = mutt_addr_copy(t);
262  ptr = ptr->next;
263  }
264  else
265  {
266  top = mutt_addr_copy(t);
267  ptr = top;
268  }
269  }
270  }
271  }
272  return top;
273 }
An email address.
Definition: address.h:32
bool mutt_is_mail_list(struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:98
struct Address * mutt_addr_copy(struct Address *addr)
Copy the real address.
Definition: address.c:712
bool group
group mailbox?
Definition: address.h:36
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int edit_address ( struct Address **  a,
const char *  field 
)
static

Edit an email address.

Parameters
aAddress to edit
fieldPrompt for user
Return values
0Success
-1Failure

Definition at line 282 of file send.c.

283 {
284  char buf[HUGE_STRING];
285  char *err = NULL;
286  int idna_ok = 0;
287 
288  do
289  {
290  buf[0] = 0;
292  mutt_addr_write(buf, sizeof(buf), *a, false);
293  if (mutt_get_field(field, buf, sizeof(buf), MUTT_ALIAS) != 0)
294  return -1;
295  mutt_addr_free(a);
297  idna_ok = mutt_addrlist_to_intl(*a, &err);
298  if (idna_ok != 0)
299  {
300  mutt_error(_("Bad IDN: '%s'"), err);
301  FREE(&err);
302  }
303  } while (idna_ok != 0);
304  return 0;
305 }
struct Address * mutt_addr_parse_list2(struct Address *p, const char *s)
Parse a list of email addresses.
Definition: address.c:630
#define MUTT_ALIAS
do alias "completion" by calling up the alias-menu
Definition: mutt.h:58
#define _(a)
Definition: message.h:28
int mutt_addrlist_to_intl(struct Address *a, char **err)
Convert an Address list to Punycode.
Definition: address.c:1208
size_t mutt_addr_write(char *buf, size_t buflen, struct Address *addr, bool display)
Write an Address to a buffer.
Definition: address.c:1146
#define HUGE_STRING
Definition: string2.h:37
int mutt_addrlist_to_local(struct Address *a)
Convert an Address list from Punycode.
Definition: address.c:1249
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
struct Address * mutt_expand_aliases(struct Address *a)
Expand aliases in a List of Addresses.
Definition: alias.c:296
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int edit_envelope ( struct Envelope en,
int  flags 
)
static

Edit Envelope fields.

Parameters
enEnvelope to edit
flagsFlags, e.g. SEND_LIST_REPLY
Return values
0Success
-1Failure

Definition at line 314 of file send.c.

315 {
316  char buf[HUGE_STRING];
317 
318 #ifdef USE_NNTP
319  if (OptNewsSend)
320  {
321  if (en->newsgroups)
322  mutt_str_strfcpy(buf, en->newsgroups, sizeof(buf));
323  else
324  buf[0] = 0;
325  if (mutt_get_field("Newsgroups: ", buf, sizeof(buf), 0) != 0)
326  return -1;
327  FREE(&en->newsgroups);
328  en->newsgroups = mutt_str_strdup(buf);
329 
330  if (en->followup_to)
331  mutt_str_strfcpy(buf, en->followup_to, sizeof(buf));
332  else
333  buf[0] = 0;
334  if (AskFollowUp && mutt_get_field("Followup-To: ", buf, sizeof(buf), 0) != 0)
335  {
336  return -1;
337  }
338  FREE(&en->followup_to);
339  en->followup_to = mutt_str_strdup(buf);
340 
341  if (en->x_comment_to)
342  mutt_str_strfcpy(buf, en->x_comment_to, sizeof(buf));
343  else
344  buf[0] = 0;
345  if (XCommentTo && AskXCommentTo &&
346  mutt_get_field("X-Comment-To: ", buf, sizeof(buf), 0) != 0)
347  {
348  return -1;
349  }
350  FREE(&en->x_comment_to);
351  en->x_comment_to = mutt_str_strdup(buf);
352  }
353  else
354 #endif
355  {
356  if (edit_address(&en->to, _("To: ")) == -1 || !en->to)
357  return -1;
358  if (Askcc && edit_address(&en->cc, _("Cc: ")) == -1)
359  return -1;
360  if (Askbcc && edit_address(&en->bcc, _("Bcc: ")) == -1)
361  return -1;
363  (edit_address(&en->from, "From: ") == -1))
364  {
365  return -1;
366  }
367  }
368 
369  if (en->subject)
370  {
371  if (FastReply)
372  return 0;
373  else
374  mutt_str_strfcpy(buf, en->subject, sizeof(buf));
375  }
376  else
377  {
378  const char *p = NULL;
379 
380  buf[0] = 0;
381  struct ListNode *uh = NULL;
382  STAILQ_FOREACH(uh, &UserHeader, entries)
383  {
384  size_t plen = mutt_str_startswith(uh->data, "subject:", CASE_IGNORE);
385  if (plen)
386  {
387  p = mutt_str_skip_email_wsp(uh->data + plen);
388  mutt_str_strfcpy(buf, p, sizeof(buf));
389  }
390  }
391  }
392 
393  if (mutt_get_field(_("Subject: "), buf, sizeof(buf), 0) != 0 ||
394  (!buf[0] && query_quadoption(AbortNosubject, _("No subject, abort?")) != MUTT_NO))
395  {
396  mutt_message(_("No subject, aborting"));
397  return -1;
398  }
399  mutt_str_replace(&en->subject, buf);
400 
401  return 0;
402 }
#define mutt_message(...)
Definition: logging.h:87
WHERE bool XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:282
struct Address * to
Definition: envelope.h:36
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
#define _(a)
Definition: message.h:28
bool AskFollowUp
Config: (nntp) Ask the user for follow-up groups before editing.
Definition: send.c:88
WHERE bool Askcc
Config: Ask the user for the carbon-copy recipients.
Definition: globals.h:202
#define SEND_LIST_REPLY
Definition: send.h:84
struct Address * from
Definition: envelope.h:35
#define HUGE_STRING
Definition: string2.h:37
bool ReplyWithXorig
Config: Create &#39;From&#39; header from &#39;X-Original-To&#39; header.
Definition: send.c:121
char * x_comment_to
Definition: envelope.h:56
static int edit_address(struct Address **a, const char *field)
Edit an email address.
Definition: send.c:282
struct Address * bcc
Definition: envelope.h:38
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
int query_quadoption(int opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3227
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:742
unsigned char AbortNosubject
Config: Abort creating the email if subject is missing.
Definition: send.c:86
bool AskXCommentTo
Config: (nntp) Ask the user for the &#39;X-Comment-To&#39; field before editing.
Definition: send.c:89
Ignore case when comparing strings.
Definition: string2.h:70
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:768
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
#define SEND_REPLY
Definition: send.h:82
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
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:166
#define SEND_GROUP_REPLY
Definition: send.h:83
char * data
Definition: list.h:35
char * subject
Definition: envelope.h:44
char * newsgroups
Definition: envelope.h:53
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
char * followup_to
Definition: envelope.h:55
#define FREE(x)
Definition: memory.h:46
WHERE bool Askbcc
Config: Ask the user for the blind-carbon-copy recipients.
Definition: globals.h:201
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
A List node for strings.
Definition: list.h:33
bool FastReply
Config: Don&#39;t prompt for the recipients and subject when replying/forwarding.
Definition: send.c:99
struct Address * cc
Definition: envelope.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 412 of file send.c.

413 {
414  SKIPWS(s);
415  return mutt_str_strdup(s);
416 }
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define SKIPWS(c)
Definition: string2.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void process_user_recips ( struct Envelope env)
static

Process the user headers.

Parameters
envEnvelope to populate

Definition at line 423 of file send.c.

424 {
425  struct ListNode *uh = NULL;
426  STAILQ_FOREACH(uh, &UserHeader, entries)
427  {
428  size_t plen;
429  if ((plen = mutt_str_startswith(uh->data, "to:", CASE_IGNORE)))
430  env->to = mutt_addr_parse_list(env->to, uh->data + plen);
431  else if ((plen = mutt_str_startswith(uh->data, "cc:", CASE_IGNORE)))
432  env->cc = mutt_addr_parse_list(env->cc, uh->data + plen);
433  else if ((plen = mutt_str_startswith(uh->data, "bcc:", CASE_IGNORE)))
434  env->bcc = mutt_addr_parse_list(env->bcc, uh->data + plen);
435 #ifdef USE_NNTP
436  else if ((plen = mutt_str_startswith(uh->data, "newsgroups:", CASE_IGNORE)))
437  env->newsgroups = nntp_get_header(uh->data + plen);
438  else if ((plen = mutt_str_startswith(uh->data, "followup-to:", CASE_IGNORE)))
439  env->followup_to = nntp_get_header(uh->data + plen);
440  else if ((plen = mutt_str_startswith(uh->data, "x-comment-to:", CASE_IGNORE)))
441  env->x_comment_to = nntp_get_header(uh->data + plen);
442 #endif
443  }
444 }
struct Address * to
Definition: envelope.h:36
static char * nntp_get_header(const char *s)
Get the trimmed header.
Definition: send.c:412
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
char * x_comment_to
Definition: envelope.h:56
struct Address * bcc
Definition: envelope.h:38
struct Address * mutt_addr_parse_list(struct Address *top, const char *s)
Parse a list of email addresses.
Definition: address.c:465
Ignore case when comparing strings.
Definition: string2.h:70
#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:166
char * data
Definition: list.h:35
char * newsgroups
Definition: envelope.h:53
char * followup_to
Definition: envelope.h:55
A List node for strings.
Definition: list.h:33
struct Address * cc
Definition: envelope.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void process_user_header ( struct Envelope env)
static

Process the user headers.

Parameters
envEnvelope to populate

Definition at line 450 of file send.c.

451 {
452  struct ListNode *uh = NULL;
453  STAILQ_FOREACH(uh, &UserHeader, entries)
454  {
455  size_t plen;
456  if ((plen = mutt_str_startswith(uh->data, "from:", CASE_IGNORE)))
457  {
458  /* User has specified a default From: address. Remove default address */
459  mutt_addr_free(&env->from);
460  env->from = mutt_addr_parse_list(env->from, uh->data + plen);
461  }
462  else if ((plen = mutt_str_startswith(uh->data, "reply-to:", CASE_IGNORE)))
463  {
464  mutt_addr_free(&env->reply_to);
465  env->reply_to = mutt_addr_parse_list(env->reply_to, uh->data + plen);
466  }
467  else if ((plen = mutt_str_startswith(uh->data, "message-id:", CASE_IGNORE)))
468  {
469  char *tmp = mutt_extract_message_id(uh->data + plen, NULL);
470  if (mutt_addr_valid_msgid(tmp))
471  {
472  FREE(&env->message_id);
473  env->message_id = tmp;
474  }
475  else
476  FREE(&tmp);
477  }
478  else if (!mutt_str_startswith(uh->data, "to:", CASE_IGNORE) &&
479  !mutt_str_startswith(uh->data, "cc:", CASE_IGNORE) &&
480  !mutt_str_startswith(uh->data, "bcc:", CASE_IGNORE) &&
481 #ifdef USE_NNTP
482  !mutt_str_startswith(uh->data, "newsgroups:", CASE_IGNORE) &&
483  !mutt_str_startswith(uh->data, "followup-to:", CASE_IGNORE) &&
484  !mutt_str_startswith(uh->data, "x-comment-to:", CASE_IGNORE) &&
485 #endif
486  !mutt_str_startswith(uh->data, "supersedes:", CASE_IGNORE) &&
487  !mutt_str_startswith(uh->data, "subject:", CASE_IGNORE) &&
488  !mutt_str_startswith(uh->data, "return-path:", CASE_IGNORE))
489  {
491  }
492  }
493 }
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
struct ListHead userhdrs
user defined headers
Definition: envelope.h:61
struct Address * reply_to
Definition: envelope.h:40
char * message_id
Definition: envelope.h:47
struct Address * from
Definition: envelope.h:35
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:58
struct Address * mutt_addr_parse_list(struct Address *top, const char *s)
Parse a list of email addresses.
Definition: address.c:465
Ignore case when comparing strings.
Definition: string2.h:70
#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:166
char * data
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
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:295
bool mutt_addr_valid_msgid(const char *msgid)
Is this a valid Message ID?
Definition: address.c:790

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_forward_intro ( struct Context ctx,
struct Email cur,
FILE *  fp 
)

Add the "start of forwarded message" text.

Parameters
ctxMailbox
curEmail
fpFile to write to

Definition at line 501 of file send.c.

502 {
503  if (!ForwardAttributionIntro || !fp)
504  return;
505 
506  char buf[LONG_STRING];
507  setlocale(LC_TIME, NONULL(AttributionLocale));
508  mutt_make_string(buf, sizeof(buf), ForwardAttributionIntro, ctx, cur);
509  setlocale(LC_TIME, "");
510  fputs(buf, fp);
511  fputs("\n\n", fp);
512 }
#define NONULL(x)
Definition: string2.h:39
#define LONG_STRING
Definition: string2.h:36
#define mutt_make_string(A, B, C, D, E)
Definition: hdrline.h:55
char * ForwardAttributionIntro
Config: Prefix message for forwarded messages.
Definition: send.c:103
WHERE char * AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:104

+ Here is the caller graph for this function:

void mutt_forward_trailer ( struct Context ctx,
struct Email cur,
FILE *  fp 
)

Add a "end of forwarded message" text.

Parameters
ctxMailbox
curEmail
fpFile to write to

Definition at line 520 of file send.c.

521 {
522  if (!ForwardAttributionTrailer || !fp)
523  return;
524 
525  char buf[LONG_STRING];
526  setlocale(LC_TIME, NONULL(AttributionLocale));
527  mutt_make_string(buf, sizeof(buf), ForwardAttributionTrailer, ctx, cur);
528  setlocale(LC_TIME, "");
529  fputc('\n', fp);
530  fputs(buf, fp);
531  fputc('\n', fp);
532 }
#define NONULL(x)
Definition: string2.h:39
#define LONG_STRING
Definition: string2.h:36
#define mutt_make_string(A, B, C, D, E)
Definition: hdrline.h:55
char * ForwardAttributionTrailer
Config: Suffix message for forwarded messages.
Definition: send.c:104
WHERE char * AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:104

+ Here is the caller graph for this function:

static int include_forward ( struct Context ctx,
struct Email cur,
FILE *  out 
)
static

Write out a forwarded message.

Parameters
ctxMailbox
curEmail
outFile to write to
Return values
0Success
-1Failure

Definition at line 542 of file send.c.

543 {
544  int chflags = CH_DECODE, cmflags = 0;
545 
546  mutt_parse_mime_message(ctx->mailbox, cur);
548 
549  if ((WithCrypto != 0) && (cur->security & ENCRYPT) && ForwardDecode)
550  {
551  /* make sure we have the user's passphrase before proceeding... */
552  if (!crypt_valid_passphrase(cur->security))
553  return -1;
554  }
555 
556  mutt_forward_intro(ctx, cur, out);
557 
558  if (ForwardDecode)
559  {
560  cmflags |= MUTT_CM_DECODE | MUTT_CM_CHARCONV;
561  if (Weed)
562  {
563  chflags |= CH_WEED | CH_REORDER;
564  cmflags |= MUTT_CM_WEED;
565  }
566  }
567  if (ForwardQuote)
568  cmflags |= MUTT_CM_PREFIX;
569 
570  /* wrapping headers for forwarding is considered a display
571  * rather than send action */
572  chflags |= CH_DISPLAY;
573 
574  mutt_copy_message_ctx(out, ctx->mailbox, cur, cmflags, chflags);
575  mutt_forward_trailer(ctx, cur, out);
576  return 0;
577 }
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
int mutt_copy_message_ctx(FILE *fpout, struct Mailbox *src, struct Email *e, int flags, int chflags)
Copy a message from a Context.
Definition: copy.c:792
WHERE bool ForwardDecode
Config: Decode the message when forwarding it.
Definition: globals.h:214
void mutt_forward_trailer(struct Context *ctx, struct Email *cur, FILE *fp)
Add a "end of forwarded message" text.
Definition: send.c:520
#define MUTT_CM_WEED
weed message/rfc822 attachment headers
Definition: copy.h:37
#define MUTT_MESSAGE_HOOK
Definition: hook.h:48
void mutt_forward_intro(struct Context *ctx, struct Email *cur, FILE *fp)
Add the "start of forwarded message" text.
Definition: send.c:501
struct Mailbox * mailbox
Definition: context.h:50
#define CH_WEED
weed the headers?
Definition: copy.h:48
void mutt_parse_mime_message(struct Mailbox *m, struct Email *cur)
Parse a MIME email.
Definition: mutt_parse.c:50
bool Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:38
#define ENCRYPT
Definition: ncrypt.h:119
#define MUTT_CM_PREFIX
quote the message
Definition: copy.h:33
#define MUTT_CM_DECODE
decode the message body into text/plain
Definition: copy.h:34
#define CH_REORDER
Re-order output of headers.
Definition: copy.h:54
#define MUTT_CM_CHARCONV
perform character set conversions
Definition: copy.h:38
#define CH_DECODE
do RFC1522 decoding?
Definition: copy.h:49
#define CH_DISPLAY
display result to user
Definition: copy.h:65
int crypt_valid_passphrase(int flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
WHERE bool ForwardQuote
Config: Automatically quote a forwarded message using IndentString.
Definition: globals.h:215
void mutt_message_hook(struct Mailbox *m, struct Email *e, int type)
Perform a message hook.
Definition: hook.c:438
#define WithCrypto
Definition: ncrypt.h:154

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_make_attribution ( struct Context ctx,
struct Email cur,
FILE *  out 
)

Add "on DATE, PERSON wrote" header.

Parameters
ctxMailbox
curEmail
outFile to write to

Definition at line 585 of file send.c.

586 {
587  if (!Attribution || !out)
588  return;
589 
590  char buf[LONG_STRING];
591  setlocale(LC_TIME, NONULL(AttributionLocale));
592  mutt_make_string(buf, sizeof(buf), Attribution, ctx, cur);
593  setlocale(LC_TIME, "");
594  fputs(buf, out);
595  fputc('\n', out);
596 }
#define NONULL(x)
Definition: string2.h:39
#define LONG_STRING
Definition: string2.h:36
#define mutt_make_string(A, B, C, D, E)
Definition: hdrline.h:55
WHERE char * Attribution
Config: Message to start a reply, "On DATE, PERSON wrote:".
Definition: globals.h:103
WHERE char * AttributionLocale
Config: Locale for dates in the attribution message.
Definition: globals.h:104

+ Here is the caller graph for this function:

void mutt_make_post_indent ( struct Context ctx,
struct Email cur,
FILE *  out 
)

Add suffix to replied email text.

Parameters
ctxMailbox
curEmail
outFile to write to

Definition at line 604 of file send.c.

605 {
606  if (!PostIndentString || !out)
607  return;
608 
609  char buf[STRING];
610  mutt_make_string(buf, sizeof(buf), PostIndentString, ctx, cur);
611  fputs(buf, out);
612  fputc('\n', out);
613 }
#define mutt_make_string(A, B, C, D, E)
Definition: hdrline.h:55
char * PostIndentString
Config: Suffix message to add after reply text.
Definition: send.c:115
#define STRING
Definition: string2.h:35

+ Here is the caller graph for this function:

static int include_reply ( struct Context ctx,
struct Email cur,
FILE *  out 
)
static

Generate the reply text for an email.

Parameters
ctxMailbox
curEmail
outFile to write to
Return values
0Success
-1Failure

Definition at line 623 of file send.c.

624 {
626  int chflags = CH_DECODE;
627 
628  if ((WithCrypto != 0) && (cur->security & ENCRYPT))
629  {
630  /* make sure we have the user's passphrase before proceeding... */
631  if (!crypt_valid_passphrase(cur->security))
632  return -1;
633  }
634 
635  mutt_parse_mime_message(ctx->mailbox, cur);
637 
638  mutt_make_attribution(ctx, cur, out);
639 
640  if (!Header)
641  cmflags |= MUTT_CM_NOHEADER;
642  if (Weed)
643  {
644  chflags |= CH_WEED | CH_REORDER;
645  cmflags |= MUTT_CM_WEED;
646  }
647 
648  mutt_copy_message_ctx(out, ctx->mailbox, cur, cmflags, chflags);
649 
650  mutt_make_post_indent(ctx, cur, out);
651 
652  return 0;
653 }
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
int mutt_copy_message_ctx(FILE *fpout, struct Mailbox *src, struct Email *e, int flags, int chflags)
Copy a message from a Context.
Definition: copy.c:792
#define MUTT_CM_WEED
weed message/rfc822 attachment headers
Definition: copy.h:37
void mutt_make_post_indent(struct Context *ctx, struct Email *cur, FILE *out)
Add suffix to replied email text.
Definition: send.c:604
#define MUTT_MESSAGE_HOOK
Definition: hook.h:48
#define MUTT_CM_REPLYING
replying the message
Definition: copy.h:40
struct Mailbox * mailbox
Definition: context.h:50
#define CH_WEED
weed the headers?
Definition: copy.h:48
void mutt_parse_mime_message(struct Mailbox *m, struct Email *cur)
Parse a MIME email.
Definition: mutt_parse.c:50
bool Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:38
void mutt_make_attribution(struct Context *ctx, struct Email *cur, FILE *out)
Add "on DATE, PERSON wrote" header.
Definition: send.c:585
#define ENCRYPT
Definition: ncrypt.h:119
#define MUTT_CM_PREFIX
quote the message
Definition: copy.h:33
#define MUTT_CM_DECODE
decode the message body into text/plain
Definition: copy.h:34
#define CH_REORDER
Re-order output of headers.
Definition: copy.h:54
#define MUTT_CM_CHARCONV
perform character set conversions
Definition: copy.h:38
WHERE bool Header
Config: Include the message headers in the reply email (Weed applies)
Definition: globals.h:221
#define CH_DECODE
do RFC1522 decoding?
Definition: copy.h:49
int crypt_valid_passphrase(int flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
#define MUTT_CM_NOHEADER
flags to mutt_copy_message
Definition: copy.h:32
void mutt_message_hook(struct Mailbox *m, struct Email *e, int type)
Perform a message hook.
Definition: hook.c:438
#define WithCrypto
Definition: ncrypt.h:154

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int default_to ( struct Address **  to,
struct Envelope env,
int  flags,
int  hmfupto 
)
static

Generate default email addresses.

Parameters
to'To' address
envEnvelope to populate
flagsFlags, e.g. SEND_LIST_REPLY
hmfuptoIf true, add 'followup-to' address to 'to' address
Return values
0Success
-1Aborted

Definition at line 664 of file send.c.

665 {
666  char prompt[STRING];
667 
668  if (flags && env->mail_followup_to && hmfupto == MUTT_YES)
669  {
670  mutt_addr_append(to, env->mail_followup_to, true);
671  return 0;
672  }
673 
674  /* Exit now if we're setting up the default Cc list for list-reply
675  * (only set if Mail-Followup-To is present and honoured).
676  */
677  if (flags & SEND_LIST_REPLY)
678  return 0;
679 
680  if (!ReplySelf && mutt_addr_is_user(env->from))
681  {
682  /* mail is from the user, assume replying to recipients */
683  mutt_addr_append(to, env->to, true);
684  }
685  else if (env->reply_to)
686  {
687  if ((mutt_addr_cmp(env->from, env->reply_to) && !env->reply_to->next &&
688  !env->reply_to->personal) ||
690  (mutt_addr_search(env->reply_to, env->to) ||
691  mutt_addr_search(env->reply_to, env->cc))))
692  {
693  /* If the Reply-To: address is a mailing list, assume that it was
694  * put there by the mailing list, and use the From: address
695  *
696  * We also take the from header if our correspondent has a reply-to
697  * header which is identical to the electronic mail address given
698  * in his From header, and the reply-to has no display-name. */
699  mutt_addr_append(to, env->from, false);
700  }
701  else if (!(mutt_addr_cmp(env->from, env->reply_to) && !env->reply_to->next) &&
702  ReplyTo != MUTT_YES)
703  {
704  /* There are quite a few mailing lists which set the Reply-To:
705  * header field to the list address, which makes it quite impossible
706  * to send a message to only the sender of the message. This
707  * provides a way to do that.
708  */
709  /* L10N:
710  Asks whether the user respects the reply-to header.
711  If she says no, neomutt will reply to the from header's address instead. */
712  snprintf(prompt, sizeof(prompt), _("Reply to %s%s?"),
713  env->reply_to->mailbox, env->reply_to->next ? ",..." : "");
714  switch (query_quadoption(ReplyTo, prompt))
715  {
716  case MUTT_YES:
717  mutt_addr_append(to, env->reply_to, false);
718  break;
719 
720  case MUTT_NO:
721  mutt_addr_append(to, env->from, false);
722  break;
723 
724  default:
725  return -1; /* abort */
726  }
727  }
728  else
729  mutt_addr_append(to, env->reply_to, false);
730  }
731  else
732  mutt_addr_append(to, env->from, false);
733 
734  return 0;
735 }
struct Address * to
Definition: envelope.h:36
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define _(a)
Definition: message.h:28
bool ReplySelf
Config: Really reply to yourself, when replying to your own email.
Definition: send.c:119
char * mailbox
mailbox and host address
Definition: address.h:35
struct Address * mutt_addr_append(struct Address **a, struct Address *b, bool prune)
Append one list of addresses onto another.
Definition: address.c:763
bool mutt_is_mail_list(struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:98
struct Address * reply_to
Definition: envelope.h:40
struct Address * mail_followup_to
Definition: envelope.h:41
bool IgnoreListReplyTo
Config: Ignore the &#39;Reply-To&#39; header when using <reply> on a mailing list.
Definition: send.c:110
#define SEND_LIST_REPLY
Definition: send.h:84
struct Address * from
Definition: envelope.h:35
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
int query_quadoption(int opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3227
bool mutt_addr_cmp(struct Address *a, struct Address *b)
Compare two e-mail addresses.
Definition: address.c:883
unsigned char ReplyTo
Config: Address to use as a &#39;Reply-To&#39; header.
Definition: send.c:120
char * personal
real name of address
Definition: address.h:34
#define STRING
Definition: string2.h:35
bool mutt_addr_search(struct Address *a, struct Address *lst)
Search for an e-mail address in a list.
Definition: address.c:898
struct Address * cc
Definition: envelope.h:37
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:676
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_fetch_recips ( struct Envelope out,
struct Envelope in,
int  flags 
)

Generate recpients for a reply email.

Parameters
outEnvelope to populate
inEnvelope of source email
flagsFlags, e.g. SEND_LIST_REPLY
Return values
0Success
-1Failure

Definition at line 745 of file send.c.

746 {
747  struct Address *tmp = NULL;
748  int hmfupto = -1;
749 
750  if ((flags & (SEND_LIST_REPLY | SEND_GROUP_REPLY)) && in->mail_followup_to)
751  {
752  char prompt[STRING];
753  snprintf(prompt, sizeof(prompt), _("Follow-up to %s%s?"),
754  in->mail_followup_to->mailbox, in->mail_followup_to->next ? ",..." : "");
755 
756  hmfupto = query_quadoption(HonorFollowupTo, prompt);
757  if (hmfupto == MUTT_ABORT)
758  return -1;
759  }
760 
761  if (flags & SEND_LIST_REPLY)
762  {
763  tmp = find_mailing_lists(in->to, in->cc);
764  mutt_addr_append(&out->to, tmp, false);
765  mutt_addr_free(&tmp);
766 
767  if (in->mail_followup_to && hmfupto == MUTT_YES &&
768  default_to(&out->cc, in, flags & SEND_LIST_REPLY, hmfupto) == MUTT_ABORT)
769  {
770  return -1; /* abort */
771  }
772  }
773  else if (flags & SEND_TO_SENDER)
774  {
775  mutt_addr_append(&out->to, in->from, false);
776  }
777  else
778  {
779  if (default_to(&out->to, in, flags & SEND_GROUP_REPLY, hmfupto) == MUTT_ABORT)
780  return -1; /* abort */
781 
782  if ((flags & SEND_GROUP_REPLY) && (!in->mail_followup_to || hmfupto != MUTT_YES))
783  {
784  /* if(!mutt_addr_is_user(in->to)) */
785  mutt_addr_append(&out->cc, in->to, true);
786  mutt_addr_append(&out->cc, in->cc, true);
787  }
788  }
789  return 0;
790 }
#define SEND_TO_SENDER
Definition: send.h:94
User aborted the question (with Ctrl-G)
Definition: quad.h:37
struct Address * to
Definition: envelope.h:36
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define _(a)
Definition: message.h:28
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
static int default_to(struct Address **to, struct Envelope *env, int flags, int hmfupto)
Generate default email addresses.
Definition: send.c:664
struct Address * mutt_addr_append(struct Address **a, struct Address *b, bool prune)
Append one list of addresses onto another.
Definition: address.c:763
struct Address * mail_followup_to
Definition: envelope.h:41
#define SEND_LIST_REPLY
Definition: send.h:84
struct Address * from
Definition: envelope.h:35
int query_quadoption(int opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3227
unsigned char HonorFollowupTo
Config: Honour the &#39;Mail-Followup-To&#39; header when group replying.
Definition: send.c:109
#define SEND_GROUP_REPLY
Definition: send.h:83
#define STRING
Definition: string2.h:35
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
static struct Address * find_mailing_lists(struct Address *t, struct Address *c)
Search Address lists for mailing lists.
Definition: send.c:249
struct Address * cc
Definition: envelope.h:37
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 797 of file send.c.

798 {
799  struct ListNode *np = NULL;
800 
801  struct ListHead *src = !STAILQ_EMPTY(&env->references) ? &env->references : &env->in_reply_to;
802  STAILQ_FOREACH(np, src, entries)
803  {
805  }
806 }
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:60
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:58
#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:384
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct ListHead references
message references (in reverse order)
Definition: envelope.h:59
A List node for strings.
Definition: list.h:33

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 813 of file send.c.

814 {
815  if (env->message_id)
816  {
818  }
819 }
char * message_id
Definition: envelope.h:47
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:44
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_fix_reply_recipients ( struct Envelope env)

Remove duplicate recipients.

Parameters
envEnvelope to fix

Definition at line 825 of file send.c.

826 {
827  if (!Metoo)
828  {
829  /* the order is important here. do the CC: first so that if the
830  * the user is the only recipient, it ends up on the TO: field
831  */
832  env->cc = remove_user(env->cc, (env->to == NULL));
833  env->to = remove_user(env->to, (env->cc == NULL) || ReplySelf);
834  }
835 
836  /* the CC field can get cluttered, especially with lists */
837  env->to = mutt_addrlist_dedupe(env->to);
838  env->cc = mutt_addrlist_dedupe(env->cc);
839  env->cc = mutt_remove_xrefs(env->to, env->cc);
840 
841  if (env->cc && !env->to)
842  {
843  env->to = env->cc;
844  env->cc = NULL;
845  }
846 }
static struct Address * remove_user(struct Address *a, bool leave_only)
Remove any address which matches the current user.
Definition: send.c:202
struct Address * to
Definition: envelope.h:36
struct Address * mutt_addrlist_dedupe(struct Address *addr)
Remove duplicate addresses.
Definition: address.c:1281
bool ReplySelf
Config: Really reply to yourself, when replying to your own email.
Definition: send.c:119
struct Address * mutt_remove_xrefs(struct Address *a, struct Address *b)
Remove cross-references.
Definition: send.c:157
bool Metoo
Config: Remove the user&#39;s address from the list of recipients.
Definition: send.c:112
struct Address * cc
Definition: envelope.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_make_forward_subject ( struct Envelope env,
struct Context ctx,
struct Email cur 
)

Create a subject for a forwarded email.

Parameters
envEnvelope for result
ctxMailbox
curEmail

Definition at line 854 of file send.c.

855 {
856  if (!env)
857  return;
858 
859  char buf[STRING];
860 
861  /* set the default subject for the message. */
862  mutt_make_string(buf, sizeof(buf), NONULL(ForwardFormat), ctx, cur);
863  mutt_str_replace(&env->subject, buf);
864 }
#define NONULL(x)
Definition: string2.h:39
char * ForwardFormat
Config: printf-like format string to control the subject when forwarding a message.
Definition: send.c:106
#define mutt_make_string(A, B, C, D, E)
Definition: hdrline.h:55
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
char * subject
Definition: envelope.h:44
#define STRING
Definition: string2.h:35

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 871 of file send.c.

872 {
873  if (!env || !curenv)
874  return;
875 
876  /* This takes precedence over a subject that might have
877  * been taken from a List-Post header. Is that correct?
878  */
879  if (curenv->real_subj)
880  {
881  FREE(&env->subject);
882  env->subject = mutt_mem_malloc(mutt_str_strlen(curenv->real_subj) + 5);
883  sprintf(env->subject, "Re: %s", curenv->real_subj);
884  }
885  else if (!env->subject)
887 }
char * EmptySubject
Config: Subject to use when replying to an email with none.
Definition: send.c:98
char * real_subj
offset of the real subject
Definition: envelope.h:45
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
char * subject
Definition: envelope.h:44
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 894 of file send.c.

895 {
896  add_references(&env->references, curenv);
897  add_message_id(&env->references, curenv);
898  add_message_id(&env->in_reply_to, curenv);
899 
900 #ifdef USE_NNTP
901  if (OptNewsSend && XCommentTo && curenv->from)
903 #endif
904 }
WHERE bool XCommentTo
Config: (nntp) Add &#39;X-Comment-To&#39; header that contains article author.
Definition: globals.h:282
static void add_references(struct ListHead *head, struct Envelope *env)
Add the email&#39;s references to a list.
Definition: send.c:797
static void add_message_id(struct ListHead *head, struct Envelope *env)
Add the email&#39;s message ID to a list.
Definition: send.c:813
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:60
struct Address * from
Definition: envelope.h:35
char * x_comment_to
Definition: envelope.h:56
const char * mutt_get_name(struct Address *a)
Pick the best name to display from an address.
Definition: sort.c:153
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
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:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void make_reference_headers ( struct Envelope curenv,
struct Envelope env,
struct Context ctx 
)
static

Generate reference headers for an email.

Parameters
curenvEnvelope of source email
envEnvelope for result
ctxMailbox

Definition at line 912 of file send.c.

914 {
915  if (!env || !ctx || !ctx->mailbox)
916  return;
917 
918  if (!curenv)
919  {
920  for (int i = 0; i < ctx->mailbox->msg_count; i++)
921  {
922  if (message_is_tagged(ctx, i))
924  }
925  }
926  else
927  mutt_add_to_reference_headers(env, curenv);
928 
929  /* if there's more than entry in In-Reply-To (i.e. message has
930  multiple parents), don't generate a References: header as it's
931  discouraged by RFC2822, sect. 3.6.4 */
932  if (ctx->mailbox->msg_tagged > 0 && !STAILQ_EMPTY(&env->in_reply_to) &&
933  STAILQ_NEXT(STAILQ_FIRST(&env->in_reply_to), entries))
934  {
935  mutt_list_free(&env->references);
936  }
937 }
int msg_count
total number of messages
Definition: mailbox.h:86
struct Email ** hdrs
Definition: mailbox.h:93
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:105
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:60
struct Mailbox * mailbox
Definition: context.h:50
struct Envelope * env
envelope information
Definition: email.h:91
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: curs_lib.c:1236
int msg_tagged
how many messages are tagged?
Definition: mailbox.h:91
#define STAILQ_NEXT(elm, field)
Definition: queue.h:398
#define STAILQ_EMPTY(head)
Definition: queue.h:346
struct ListHead references
message references (in reverse order)
Definition: envelope.h:59
#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:894

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int envelope_defaults ( struct Envelope env,
struct Context ctx,
struct Email cur,
int  flags 
)
static

Fill in some defaults for a new email.

Parameters
envEnvelope for result
ctxMailbox
curEmail
flagsFlags, e.g. SEND_REPLY
Return values
0Success
-1Failure

Definition at line 948 of file send.c.

950 {
951  struct Envelope *curenv = NULL;
952  bool tag = false;
953 
954  if (!cur)
955  {
956  tag = true;
957  for (int i = 0; i < ctx->mailbox->msg_count; i++)
958  {
959  if (!message_is_tagged(ctx, i))
960  continue;
961 
962  cur = ctx->mailbox->hdrs[i];
963  curenv = cur->env;
964  break;
965  }
966 
967  if (!cur)
968  {
969  /* This could happen if the user tagged some messages and then did
970  * a limit such that none of the tagged message are visible.
971  */
972  mutt_error(_("No tagged messages are visible"));
973  return -1;
974  }
975  }
976  else
977  curenv = cur->env;
978 
979  if (!curenv)
980  return -1;
981 
982  if (flags & (SEND_REPLY | SEND_TO_SENDER))
983  {
984 #ifdef USE_NNTP
985  if ((flags & SEND_NEWS))
986  {
987  /* in case followup set Newsgroups: with Followup-To: if it present */
988  if (!env->newsgroups &&
989  (mutt_str_strcasecmp(curenv->followup_to, "poster") != 0))
990  {
991  env->newsgroups = mutt_str_strdup(curenv->followup_to);
992  }
993  }
994  else
995 #endif
996  if (tag)
997  {
998  for (int i = 0; i < ctx->mailbox->msg_count; i++)
999  {
1000  if (!message_is_tagged(ctx, i))
1001  continue;
1002 
1003  if (mutt_fetch_recips(env, ctx->mailbox->hdrs[i]->env, flags) == -1)
1004  return -1;
1005  }
1006  }
1007  else if (mutt_fetch_recips(env, curenv, flags) == -1)
1008  return -1;
1009 
1010  if ((flags & SEND_LIST_REPLY) && !env->to)
1011  {
1012  mutt_error(_("No mailing lists found"));
1013  return -1;
1014  }
1015 
1016  if (flags & SEND_REPLY)
1017  {
1018  mutt_make_misc_reply_headers(env, curenv);
1019  make_reference_headers(tag ? NULL : curenv, env, ctx);
1020  }
1021  }
1022  else if (flags & SEND_FORWARD)
1023  {
1024  mutt_make_forward_subject(env, ctx, cur);
1025  if (ForwardReferences)
1026  make_reference_headers(tag ? NULL : curenv, env, ctx);
1027  }
1028 
1029  return 0;
1030 }
int msg_count
total number of messages
Definition: mailbox.h:86
#define SEND_TO_SENDER
Definition: send.h:94
struct Address * to
Definition: envelope.h:36
#define SEND_FORWARD
Definition: send.h:85
#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:871
void mutt_make_forward_subject(struct Envelope *env, struct Context *ctx, struct Email *cur)
Create a subject for a forwarded email.
Definition: send.c:854
struct Email ** hdrs
Definition: mailbox.h:93
int mutt_fetch_recips(struct Envelope *out, struct Envelope *in, int flags)
Generate recpients for a reply email.
Definition: send.c:745
struct Mailbox * mailbox
Definition: context.h:50
struct Envelope * env
envelope information
Definition: email.h:91
#define SEND_LIST_REPLY
Definition: send.h:84
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: curs_lib.c:1236
#define SEND_NEWS
Definition: send.h:95
#define SEND_REPLY
Definition: send.h:82
char * newsgroups
Definition: envelope.h:53
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define mutt_error(...)
Definition: logging.h:88
char * followup_to
Definition: envelope.h:55
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
static void make_reference_headers(struct Envelope *curenv, struct Envelope *env, struct Context *ctx)
Generate reference headers for an email.
Definition: send.c:912
bool ForwardReferences
Config: Set the &#39;In-Reply-To&#39; and &#39;References&#39; headers when forwarding a message. ...
Definition: send.c:107
The header of an email.
Definition: envelope.h:32

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int generate_body ( FILE *  tempfp,
struct Email msg,
int  flags,
struct Context ctx,
struct Email cur 
)
static

Create a new email body.

Parameters
tempfpstream for outgoing message
msgheader for outgoing message
flagscompose mode
ctxcurrent mailbox
curcurrent message
Return values
0Success
-1Error

Definition at line 1042 of file send.c.

1044 {
1045  int i;
1046  struct Body *tmp = NULL;
1047 
1048  if (flags & SEND_REPLY)
1049  {
1050  i = query_quadoption(Include, _("Include message in reply?"));
1051  if (i == MUTT_ABORT)
1052  return -1;
1053 
1054  if (i == MUTT_YES)
1055  {
1056  mutt_message(_("Including quoted message..."));
1057  if (!cur)
1058  {
1059  for (i = 0; i < ctx->mailbox->msg_count; i++)
1060  {
1061  if (!message_is_tagged(ctx, i))
1062  continue;
1063 
1064  if (include_reply(ctx, ctx->mailbox->hdrs[i], tempfp) == -1)
1065  {
1066  mutt_error(_("Could not include all requested messages"));
1067  return -1;
1068  }
1069  fputc('\n', tempfp);
1070  }
1071  }
1072  else
1073  include_reply(ctx, cur, tempfp);
1074  }
1075  }
1076  else if (flags & SEND_FORWARD)
1077  {
1078  i = query_quadoption(MimeForward, _("Forward as attachment?"));
1079  if (i == MUTT_YES)
1080  {
1081  struct Body *last = msg->content;
1082 
1083  mutt_message(_("Preparing forwarded message..."));
1084 
1085  while (last && last->next)
1086  last = last->next;
1087 
1088  if (cur)
1089  {
1090  tmp = mutt_make_message_attach(ctx->mailbox, cur, false);
1091  if (last)
1092  last->next = tmp;
1093  else
1094  msg->content = tmp;
1095  }
1096  else
1097  {
1098  for (i = 0; i < ctx->mailbox->msg_count; i++)
1099  {
1100  if (!message_is_tagged(ctx, i))
1101  continue;
1102 
1103  tmp = mutt_make_message_attach(ctx->mailbox, ctx->mailbox->hdrs[i], false);
1104  if (last)
1105  {
1106  last->next = tmp;
1107  last = tmp;
1108  }
1109  else
1110  {
1111  last = tmp;
1112  msg->content = tmp;
1113  }
1114  }
1115  }
1116  }
1117  else if (i != -1)
1118  {
1119  if (cur)
1120  include_forward(ctx, cur, tempfp);
1121  else
1122  {
1123  for (i = 0; i < ctx->mailbox->msg_count; i++)
1124  {
1125  if (message_is_tagged(ctx, i))
1126  include_forward(ctx, ctx->mailbox->hdrs[i], tempfp);
1127  }
1128  }
1129  }
1130  else
1131  return -1;
1132  }
1133  /* if (WithCrypto && (flags & SEND_KEY)) */
1134  else if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY))
1135  {
1136  struct Body *b = NULL;
1137 
1138  if (((WithCrypto & APPLICATION_PGP) != 0) && !(b = crypt_pgp_make_key_attachment()))
1139  {
1140  return -1;
1141  }
1142 
1143  b->next = msg->content;
1144  msg->content = b;
1145  }
1146 
1147  mutt_clear_error();
1148 
1149  return 0;
1150 }
unsigned char Include
Config: Include a copy of the email that&#39;s being replied to.
Definition: send.c:111
struct Body * mutt_make_message_attach(struct Mailbox *m, struct Email *e, bool attach_msg)
Create a message attachment.
Definition: sendlib.c:1459
int msg_count
total number of messages
Definition: mailbox.h:86
static int include_forward(struct Context *ctx, struct Email *cur, FILE *out)
Write out a forwarded message.
Definition: send.c:542
User aborted the question (with Ctrl-G)
Definition: quad.h:37
#define mutt_message(...)
Definition: logging.h:87
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define SEND_FORWARD
Definition: send.h:85
struct Body * content
list of MIME parts
Definition: email.h:92
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:57
struct Email ** hdrs
Definition: mailbox.h:93
The body of an email.
Definition: body.h:33
struct Mailbox * mailbox
Definition: context.h:50
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
#define SEND_KEY
Definition: send.h:89
int query_quadoption(int opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3227
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: curs_lib.c:1236
#define SEND_REPLY
Definition: send.h:82
#define APPLICATION_PGP
Definition: ncrypt.h:129
WHERE unsigned char MimeForward
Config: Forward a message as a &#39;message/RFC822&#39; MIME part.
Definition: globals.h:188
struct Body * crypt_pgp_make_key_attachment(void)
Wrapper for CryptModuleSpecs::pgp_make_key_attachment()
Definition: cryptglue.c:260
#define mutt_error(...)
Definition: logging.h:88
static int include_reply(struct Context *ctx, struct Email *cur, FILE *out)
Generate the reply text for an email.
Definition: send.c:623
#define WithCrypto
Definition: ncrypt.h:154

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_set_followup_to ( struct Envelope env)

Set followup-to field.

Parameters
envEnvelope to modify

Definition at line 1156 of file send.c.

1157 {
1158  struct Address *t = NULL;
1159  struct Address *from = NULL;
1160 
1161  /* Only generate the Mail-Followup-To if the user has requested it, and
1162  * it hasn't already been set
1163  */
1164 
1165  if (!FollowupTo)
1166  return;
1167 #ifdef USE_NNTP
1168  if (OptNewsSend)
1169  {
1170  if (!env->followup_to && env->newsgroups && (strrchr(env->newsgroups, ',')))
1171  env->followup_to = mutt_str_strdup(env->newsgroups);
1172  return;
1173  }
1174 #endif
1175 
1176  if (!env->mail_followup_to)
1177  {
1178  if (mutt_is_list_cc(0, env->to, env->cc))
1179  {
1180  /* this message goes to known mailing lists, so create a proper
1181  * mail-followup-to header
1182  */
1183 
1184  t = mutt_addr_append(&env->mail_followup_to, env->to, false);
1185  mutt_addr_append(&t, env->cc, true);
1186  }
1187 
1188  /* remove ourselves from the mail-followup-to header */
1189  env->mail_followup_to = remove_user(env->mail_followup_to, false);
1190 
1191  /* If we are not subscribed to any of the lists in question,
1192  * re-add ourselves to the mail-followup-to header. The
1193  * mail-followup-to header generated is a no-op with group-reply,
1194  * but makes sure list-reply has the desired effect.
1195  */
1196 
1197  if (env->mail_followup_to && !mutt_is_list_recipient(false, env->to, env->cc))
1198  {
1199  if (env->reply_to)
1200  from = mutt_addr_copy_list(env->reply_to, false);
1201  else if (env->from)
1202  from = mutt_addr_copy_list(env->from, false);
1203  else
1204  from = mutt_default_from();
1205 
1206  if (from)
1207  {
1208  /* Normally, this loop will not even be entered. */
1209  for (t = from; t && t->next; t = t->next)
1210  ;
1211 
1212  t->next = env->mail_followup_to; /* t cannot be NULL at this point. */
1213  env->mail_followup_to = from;
1214  }
1215  }
1216 
1218  }
1219 }
static struct Address * remove_user(struct Address *a, bool leave_only)
Remove any address which matches the current user.
Definition: send.c:202
struct Address * to
Definition: envelope.h:36
int mutt_is_list_recipient(bool alladdr, struct Address *a1, struct Address *a2)
Matches subscribed mailing lists.
Definition: pattern.c:1614
struct Address * mutt_addrlist_dedupe(struct Address *addr)
Remove duplicate addresses.
Definition: address.c:1281
An email address.
Definition: address.h:32
struct Address * mutt_addr_append(struct Address **a, struct Address *b, bool prune)
Append one list of addresses onto another.
Definition: address.c:763
struct Address * reply_to
Definition: envelope.h:40
struct Address * mail_followup_to
Definition: envelope.h:41
struct Address * from
Definition: envelope.h:35
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1266
bool FollowupTo
Config: Add the &#39;Mail-Followup-To&#39; header is generated when sending mail.
Definition: send.c:102
int mutt_is_list_cc(int alladdr, struct Address *a1, struct Address *a2)
Matches known mailing lists.
Definition: pattern.c:1636
char * newsgroups
Definition: envelope.h:53
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
char * followup_to
Definition: envelope.h:55
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct Address * mutt_addr_copy_list(struct Address *addr, bool prune)
Copy a list of addresses.
Definition: address.c:730
struct Address * cc
Definition: envelope.h:37
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static struct Address* set_reverse_name ( struct Envelope env)
static

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

Parameters
envEnvelope to use
Return values
ptrNewly allocated Address
NULLA suitable Address wasn't found

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 1231 of file send.c.

1232 {
1233  struct Address *tmp = NULL;
1234 
1235  for (tmp = env->to; tmp; tmp = tmp->next)
1236  {
1237  if (mutt_addr_is_user(tmp))
1238  break;
1239  }
1240  if (!tmp)
1241  {
1242  for (tmp = env->cc; tmp; tmp = tmp->next)
1243  {
1244  if (mutt_addr_is_user(tmp))
1245  break;
1246  }
1247  }
1248  if (!tmp && mutt_addr_is_user(env->from))
1249  tmp = env->from;
1250  if (tmp)
1251  {
1252  tmp = mutt_addr_copy(tmp);
1253  /* when $reverse_realname is not set, clear the personal name so that it
1254  * may be set via a reply- or send-hook.
1255  */
1256  if (!ReverseRealname)
1257  FREE(&tmp->personal);
1258  }
1259  return tmp;
1260 }
struct Address * to
Definition: envelope.h:36
An email address.
Definition: address.h:32
bool ReverseRealname
Config: Set the &#39;From&#39; from the full &#39;To&#39; address the email was sent to.
Definition: send.c:123
struct Address * mutt_addr_copy(struct Address *addr)
Copy the real address.
Definition: address.c:712
struct Address * from
Definition: envelope.h:35
char * personal
real name of address
Definition: address.h:34
#define FREE(x)
Definition: memory.h:46
struct Address * cc
Definition: envelope.h:37
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:676
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Address* mutt_default_from ( void  )

Get a default 'from' Address.

Return values
ptrNewly allocated Address

Definition at line 1266 of file send.c.

1267 {
1268  struct Address *addr = NULL;
1269 
1270  /* Note: We let $from override $realname here.
1271  * Is this the right thing to do?
1272  */
1273 
1274  if (From)
1275  addr = mutt_addr_copy(From);
1276  else
1277  {
1278  addr = mutt_addr_new();
1279  if (UseDomain)
1280  {
1281  const char *fqdn = mutt_fqdn(true);
1282  addr->mailbox =
1284  sprintf(addr->mailbox, "%s@%s", NONULL(Username), NONULL(fqdn));
1285  }
1286  else
1287  {
1288  addr->mailbox = mutt_str_strdup(Username);
1289  }
1290  }
1291 
1292  return addr;
1293 }
WHERE char * Username
User&#39;s login name.
Definition: globals.h:50
#define NONULL(x)
Definition: string2.h:39
An email address.
Definition: address.h:32
char * mailbox
mailbox and host address
Definition: address.h:35
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
struct Address * mutt_addr_copy(struct Address *addr)
Copy the real address.
Definition: address.c:712
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2425
WHERE struct Address * From
Config: Default &#39;From&#39; address to use, if isn&#39;t otherwise set.
Definition: globals.h:100
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
WHERE bool UseDomain
Config: Qualify local addresses using this domain.
Definition: globals.h:261
struct Address * mutt_addr_new(void)
Create a new Address.
Definition: address.c:401

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int send_message ( struct Email msg)
static

Send an email.

Parameters
msgEmail
Return values
0Success
-1Failure

Definition at line 1301 of file send.c.

1302 {
1303  char tempfile[PATH_MAX];
1304  int i;
1305 #ifdef USE_SMTP
1306  short old_write_bcc;
1307 #endif
1308 
1309  /* Write out the message in MIME form. */
1310  mutt_mktemp(tempfile, sizeof(tempfile));
1311  FILE *tempfp = mutt_file_fopen(tempfile, "w");
1312  if (!tempfp)
1313  return -1;
1314 
1315 #ifdef USE_SMTP
1316  old_write_bcc = WriteBcc;
1317  if (SmtpUrl)
1318  WriteBcc = false;
1319 #endif
1320 #ifdef MIXMASTER
1321  mutt_rfc822_write_header(tempfp, msg->env, msg->content, 0, !STAILQ_EMPTY(&msg->chain));
1322 #endif
1323 #ifndef MIXMASTER
1324  mutt_rfc822_write_header(tempfp, msg->env, msg->content, 0, false);
1325 #endif
1326 #ifdef USE_SMTP
1327  if (old_write_bcc)
1328  WriteBcc = true;
1329 #endif
1330 
1331  fputc('\n', tempfp); /* tie off the header. */
1332 
1333  if ((mutt_write_mime_body(msg->content, tempfp) == -1))
1334  {
1335  mutt_file_fclose(&tempfp);
1336  unlink(tempfile);
1337  return -1;
1338  }
1339 
1340  if (fclose(tempfp) != 0)
1341  {
1342  mutt_perror(tempfile);
1343  unlink(tempfile);
1344  return -1;
1345  }
1346 
1347 #ifdef MIXMASTER
1348  if (!STAILQ_EMPTY(&msg->chain))
1349  return mix_send_message(&msg->chain, tempfile);
1350 #endif
1351 
1352 #ifdef USE_SMTP
1353 #ifdef USE_NNTP
1354  if (!OptNewsSend)
1355 #endif
1356  if (SmtpUrl)
1357  {
1358  return mutt_smtp_send(msg->env->from, msg->env->to, msg->env->cc, msg->env->bcc,
1359  tempfile, (msg->content->encoding == ENC_8BIT));
1360  }
1361 #endif /* USE_SMTP */
1362 
1363  i = mutt_invoke_sendmail(msg->env->from, msg->env->to, msg->env->cc, msg->env->bcc,
1364  tempfile, (msg->content->encoding == ENC_8BIT));
1365  return i;
1366 }
#define mutt_perror(...)
Definition: logging.h:89
struct Address * to
Definition: envelope.h:36
struct Body * content
list of MIME parts
Definition: email.h:92
8-bit text
Definition: mime.h:50
int mutt_invoke_sendmail(struct Address *from, struct Address *to, struct Address *cc, struct Address *bcc, const char *msg, int eightbit)
Run sendmail.
Definition: sendlib.c:2707
int mutt_write_mime_body(struct Body *a, FILE *f)
Write a MIME part.
Definition: sendlib.c:488
int mutt_rfc822_write_header(FILE *fp, struct Envelope *env, struct Body *attach, int mode, bool privacy)
Write out one RFC822 header line.
Definition: sendlib.c:2212
WHERE bool WriteBcc
Config: Write out the &#39;Bcc&#39; field when preparing to send a mail.
Definition: globals.h:264
struct Envelope * env
envelope information
Definition: email.h:91
unsigned int encoding
content-transfer-encoding
Definition: body.h:68
struct Address * from
Definition: envelope.h:35
struct Address * bcc
Definition: envelope.h:38
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
#define PATH_MAX
Definition: mutt.h:46
int mix_send_message(struct ListHead *chain, const char *tempfile)
Send an email via Mixmaster.
Definition: remailer.c:827
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
WHERE char * SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:145
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define STAILQ_EMPTY(head)
Definition: queue.h:346
int mutt_smtp_send(const struct Address *from, const struct Address *to, const struct Address *cc, const struct Address *bcc, const char *msgfile, bool eightbit)
Send a message using SMTP.
Definition: smtp.c:739
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
struct Address * cc
Definition: envelope.h:37

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 1373 of file send.c.

1374 {
1375  for (struct Body *t = b; t; t = t->next)
1376  {
1377  if (t->description)
1378  {
1379  rfc2047_encode(&t->description, NULL, sizeof("Content-Description:"), SendCharset);
1380  }
1381  if (recurse && t->parts)
1382  mutt_encode_descriptions(t->parts, recurse);
1383  }
1384 }
struct Body * next
next attachment in the list
Definition: body.h:57
The body of an email.
Definition: body.h:33
void rfc2047_encode(char **pd, const char *specials, int col, const char *charsets)
RFC-2047-encode a string.
Definition: rfc2047.c:625
void mutt_encode_descriptions(struct Body *b, bool recurse)
rfc2047 encode the content-descriptions
Definition: send.c:1373
char * SendCharset
Config: Character sets for outgoing mail ///< Config: List of character sets for outgoing messages...
Definition: email_globals.c:36

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void decode_descriptions ( struct Body b)
static

rfc2047 decode them in case of an error

Parameters
bMIME parts to decode

Definition at line 1390 of file send.c.

1391 {
1392  for (struct Body *t = b; t; t = t->next)
1393  {
1394  if (t->description)
1395  {
1396  rfc2047_decode(&t->description);
1397  }
1398  if (t->parts)
1399  decode_descriptions(t->parts);
1400  }
1401 }
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:649
struct Body * next
next attachment in the list
Definition: body.h:57
The body of an email.
Definition: body.h:33
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1390

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 1407 of file send.c.

1408 {
1409  FILE *fp = mutt_file_fopen(data, "a+");
1410  if (!fp)
1411  return;
1412  if (fseek(fp, -1, SEEK_END) >= 0)
1413  {
1414  int c = fgetc(fp);
1415  if (c != '\n')
1416  fputc('\n', fp);
1417  }
1418  mutt_file_fclose(&fp);
1419 }
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_resend_message ( FILE *  fp,
struct Context ctx,
struct Email cur 
)

Resend an email.

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

Definition at line 1430 of file send.c.

1431 {
1432  struct Email *msg = mutt_email_new();
1433 
1434  if (mutt_prepare_template(fp, ctx->mailbox, msg, cur, true) < 0)
1435  {
1436  mutt_email_free(&msg);
1437  return -1;
1438  }
1439 
1440  if (WithCrypto)
1441  {
1442  /* mutt_prepare_template doesn't always flip on an application bit.
1443  * so fix that here */
1444  if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP)))
1445  {
1446  if (((WithCrypto & APPLICATION_SMIME) != 0) && SmimeIsDefault)
1447  msg->security |= APPLICATION_SMIME;
1448  else if (WithCrypto & APPLICATION_PGP)
1449  msg->security |= APPLICATION_PGP;
1450  else
1451  msg->security |= APPLICATION_SMIME;
1452  }
1453 
1455  {
1456  msg->security |= OPPENCRYPT;
1458  }
1459  }
1460 
1461  return ci_send_message(SEND_RESEND, msg, NULL, ctx, cur);
1462 }
The envelope/body of an email.
Definition: email.h:35
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
struct Mailbox * mailbox
Definition: context.h:50
#define OPPENCRYPT
Definition: ncrypt.h:127
WHERE bool SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:272
void crypt_opportunistic_encrypt(struct Email *msg)
Can all recipients be determined.
Definition: crypt.c:1021
#define SEND_RESEND
Definition: send.h:90
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *newhdr, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:580
void mutt_email_free(struct Email **e)
Free an Email.
Definition: email.c:41
#define APPLICATION_PGP
Definition: ncrypt.h:129
WHERE bool CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:271
int ci_send_message(int flags, struct Email *msg, char *tempfile, struct Context *ctx, struct Email *cur)
Send an email.
Definition: send.c:1530
#define WithCrypto
Definition: ncrypt.h:154
#define APPLICATION_SMIME
Definition: ncrypt.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int is_reply ( struct Email reply,
struct Email orig 
)
static

Is one email a reply to another?

Parameters
replyEmail to test
origOriginal email
Return values
1It is a reply
0It is not a reply

Definition at line 1471 of file send.c.

1472 {
1473  if (!reply || !reply->env || !orig || !orig->env)
1474  return 0;
1475  return mutt_list_find(&orig->env->references, reply->env->message_id) ||
1476  mutt_list_find(&orig->env->in_reply_to, reply->env->message_id);
1477 }
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:60
char * message_id
Definition: envelope.h:47
struct Envelope * env
envelope information
Definition: email.h:91
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:88
struct ListHead references
message references (in reverse order)
Definition: envelope.h:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 1489 of file send.c.

1490 {
1491  /* Search for the regex in AbortNoattachRegex within a file */
1493  !QuoteRegex->regex)
1494  {
1495  return false;
1496  }
1497 
1498  FILE *attf = mutt_file_fopen(filename, "r");
1499  if (!attf)
1500  return false;
1501 
1502  char *inputline = mutt_mem_malloc(LONG_STRING);
1503  bool found = false;
1504  while (!feof(attf))
1505  {
1506  fgets(inputline, LONG_STRING, attf);
1507  if (!mutt_is_quote_line(inputline, NULL) &&
1508  regexec(AbortNoattachRegex->regex, inputline, 0, NULL, 0) == 0)
1509  {
1510  found = true;
1511  break;
1512  }
1513  }
1514  FREE(&inputline);
1515  mutt_file_fclose(&attf);
1516  return found;
1517 }
regex_t * regex
compiled expression
Definition: regex3.h:60
#define LONG_STRING
Definition: string2.h:36
struct Regex * AbortNoattachRegex
Config: Regex to match text indicating attachments are expected.
Definition: send.c:85
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define FREE(x)
Definition: memory.h:46
int mutt_is_quote_line(char *line, regmatch_t *pmatch)
Is a line of message text a quote?
Definition: pager.c:850
WHERE struct Regex * QuoteRegex
Config: Regex to match quoted text in a reply.
Definition: globals.h:182

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int ci_send_message ( int  flags,
struct Email msg,
char *  tempfile,
struct Context ctx,
struct Email cur 
)

Send an email.

Parameters
flagssend mode, e.g. SEND_RESEND
msgtemplate to use for new message
tempfilefile specified by -i or -H
ctxcurrent mailbox
curcurrent message
Return values
0Message was successfully sent
-1Message was aborted or an error occurred
1Message was postponed

Definition at line 1530 of file send.c.

1532 {
1533  char buf[LONG_STRING];
1534  char fcc[PATH_MAX] = ""; /* where to copy this message */
1535  FILE *tempfp = NULL;
1536  struct Body *pbody = NULL;
1537  int i;
1538  bool killfrom = false;
1539  bool fcc_error = false;
1540  bool free_clear_content = false;
1541 
1542  struct Body *save_content = NULL;
1543  struct Body *clear_content = NULL;
1544  char *pgpkeylist = NULL;
1545  /* save current value of "pgp_sign_as" and "smime_default_key" */
1546  char *pgp_signas = NULL;
1547  char *smime_signas = NULL;
1548  const char *tag = NULL;
1549  char *err = NULL;
1550  char *ctype = NULL;
1551  char *finalpath = NULL;
1552 
1553  int rc = -1;
1554 
1555 #ifdef USE_NNTP
1556  if (flags & SEND_NEWS)
1557  OptNewsSend = true;
1558  else
1559  OptNewsSend = false;
1560 #endif
1561 
1562  if (!flags && !msg && Recall != MUTT_NO && mutt_num_postponed(ctx ? ctx->mailbox: NULL, true))
1563  {
1564  /* If the user is composing a new message, check to see if there
1565  * are any postponed messages first.
1566  */
1567  i = query_quadoption(Recall, _("Recall postponed message?"));
1568  if (i == MUTT_ABORT)
1569  return rc;
1570 
1571  if (i == MUTT_YES)
1572  flags |= SEND_POSTPONED;
1573  }
1574 
1575  if (flags & SEND_POSTPONED)
1576  {
1578  pgp_signas = mutt_str_strdup(PgpSignAs);
1580  smime_signas = mutt_str_strdup(SmimeSignAs);
1581  }
1582 
1583  /* Delay expansion of aliases until absolutely necessary--shouldn't
1584  * be necessary unless we are prompting the user or about to execute a
1585  * send-hook.
1586  */
1587 
1588  if (!msg)
1589  {
1590  msg = mutt_email_new();
1591 
1592  if (flags == SEND_POSTPONED)
1593  {
1594  flags = mutt_get_postponed(ctx, msg, &cur, fcc, sizeof(fcc));
1595  if (flags < 0)
1596  goto cleanup;
1597 #ifdef USE_NNTP
1598  /* If postponed message is a news article, it have
1599  * a "Newsgroups:" header line, then set appropriate flag.
1600  */
1601  if (msg->env->newsgroups)
1602  {
1603  flags |= SEND_NEWS;
1604  OptNewsSend = true;
1605  }
1606  else
1607  {
1608  flags &= ~SEND_NEWS;
1609  OptNewsSend = false;
1610  }
1611 #endif
1612  }
1613 
1614  if (flags & (SEND_POSTPONED | SEND_RESEND))
1615  {
1616  tempfp = mutt_file_fopen(msg->content->filename, "a+");
1617  if (!tempfp)
1618  {
1619  mutt_perror(msg->content->filename);
1620  goto cleanup;
1621  }
1622  }
1623 
1624  if (!msg->env)
1625  msg->env = mutt_env_new();
1626  }
1627 
1628  /* Parse and use an eventual list-post header */
1629  if ((flags & SEND_LIST_REPLY) && cur && cur->env && cur->env->list_post)
1630  {
1631  /* Use any list-post header as a template */
1632  url_parse_mailto(msg->env, NULL, cur->env->list_post);
1633  /* We don't let them set the sender's address. */
1634  mutt_addr_free(&msg->env->from);
1635  }
1636 
1637  if (!(flags & (SEND_KEY | SEND_POSTPONED | SEND_RESEND)))
1638  {
1639  /* When SEND_DRAFT_FILE is set, the caller has already
1640  * created the "parent" body structure.
1641  */
1642  if (!(flags & SEND_DRAFT_FILE))
1643  {
1644  pbody = mutt_body_new();
1645  pbody->next = msg->content; /* don't kill command-line attachments */
1646  msg->content = pbody;
1647 
1648  ctype = mutt_str_strdup(ContentType);
1649  if (!ctype)
1650  ctype = mutt_str_strdup("text/plain");
1651  mutt_parse_content_type(ctype, msg->content);
1652  FREE(&ctype);
1653  msg->content->unlink = true;
1654  msg->content->use_disp = false;
1656 
1657  if (!tempfile)
1658  {
1659  mutt_mktemp(buf, sizeof(buf));
1660  tempfp = mutt_file_fopen(buf, "w+");
1661  msg->content->filename = mutt_str_strdup(buf);
1662  }
1663  else
1664  {
1665  tempfp = mutt_file_fopen(tempfile, "a+");
1666  msg->content->filename = mutt_str_strdup(tempfile);
1667  }
1668  }
1669  else
1670  tempfp = mutt_file_fopen(msg->content->filename, "a+");
1671 
1672  if (!tempfp)
1673  {
1674  mutt_debug(1, "can't create tempfile %s (errno=%d)\n", msg->content->filename, errno);
1675  mutt_perror(msg->content->filename);
1676  goto cleanup;
1677  }
1678  }
1679 
1680  /* this is handled here so that the user can match ~f in send-hook */
1681  if (cur && ReverseName && !(flags & (SEND_POSTPONED | SEND_RESEND)))
1682  {
1683  /* we shouldn't have to worry about freeing `msg->env->from' before
1684  * setting it here since this code will only execute when doing some
1685  * sort of reply. the pointer will only be set when using the -H command
1686  * line option.
1687  *
1688  * We shouldn't have to worry about alias expansion here since we are
1689  * either replying to a real or postponed message, therefore no aliases
1690  * should exist since the user has not had the opportunity to add
1691  * addresses to the list. We just have to ensure the postponed messages
1692  * have their aliases expanded.
1693  */
1694 
1695  if (msg->env->from)
1696  {
1697  mutt_debug(5, "msg->env->from before set_reverse_name: %s\n",
1698  msg->env->from->mailbox);
1699  }
1700  msg->env->from = set_reverse_name(cur->env);
1701  }
1702  if (cur && ReplyWithXorig && !(flags & (SEND_POSTPONED | SEND_RESEND | SEND_FORWARD)))
1703  {
1704  /* We shouldn't have to worry about freeing `msg->env->from' before
1705  * setting it here since this code will only execute when doing some
1706  * sort of reply. The pointer will only be set when using the -H command
1707  * line option.
1708  *
1709  * If there is already a from address recorded in `msg->env->from',
1710  * then it theoretically comes from ReverseName handling, and we don't use
1711  * the `X-Orig-To header'.
1712  */
1713  if (cur->env->x_original_to && !msg->env->from)
1714  {
1715  msg->env->from = mutt_addr_copy(cur->env->x_original_to);
1716  mutt_debug(5, "msg->env->from extracted from X-Original-To: header: %s\n",
1717  msg->env->from->mailbox);
1718  }
1719  }
1720 
1721  if (!(flags & (SEND_POSTPONED | SEND_RESEND)) && !((flags & SEND_DRAFT_FILE) && ResumeDraftFiles))
1722  {
1723  if ((flags & (SEND_REPLY | SEND_FORWARD | SEND_TO_SENDER)) && ctx &&
1724  envelope_defaults(msg->env, ctx, cur, flags) == -1)
1725  {
1726  goto cleanup;
1727  }
1728 
1729  if (Hdrs)
1730  process_user_recips(msg->env);
1731 
1732  /* Expand aliases and remove duplicates/crossrefs */
1734 
1735  if (flags & SEND_REPLY)
1737 
1738 #ifdef USE_NNTP
1739  if ((flags & SEND_NEWS) && ctx && ctx->mailbox->magic == MUTT_NNTP &&
1740  !msg->env->newsgroups)
1741  msg->env->newsgroups =
1742  mutt_str_strdup(((struct NntpMboxData *) ctx->mailbox->mdata)->group);
1743 #endif
1744 
1745  if (!(flags & (SEND_MAILX | SEND_BATCH)) && !(Autoedit && EditHeaders) &&
1746  !((flags & SEND_REPLY) && FastReply))
1747  {
1748  if (edit_envelope(msg->env, flags) == -1)
1749  goto cleanup;
1750  }
1751 
1752  /* the from address must be set here regardless of whether or not
1753  * $use_from is set so that the `~P' (from you) operator in send-hook
1754  * patterns will work. if $use_from is unset, the from address is killed
1755  * after send-hooks are evaluated */
1756 
1757  if (!msg->env->from)
1758  {
1759  msg->env->from = mutt_default_from();
1760  killfrom = true;
1761  }
1762 
1763  if ((flags & SEND_REPLY) && cur)
1764  {
1765  /* change setting based upon message we are replying to */
1767 
1768  /* set the replied flag for the message we are generating so that the
1769  * user can use ~Q in a send-hook to know when reply-hook's are also
1770  * being used.
1771  */
1772  msg->replied = true;
1773  }
1774 
1775  /* change settings based upon recipients */
1776 
1777  mutt_message_hook(NULL, msg, MUTT_SEND_HOOK);
1778 
1779  /* Unset the replied flag from the message we are composing since it is
1780  * no longer required. This is done here because the FCC'd copy of
1781  * this message was erroneously get the 'R'eplied flag when stored in
1782  * a maildir-style mailbox.
1783  */
1784  msg->replied = false;
1785 
1786  if (!(flags & SEND_KEY))
1787  {
1788  if (TextFlowed && msg->content->type == TYPE_TEXT &&
1789  (mutt_str_strcasecmp(msg->content->subtype, "plain") == 0))
1790  {
1791  mutt_param_set(&msg->content->parameter, "format", "flowed");
1792  }
1793  }
1794 
1795  /* $use_from and/or $from might have changed in a send-hook */
1796  if (killfrom)
1797  {
1798  mutt_addr_free(&msg->env->from);
1799  if (UseFrom && !(flags & (SEND_POSTPONED | SEND_RESEND)))
1800  msg->env->from = mutt_default_from();
1801  killfrom = false;
1802  }
1803 
1804  if (Hdrs)
1805  process_user_header(msg->env);
1806 
1807  if (flags & SEND_BATCH)
1808  mutt_file_copy_stream(stdin, tempfp);
1809 
1810  if (SigOnTop && !(flags & (SEND_MAILX | SEND_KEY | SEND_BATCH)) && Editor &&
1811  (mutt_str_strcmp(Editor, "builtin") != 0))
1812  {
1813  append_signature(tempfp);
1814  }
1815 
1816  /* include replies/forwarded messages, unless we are given a template */
1817  if (!tempfile && (ctx || !(flags & (SEND_REPLY | SEND_FORWARD))) &&
1818  generate_body(tempfp, msg, flags, ctx, cur) == -1)
1819  {
1820  goto cleanup;
1821  }
1822 
1823  if (!SigOnTop && !(flags & (SEND_MAILX | SEND_KEY | SEND_BATCH)) &&
1824  Editor && (mutt_str_strcmp(Editor, "builtin") != 0))
1825  {
1826  append_signature(tempfp);
1827  }
1828  }
1829 
1830  /* This hook is even called for postponed messages, and can, e.g., be
1831  * used for setting the editor, the sendmail path, or the
1832  * envelope sender.
1833  */
1834  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1835 
1836  /* wait until now to set the real name portion of our return address so
1837  that $realname can be set in a send-hook */
1838  if (msg->env->from && !msg->env->from->personal && !(flags & (SEND_RESEND | SEND_POSTPONED)))
1840 
1841  if (!(((WithCrypto & APPLICATION_PGP) != 0) && (flags & SEND_KEY)))
1842  mutt_file_fclose(&tempfp);
1843 
1844  if (flags & SEND_MAILX)
1845  {
1846  if (mutt_builtin_editor(msg->content->filename, msg, cur) == -1)
1847  goto cleanup;
1848  }
1849  else if (!(flags & SEND_BATCH))
1850  {
1851  struct stat st;
1852  time_t mtime = mutt_file_decrease_mtime(msg->content->filename, NULL);
1853 
1855 
1856  /* Select whether or not the user's editor should be called now. We
1857  * don't want to do this when:
1858  * 1) we are sending a key/cert
1859  * 2) we are forwarding a message and the user doesn't want to edit it.
1860  * This is controlled by the quadoption $forward_edit. However, if
1861  * both $edit_headers and $autoedit are set, we want to ignore the
1862  * setting of $forward_edit because the user probably needs to add the
1863  * recipients.
1864  */
1865  if (!(flags & SEND_KEY) &&
1866  ((flags & SEND_FORWARD) == 0 || (EditHeaders && Autoedit) ||
1867  query_quadoption(ForwardEdit, _("Edit forwarded message?")) == MUTT_YES))
1868  {
1869  /* If the this isn't a text message, look for a mailcap edit command */
1870  if (mutt_needs_mailcap(msg->content))
1871  {
1872  if (!mutt_edit_attachment(msg->content))
1873  goto cleanup;
1874  }
1875  else if (!Editor || (mutt_str_strcmp("builtin", Editor) == 0))
1876  mutt_builtin_editor(msg->content->filename, msg, cur);
1877  else if (EditHeaders)
1878  {
1879  mutt_env_to_local(msg->env);
1880  mutt_edit_headers(Editor, msg->content->filename, msg, fcc, sizeof(fcc));
1881  mutt_env_to_intl(msg->env, NULL, NULL);
1882  }
1883  else
1884  {
1886  if (stat(msg->content->filename, &st) == 0)
1887  {
1888  if (mtime != st.st_mtime)
1890  }
1891  else
1892  mutt_perror(msg->content->filename);
1893  }
1894 
1895  /* If using format=flowed, perform space stuffing. Avoid stuffing when
1896  * recalling a postponed message where the stuffing was already
1897  * performed. If it has already been performed, the format=flowed
1898  * parameter will be present.
1899  */
1900  if (TextFlowed && msg->content->type == TYPE_TEXT &&
1901  (mutt_str_strcasecmp("plain", msg->content->subtype) == 0))
1902  {
1903  char *p = mutt_param_get(&msg->content->parameter, "format");
1904  if (mutt_str_strcasecmp("flowed", p) != 0)
1905  rfc3676_space_stuff(msg);
1906  }
1907 
1908  mutt_message_hook(NULL, msg, MUTT_SEND2_HOOK);
1909  }
1910 
1911  if (!(flags & (SEND_POSTPONED | SEND_FORWARD | SEND_KEY | SEND_RESEND | SEND_DRAFT_FILE)))
1912  {
1913  if (stat(msg->content->filename, &st) == 0)
1914  {
1915  /* if the file was not modified, bail out now */
1916  if (mtime == st.st_mtime && !msg->content->next &&
1917  query_quadoption(AbortUnmodified, _("Abort unmodified message?")) == MUTT_YES)
1918  {
1919  mutt_message(_("Aborted unmodified message"));
1920  goto cleanup;
1921  }
1922  }
1923  else
1924  mutt_perror(msg->content->filename);
1925  }
1926  }
1927 
1928  /* Set the message security unless:
1929  * 1) crypto support is not enabled (WithCrypto==0)
1930  * 2) pgp: header field was present during message editing with $edit_headers (msg->security != 0)
1931  * 3) we are resending a message
1932  * 4) we are recalling a postponed message (don't override the user's saved settings)
1933  * 5) we are in mailx mode
1934  * 6) we are in batch mode
1935  *
1936  * This is done after allowing the user to edit the message so that security
1937  * settings can be configured with send2-hook and $edit_headers.
1938  */
1939  if ((WithCrypto != 0) && (msg->security == 0) &&
1940  !(flags & (SEND_BATCH | SEND_MAILX | SEND_POSTPONED | SEND_RESEND)))
1941  {
1942  if (CryptAutosign)
1943  msg->security |= SIGN;
1944  if (CryptAutoencrypt)
1945  msg->security |= ENCRYPT;
1946  if (CryptReplyencrypt && cur && (cur->security & ENCRYPT))
1947  msg->security |= ENCRYPT;
1948  if (CryptReplysign && cur && (cur->security & SIGN))
1949  msg->security |= SIGN;
1950  if (CryptReplysignencrypted && cur && (cur->security & ENCRYPT))
1951  msg->security |= SIGN;
1952  if (((WithCrypto & APPLICATION_PGP) != 0) &&
1953  ((msg->security & (ENCRYPT | SIGN)) || CryptOpportunisticEncrypt))
1954  {
1955  if (PgpAutoinline)
1956  msg->security |= INLINE;
1957  if (PgpReplyinline && cur && (cur->security & INLINE))
1958  msg->security |= INLINE;
1959  }
1960 
1961  if (msg->security || CryptOpportunisticEncrypt)
1962  {
1963  /* When replying / forwarding, use the original message's
1964  * crypto system. According to the documentation,
1965  * smime_is_default should be disregarded here.
1966  *
1967  * Problem: At least with forwarding, this doesn't really
1968  * make much sense. Should we have an option to completely
1969  * disable individual mechanisms at run-time?
1970  */
1971  if (cur)
1972  {
1973  if (((WithCrypto & APPLICATION_PGP) != 0) && CryptAutopgp &&
1974  (cur->security & APPLICATION_PGP))
1975  {
1976  msg->security |= APPLICATION_PGP;
1977  }
1978  else if (((WithCrypto & APPLICATION_SMIME) != 0) && CryptAutosmime &&
1979  (cur->security & APPLICATION_SMIME))
1980  {
1981  msg->security |= APPLICATION_SMIME;
1982  }
1983  }
1984 
1985  /* No crypto mechanism selected? Use availability + smime_is_default
1986  * for the decision.
1987  */
1988  if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP)))
1989  {
1990  if (((WithCrypto & APPLICATION_SMIME) != 0) && CryptAutosmime && SmimeIsDefault)
1991  {
1992  msg->security |= APPLICATION_SMIME;
1993  }
1994  else if (((WithCrypto & APPLICATION_PGP) != 0) && CryptAutopgp)
1995  {
1996  msg->security |= APPLICATION_PGP;
1997  }
1998  else if (((WithCrypto & APPLICATION_SMIME) != 0) && CryptAutosmime)
1999  {
2000  msg->security |= APPLICATION_SMIME;
2001  }
2002  }
2003  }
2004 
2005  /* opportunistic encrypt relies on SMIME or PGP already being selected */
2007  {
2008  /* If something has already enabled encryption, e.g. CryptAutoencrypt
2009  * or CryptReplyencrypt, then don't enable opportunistic encrypt for
2010  * the message.
2011  */
2012  if (!(msg->security & ENCRYPT))
2013  {
2014  msg->security |= OPPENCRYPT;
2016  }
2017  }
2018 
2019  /* No permissible mechanisms found. Don't sign or encrypt. */
2020  if (!(msg->security & (APPLICATION_SMIME | APPLICATION_PGP)))
2021  msg->security = 0;
2022  }
2023 
2024  /* Deal with the corner case where the crypto module backend is not available.
2025  * This can happen if configured without pgp/smime and with gpgme, but
2026  * $crypt_use_gpgme is unset.
2027  */
2028  if (msg->security && !crypt_has_module_backend(msg->security))
2029  {
2030  mutt_error(_(
2031  "No crypto backend configured. Disabling message security setting."));
2032  msg->security = 0;
2033  }
2034 
2035  /* specify a default fcc. if we are in batchmode, only save a copy of
2036  * the message if the value of $copy is yes or ask-yes */
2037 
2038  if (!fcc[0] && !(flags & (SEND_POSTPONED_FCC)) && (!(flags & SEND_BATCH) || (Copy & 0x1)))
2039  {
2040  /* set the default FCC */
2041  if (!msg->env->from)
2042  {
2043  msg->env->from = mutt_default_from();
2044  killfrom = true; /* no need to check $use_from because if the user specified
2045  a from address it would have already been set by now */
2046  }
2047  mutt_select_fcc(fcc, sizeof(fcc), msg);
2048  if (killfrom)
2049  {
2050  mutt_addr_free(&msg->env->from);
2051  }
2052  }
2053 
2055 
2056  if (!(flags & (SEND_MAILX | SEND_BATCH)))
2057  {
2058  main_loop:
2059 
2060  fcc_error = false; /* reset value since we may have failed before */
2061  mutt_pretty_mailbox(fcc, sizeof(fcc));
2062  i = mutt_compose_menu(msg, fcc, sizeof(fcc), cur,
2064  if (i == -1)
2065  {
2066 /* abort */
2067 #ifdef USE_NNTP
2068  if (flags & SEND_NEWS)
2069  mutt_message(_("Article not posted"));
2070  else
2071 #endif
2072  mutt_message(_("Mail not sent"));
2073  goto cleanup;
2074  }
2075  else if (i == 1)
2076  {
2077  /* postpone the message until later. */
2078  if (msg->content->next)
2079  msg->content = mutt_make_multipart(msg->content);
2080 
2081  if ((WithCrypto != 0) && PostponeEncrypt && (msg->security & ENCRYPT))
2082  {
2083  char *encrypt_as = NULL;
2084 
2085  if (((WithCrypto & APPLICATION_PGP) != 0) && (msg->security & APPLICATION_PGP))
2086  encrypt_as = PgpDefaultKey;
2087  else if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME))
2088  encrypt_as = SmimeDefaultKey;
2089  if (!(encrypt_as && *encrypt_as))
2090  encrypt_as = PostponeEncryptAs;
2091 
2092  if (encrypt_as && *encrypt_as)
2093  {
2094  int is_signed = msg->security & SIGN;
2095  if (is_signed)
2096  msg->security &= ~SIGN;
2097 
2098  pgpkeylist = mutt_str_strdup(encrypt_as);
2099  if (mutt_protect(msg, pgpkeylist) == -1)
2100  {
2101  if (is_signed)
2102  msg->security |= SIGN;
2103  FREE(&pgpkeylist);
2104  msg->content = mutt_remove_multipart(msg->content);
2105  goto main_loop;
2106  }
2107 
2108  if (is_signed)
2109  msg->security |= SIGN;
2110  FREE(&pgpkeylist);
2111  }
2112  }
2113 
2114  /* make sure the message is written to the right part of a maildir
2115  * postponed folder.
2116  */
2117  msg->read = false;
2118  msg->old = false;
2119 
2120  mutt_encode_descriptions(msg->content, true);
2121  mutt_prepare_envelope(msg->env, false);
2122  mutt_env_to_intl(msg->env, NULL, NULL); /* Handle bad IDNAs the next time. */
2123 
2124  if (!Postponed || mutt_write_fcc(NONULL(Postponed), msg,
2125  (cur && (flags & SEND_REPLY)) ? cur->env->message_id : NULL,
2126  true, fcc, NULL) < 0)
2127  {
2128  msg->content = mutt_remove_multipart(msg->content);
2131  goto main_loop;
2132  }
2134  mutt_message(_("Message postponed"));
2135  rc = 1;
2136  goto cleanup;
2137  }
2138  }
2139 
2140 #ifdef USE_NNTP
2141  if (!(flags & SEND_NEWS))
2142 #endif
2143  if ((mutt_addr_has_recips(msg->env->to) == 0) &&
2144  (mutt_addr_has_recips(msg->env->cc) == 0) &&
2145  (mutt_addr_has_recips(msg->env->bcc) == 0))
2146  {
2147  if (!(flags & SEND_BATCH))
2148  {
2149  mutt_error(_("No recipients specified"));
2150  goto main_loop;
2151  }
2152  else
2153  {
2154  puts(_("No recipients specified"));
2155  goto cleanup;
2156  }
2157  }
2158 
2159  if (mutt_env_to_intl(msg->env, &tag, &err))
2160  {
2161  mutt_error(_("Bad IDN in '%s': '%s'"), tag, err);
2162  FREE(&err);
2163  if (!(flags & SEND_BATCH))
2164  goto main_loop;
2165  else
2166  goto cleanup;
2167  }
2168 
2169  if (!msg->env->subject && !(flags & SEND_BATCH) &&
2170  (i = query_quadoption(AbortNosubject, _("No subject, abort sending?"))) != MUTT_NO)
2171  {
2172  /* if the abort is automatic, print an error message */
2173  if (AbortNosubject == MUTT_YES)
2174  mutt_error(_("No subject specified"));
2175  goto main_loop;
2176  }
2177 #ifdef USE_NNTP
2178  if ((flags & SEND_NEWS) && !msg->env->subject)
2179  {
2180  mutt_error(_("No subject specified"));
2181  goto main_loop;
2182  }
2183 
2184  if ((flags & SEND_NEWS) && !msg->env->newsgroups)
2185  {
2186  mutt_error(_("No newsgroup specified"));
2187  goto main_loop;
2188  }
2189 #endif
2190 
2191  if (!(flags & SEND_BATCH) && (AbortNoattach != MUTT_NO) &&
2192  !msg->content->next && (msg->content->type == TYPE_TEXT) &&
2193  (mutt_str_strcasecmp(msg->content->subtype, "plain") == 0) &&
2195  query_quadoption(AbortNoattach, _("No attachments, cancel sending?")) != MUTT_NO)
2196  {
2197  /* if the abort is automatic, print an error message */
2198  if (AbortNoattach == MUTT_YES)
2199  {
2200  mutt_error(_("Message contains text matching "
2201  "\"$abort_noattach_regex\". Not sending."));
2202  }
2203  goto main_loop;
2204  }
2205 
2206  if (msg->content->next)
2207  msg->content = mutt_make_multipart(msg->content);
2208 
2209  /* Ok, we need to do it this way instead of handling all fcc stuff in
2210  * one place in order to avoid going to main_loop with encoded "env"
2211  * in case of error. Ugh.
2212  */
2213 
2214  mutt_encode_descriptions(msg->content, true);
2215 
2216  /* Make sure that clear_content and free_clear_content are
2217  * properly initialized -- we may visit this particular place in
2218  * the code multiple times, including after a failed call to
2219  * mutt_protect().
2220  */
2221 
2222  clear_content = NULL;
2223  free_clear_content = false;
2224 
2225  if (WithCrypto)
2226  {
2227  if (msg->security & (ENCRYPT | SIGN))
2228  {
2229  /* save the decrypted attachments */
2230  clear_content = msg->content;
2231 
2232  if ((crypt_get_keys(msg, &pgpkeylist, 0) == -1) || mutt_protect(msg, pgpkeylist) == -1)
2233  {
2234  msg->content = mutt_remove_multipart(msg->content);
2235 
2236  FREE(&pgpkeylist);
2237 
2239  goto main_loop;
2240  }
2241  mutt_encode_descriptions(msg->content, false);
2242  }
2243 
2244  /* at this point, msg->content is one of the following three things:
2245  * - multipart/signed. In this case, clear_content is a child.
2246  * - multipart/encrypted. In this case, clear_content exists
2247  * independently
2248  * - application/pgp. In this case, clear_content exists independently.
2249  * - something else. In this case, it's the same as clear_content.
2250  */
2251 
2252  /* This is ugly -- lack of "reporting back" from mutt_protect(). */
2253 
2254  if (clear_content && (msg->content != clear_content) && (msg->content->parts != clear_content))
2255  free_clear_content = true;
2256  }
2257 
2258  if (!OptNoCurses && !(flags & SEND_MAILX))
2259  mutt_message(_("Sending message..."));
2260 
2261  mutt_prepare_envelope(msg->env, true);
2262 
2263  /* save a copy of the message, if necessary. */
2264 
2265  mutt_expand_path(fcc, sizeof(fcc));
2266 
2267  /* Don't save a copy when we are in batch-mode, and the FCC
2268  * folder is on an IMAP server: This would involve possibly lots
2269  * of user interaction, which is not available in batch mode.
2270  *
2271  * Note: A patch to fix the problems with the use of IMAP servers
2272  * from non-curses mode is available from Brendan Cully. However,
2273  * I'd like to think a bit more about this before including it.
2274  */
2275 
2276 #ifdef USE_IMAP
2277  if ((flags & SEND_BATCH) && fcc[0] && (imap_path_probe(fcc, NULL) == MUTT_IMAP))
2278  fcc[0] = '\0';
2279 #endif
2280 
2281  if (*fcc && (mutt_str_strcmp("/dev/null", fcc) != 0))
2282  {
2283  struct Body *tmpbody = msg->content;
2284  struct Body *save_sig = NULL;
2285  struct Body *save_parts = NULL;
2286 
2287  if ((WithCrypto != 0) && (msg->security & (ENCRYPT | SIGN)) && FccClear)
2288  msg->content = clear_content;
2289 
2290  /* check to see if the user wants copies of all attachments */
2291  if (msg->content->type == TYPE_MULTIPART)
2292  {
2293  if ((WithCrypto != 0) && (msg->security & (ENCRYPT | SIGN)) &&
2294  ((mutt_str_strcmp(msg->content->subtype, "encrypted") == 0) ||
2295  (mutt_str_strcmp(msg->content->subtype, "signed") == 0)))
2296  {
2297  if (clear_content->type == TYPE_MULTIPART &&
2298  query_quadoption(FccAttach, _("Save attachments in Fcc?")) == MUTT_NO)
2299  {
2300  if (!(msg->security & ENCRYPT) && (msg->security & SIGN))
2301  {
2302  /* save initial signature and attachments */
2303  save_sig = msg->content->parts->next;
2304  save_parts = clear_content->parts->next;
2305  }
2306 
2307  /* this means writing only the main part */
2308  msg->content = clear_content->parts;
2309 
2310  if (mutt_protect(msg, pgpkeylist) == -1)
2311  {
2312  /* we can't do much about it at this point, so
2313  * fallback to saving the whole thing to fcc
2314  */
2315  msg->content = tmpbody;
2316  save_sig = NULL;
2317  goto full_fcc;
2318  }
2319 
2320  save_content = msg->content;
2321  }
2322  }
2323  else
2324  {
2325  if (query_quadoption(FccAttach, _("Save attachments in Fcc?")) == MUTT_NO)
2326  msg->content = msg->content->parts;
2327  }
2328  }
2329 
2330  full_fcc:
2331  if (msg->content)
2332  {
2333  /* update received time so that when storing to a mbox-style folder
2334  * the From_ line contains the current time instead of when the
2335  * message was first postponed.
2336  */
2337  msg->received = time(NULL);
2338  if (mutt_write_multiple_fcc(fcc, msg, NULL, false, NULL, &finalpath) == -1)
2339  {
2340  /* Error writing FCC, we should abort sending. */
2341  fcc_error = true;
2342  }
2343  }
2344 
2345  msg->content = tmpbody;
2346 
2347  if ((WithCrypto != 0) && save_sig)
2348  {
2349  /* cleanup the second signature structures */
2350  if (save_content->parts)
2351  {
2352  mutt_body_free(&save_content->parts->next);
2353  save_content->parts = NULL;
2354  }
2355  mutt_body_free(&save_content);
2356 
2357  /* restore old signature and attachments */
2358  msg->content->parts->next = save_sig;
2359  msg->content->parts->parts->next = save_parts;
2360  }
2361  else if ((WithCrypto != 0) && save_content)
2362  {
2363  /* destroy the new encrypted body. */
2364  mutt_body_free(&save_content);
2365  }
2366  }
2367 
2368  /* Don't attempt to send the message if the FCC failed. Just pretend
2369  * the send failed as well so we give the user a chance to fix the
2370  * error.
2371  */
2372  if (fcc_error || (i = send_message(msg)) < 0)
2373  {
2374  if (!(flags & SEND_BATCH))
2375  {
2376  if (!WithCrypto)
2377  ;
2378  else if ((msg->security & ENCRYPT) ||
2379  ((msg->security & SIGN) && msg->content->type == TYPE_APPLICATION))
2380  {
2381  mutt_body_free(&msg->content); /* destroy PGP data */
2382  msg->content = clear_content; /* restore clear text. */
2383  }
2384  else if ((msg->security & SIGN) && msg->content->type == TYPE_MULTIPART)
2385  {
2386  mutt_body_free(&msg->content->parts->next); /* destroy sig */
2387  msg->content = mutt_remove_multipart(msg->content);
2388  }
2389 
2390  msg->content = mutt_remove_multipart(msg->content);
2393  FREE(&finalpath);
2394  goto main_loop;
2395  }
2396  else
2397  {
2398  puts(_("Could not send the message"));
2399  goto cleanup;
2400  }
2401  }
2402  else if (!OptNoCurses && !(flags & SEND_MAILX))
2403  {
2404  mutt_message(i != 0 ? _("Sending in background") :
2405  (flags & SEND_NEWS) ? _("Article posted") : /* USE_NNTP */
2406  _("Mail sent"));
2407 #ifdef USE_NOTMUCH
2408  if (NmRecord)
2409  nm_record_message(ctx->mailbox, finalpath, cur);
2410 #endif
2411  }
2412 
2413  if ((WithCrypto != 0) && (msg->security & ENCRYPT))
2414  FREE(&pgpkeylist);
2415 
2416  if ((WithCrypto != 0) && free_clear_content)
2417  mutt_body_free(&clear_content);
2418 
2419  /* set 'replied' flag only if the user didn't change/remove
2420  In-Reply-To: and References: headers during edit */
2421  if (flags & SEND_REPLY)
2422  {
2423  if (cur && ctx)
2424  mutt_set_flag(ctx->mailbox, cur, MUTT_REPLIED, is_reply(cur, msg));
2425  else if (!(flags & SEND_POSTPONED) && ctx && ctx->mailbox && ctx->mailbox->msg_tagged)
2426  {
2427  for (i = 0; i < ctx->mailbox->msg_count; i++)
2428  {
2429  if (message_is_tagged(ctx, i))
2430  {
2431  mutt_set_flag(ctx->mailbox, ctx->mailbox->hdrs[i], MUTT_REPLIED,
2432  is_reply(ctx->mailbox->hdrs[i], msg));
2433  }
2434  }
2435  }
2436  }
2437 
2438  rc = 0;
2439 
2440 cleanup:
2441 
2442  if (flags & SEND_POSTPONED)
2443  {
2444  if (WithCrypto & APPLICATION_PGP)
2445  {
2446  FREE(&PgpSignAs);
2447  PgpSignAs = pgp_signas;
2448  }
2449  if (WithCrypto & APPLICATION_SMIME)
2450  {
2451  FREE(&SmimeSignAs);
2452  SmimeSignAs = smime_signas;
2453  }
2454  }
2455 
2456  mutt_file_fclose(&tempfp);
2457  if (!(flags & SEND_NO_FREE_HEADER))
2458  mutt_email_free(&msg);
2459 
2460  FREE(&finalpath);
2461  return rc;
2462 }
#define MUTT_SEND_HOOK
Definition: hook.h:43
void mutt_fix_reply_recipients(struct Envelope *env)
Remove duplicate recipients.
Definition: send.c:825
unsigned char FccAttach
Config: Save send message with all their attachments.
Definition: send.c:100
#define SIGN
Definition: ncrypt.h:120
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
#define NONULL(x)
Definition: string2.h:39
int msg_count
total number of messages
Definition: mailbox.h:86
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1715
#define SEND_POSTPONED_FCC
used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present ...
Definition: send.h:91
#define SEND_TO_SENDER
Definition: send.h:94
static int envelope_defaults(struct Envelope *env, struct Context *ctx, struct Email *cur, int flags)
Fill in some defaults for a new email.
Definition: send.c:948
#define mutt_perror(...)
Definition: logging.h:89
static void fix_end_of_file(const char *data)
Ensure a file ends with a linefeed.
Definition: send.c:1407
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2479
int mutt_builtin_editor(const char *path, struct Email *msg, struct Email *cur)
Show the user the built-in editor.
Definition: edit.c:400
static bool search_attach_keyword(char *filename)
Search an email for &#39;attachment&#39; keywords.
Definition: send.c:1489
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: magic.h:41
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:606
User aborted the question (with Ctrl-G)
Definition: quad.h:37
static int send_message(struct Email *msg)
Send an email.
Definition: send.c:1301
#define mutt_message(...)
Definition: logging.h:87
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
struct Address * to
Definition: envelope.h:36
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
#define SEND_DRAFT_FILE
Used by the -H flag.
Definition: send.h:93
WHERE char * Editor
Config: External command to use as an email editor.
Definition: globals.h:110
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:311
static void process_user_header(struct Envelope *env)
Process the user headers.
Definition: send.c:450
#define SEND_FORWARD
Definition: send.h:85
struct Body * content
list of MIME parts
Definition: email.h:92
int mutt_edit_attachment(struct Body *a)
Edit an attachment.
Definition: mutt_attach.c:250
WHERE char * Postponed
Config: Folder to store postponed messages.
Definition: globals.h:137
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:57
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:45
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
char * mailbox
mailbox and host address
Definition: address.h:35
bool crypt_has_module_backend(int type)
Is there a crypto backend for a given type?
Definition: cryptglue.c:152
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
bool SigOnTop
Config: Insert the signature before the quoted text.
Definition: send.c:126
#define LONG_STRING
Definition: string2.h:36
unsigned char ForwardEdit
Config: Automatically start the editor when forwarding a message.
Definition: send.c:105
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:235
#define SEND_POSTPONED
Definition: send.h:86
void mutt_parse_content_type(char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:393
struct Email ** hdrs
Definition: mailbox.h:93
void mutt_select_fcc(char *path, size_t pathlen, struct Email *e)
Select the FCC path for an email.
Definition: hook.c:557
int url_parse_mailto(struct Envelope *e, char **body, const char *src)
Parse a mailto:// url.
Definition: mutt_url.c:47
static void append_signature(FILE *f)
Append a signature to an email.
Definition: send.c:133
The body of an email.
Definition: body.h:33
void mutt_prepare_envelope(struct Envelope *env, bool final)
Prepare an email header.
Definition: sendlib.c:2883
unsigned int disposition
content-disposition
Definition: body.h:69
WHERE bool TextFlowed
Config: Generate &#39;format=flowed&#39; messages.
Definition: globals.h:259
WHERE char * SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: globals.h:171
int nm_record_message(struct Mailbox *m, char *path, struct Email *e)
Add a message to the Notmuch database.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:157
bool read
Definition: email.h:49
#define SEND_MAILX
Definition: send.h:88
static int generate_body(FILE *tempfp, struct Email *msg, int flags, struct Context *ctx, struct Email *cur)
Create a new email body.
Definition: send.c:1042
static struct Address * set_reverse_name(struct Envelope *env)
Try to set the &#39;from&#39; field from the recipients.
Definition: send.c:1231
char * message_id
Definition: envelope.h:47
bool CryptReplysign
Config: Sign replies to signed messages.
Definition: send.c:96
struct Mailbox * mailbox
Definition: context.h:50
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:42
bool old
Definition: email.h:48
#define INLINE
Definition: ncrypt.h:126
bool UseFrom
Config: Set the &#39;From&#39; header for outgoing mail.
Definition: send.c:127
enum MailboxType magic
mailbox type
Definition: mailbox.h:99
struct Address * mutt_addr_copy(struct Address *addr)
Copy the real address.
Definition: address.c:712
void mutt_update_encoding(struct Body *a)
Update the encoding type.
Definition: sendlib.c:1428
static void process_user_recips(struct Envelope *env)
Process the user headers.
Definition: send.c:423
struct Envelope * env
envelope information
Definition: email.h:91
static void decode_descriptions(struct Body *b)
rfc2047 decode them in case of an error
Definition: send.c:1390
int crypt_get_keys(struct Email *msg, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:949
bool PgpReplyinline
Config: Reply using old-style inline PGP messages (not recommended)
Definition: send.c:114
#define SEND_LIST_REPLY
Definition: send.h:84
struct Address * from
Definition: envelope.h:35
void * mdata
driver specific data
Definition: mailbox.h:130
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:40
#define OPPENCRYPT
Definition: ncrypt.h:127
WHERE bool SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:272
bool CryptReplyencrypt
Config: Encrypt replies to encrypted messages.
Definition: send.c:95
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
struct Body * mutt_make_multipart(struct Body *b)
Create a multipart email.
Definition: sendlib.c:1689
#define SEND_KEY
Definition: send.h:89
struct Address * x_original_to
Definition: envelope.h:42
Messages that have been replied to.
Definition: mutt.h:115
WHERE char * PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:168
bool ReplyWithXorig
Config: Create &#39;From&#39; header from &#39;X-Original-To&#39; header.
Definition: send.c:121
char * subtype
content-type subtype
Definition: body.h:36
WHERE char * SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:172
void crypt_opportunistic_encrypt(struct Email *msg)
Can all recipients be determined.
Definition: crypt.c:1021
#define ENCRYPT
Definition: ncrypt.h:119
#define SEND_RESEND
Definition: send.h:90
struct Address * bcc
Definition: envelope.h:38
void mutt_unprepare_envelope(struct Envelope *env)
Undo the encodings of mutt_prepare_envelope()
Definition: sendlib.c:2935
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1266
int mutt_protect(struct Email *msg, char *keylist)
Encrypt and/or sign a message.
Definition: crypt.c:168
bool CryptAutoencrypt
Config: Automatically PGP encrypt all outgoing mail.
Definition: send.c:91
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
int mutt_file_copy_stream(FILE *fin, FILE *fout)
Copy the contents of one file into another.
Definition: file.c:264
static int is_reply(struct Email *reply, struct Email *orig)
Is one email a reply to another?
Definition: send.c:1471
#define PATH_MAX
Definition: mutt.h:46
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
int mutt_compose_menu(struct Email *msg, char *fcc, size_t fcclen, struct Email *cur, int flags)
Allow the user to edit the message envelope.
Definition: compose.c:889
int query_quadoption(int opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3227
WHERE char * Realname
Config: Real name of the user.
Definition: globals.h:141
void mutt_encode_descriptions(struct Body *b, bool recurse)
rfc2047 encode the content-descriptions
Definition: send.c:1373
unsigned char Recall
Config: Recall postponed mesaages when asked to compose a message.
Definition: send.c:118
Type: &#39;text/*&#39;.
Definition: mime.h:38
time_t mutt_file_decrease_mtime(const char *f, struct stat *st)
Decrease a file&#39;s modification time by 1 second.
Definition: file.c:884
bool Hdrs
Config: Add custom headers to outgoing mail.
Definition: send.c:108
bool CryptAutosign
Config: Automatically PGP sign all outgoing mail.
Definition: send.c:93
void mutt_param_set(struct ParameterList *p, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:107
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
unsigned char AbortNosubject
Config: Abort creating the email if subject is missing.
Definition: send.c:86
bool message_is_tagged(struct Context *ctx, int index)
Is a message in the index tagged (and within limit)
Definition: curs_lib.c:1236
#define mutt_set_flag(a, b, c, d)
Definition: protos.h:54
int msg_tagged
how many messages are tagged?
Definition: mailbox.h:91
#define SEND_NEWS
Definition: send.h:95
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:192
WHERE bool PgpAutoinline
Config: Use old-style inline PGP messages (not recommended)
Definition: globals.h:276
#define SEND_REPLY
Definition: send.h:82
NNTP-specific Mailbox data -.
Definition: nntp.h:139
unsigned char AbortUnmodified
Config: Abort the sending if the message hasn&#39;t been edited.
Definition: send.c:87
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:92
void rfc3676_space_stuff(struct Email *e)
Perform required RFC3676 space stuffing.
Definition: rfc3676.c:400
unsigned int type
content-type primary type
Definition: body.h:67
char * list_post
this stores a mailto URL, or nothing
Definition: envelope.h:43
#define APPLICATION_PGP
Definition: ncrypt.h:129
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
char * personal
real name of address
Definition: address.h:34
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:86
void mutt_env_to_local(struct Envelope *env)
Convert an Envelope&#39;s Address fields to local format.
Definition: envelope.c:200
bool PostponeEncrypt
Config: Self-encrypt postponed messages.
Definition: send.c:116
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:56
char * subject
Definition: envelope.h:44
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
WHERE char * PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: globals.h:167
char * newsgroups
Definition: envelope.h:53
#define MUTT_SEND2_HOOK
Definition: hook.h:52
WHERE bool CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:271
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:70
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
void mutt_edit_headers(const char *editor, const char *body, struct Email *msg, char *fcc, size_t fcclen)
Let the user edit the message header and body.
Definition: mutt_header.c:186
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define mutt_error(...)
Definition: logging.h:88
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:401
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:71
bool replied
Definition: email.h:52
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
#define MUTT_REPLY_HOOK
Definition: hook.h:51
bool CryptAutosmime
Config: Allow automatic SMIME functions.
Definition: send.c:94
#define FREE(x)
Definition: memory.h:46
#define MUTT_COMPOSE_NOFREEHEADER
Definition: compose.h:36
static int edit_envelope(struct Envelope *en, int flags)
Edit Envelope fields.
Definition: send.c:314
bool NmRecord
Config: (notmuch) If the &#39;record&#39; mailbox (sent mail) should be indexed.
Definition: send.c:113
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
bool FccClear
Config: Save sent messages unencrypted and unsigned.
Definition: send.c:101
WHERE bool OptNewsSend
(pseudo) used to change behavior when posting
Definition: options.h:43
void mutt_addr_free(struct Address **p)
Free a list of Addresses.
Definition: address.c:446
bool CryptReplysignencrypted
Config: Sign replies to encrypted messages.
Definition: send.c:97
WHERE bool ResumeDraftFiles
Config: Process draft files like postponed messages.
Definition: globals.h:249
WHERE bool Autoedit
Config: Skip the initial compose menu and edit the email.
Definition: globals.h:203
void mutt_message_hook(struct Mailbox *m, struct Email *e, int type)
Perform a message hook.
Definition: hook.c:438
bool FastReply
Config: Don&#39;t prompt for the recipients and subject when replying/forwarding.
Definition: send.c:99
Content is inline.
Definition: mime.h:62
WHERE unsigned char Copy
Config: Save outgoing emails to $record.
Definition: globals.h:186
struct ParameterList parameter
parameters of the content-type
Definition: body.h:38
#define WithCrypto
Definition: ncrypt.h:154
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:612
WHERE bool EditHeaders
Config: Let the user edit the email headers whilst editing an email.
Definition: globals.h:212
Type: &#39;application/*&#39;.
Definition: mime.h:33
unsigned char AbortNoattach
Config: Abort sending the email if attachments are missing.
Definition: send.c:84
bool CryptAutopgp
Config: Allow automatic PGP functions.
Definition: send.c:92
char * PostponeEncryptAs
Config: Fallback encryption key for postponed messages.
Definition: send.c:117
time_t received
time when the message was placed in the mailbox
Definition: email.h:84
#define SEND_BATCH
Definition: send.h:87
struct Address * cc
Definition: envelope.h:37
int mutt_addr_has_recips(struct Address *a)
Count the number of Addresses with valid recipients.
Definition: address.c:864
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:287
#define APPLICATION_SMIME
Definition: ncrypt.h:130
ContentType
Content-Type.
Definition: mime.h:29
bool ReverseName
Config: Set the &#39;From&#39; from the address the email was sent to.
Definition: send.c:122
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

+ Here is the caller graph for this function:

Variable Documentation

unsigned char AbortNoattach

Config: Abort sending the email if attachments are missing.

Definition at line 84 of file send.c.

struct Regex* AbortNoattachRegex

Config: Regex to match text indicating attachments are expected.

Definition at line 85 of file send.c.

unsigned char AbortNosubject

Config: Abort creating the email if subject is missing.

Definition at line 86 of file send.c.

unsigned char AbortUnmodified

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

Definition at line 87 of file send.c.

bool AskFollowUp

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

Definition at line 88 of file send.c.

bool AskXCommentTo

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

Definition at line 89 of file send.c.

char* ContentType

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

Definition at line 90 of file send.c.

bool CryptAutoencrypt

Config: Automatically PGP encrypt all outgoing mail.

Definition at line 91 of file send.c.

bool CryptAutopgp

Config: Allow automatic PGP functions.

Definition at line 92 of file send.c.

bool CryptAutosign

Config: Automatically PGP sign all outgoing mail.

Definition at line 93 of file send.c.

bool CryptAutosmime

Config: Allow automatic SMIME functions.

Definition at line 94 of file send.c.

bool CryptReplyencrypt

Config: Encrypt replies to encrypted messages.

Definition at line 95 of file send.c.

bool CryptReplysign

Config: Sign replies to signed messages.

Definition at line 96 of file send.c.

bool CryptReplysignencrypted

Config: Sign replies to encrypted messages.

Definition at line 97 of file send.c.

char* EmptySubject

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

Definition at line 98 of file send.c.

bool FastReply

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

Definition at line 99 of file send.c.

unsigned char FccAttach

Config: Save send message with all their attachments.

Definition at line 100 of file send.c.

bool FccClear

Config: Save sent messages unencrypted and unsigned.

Definition at line 101 of file send.c.

bool FollowupTo

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

Definition at line 102 of file send.c.

char* ForwardAttributionIntro

Config: Prefix message for forwarded messages.

Definition at line 103 of file send.c.

char* ForwardAttributionTrailer

Config: Suffix message for forwarded messages.

Definition at line 104 of file send.c.

unsigned char ForwardEdit

Config: Automatically start the editor when forwarding a message.

Definition at line 105 of file send.c.

char* ForwardFormat

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

Definition at line 106 of file send.c.

bool ForwardReferences

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

Definition at line 107 of file send.c.

bool Hdrs

Config: Add custom headers to outgoing mail.

Definition at line 108 of file send.c.

unsigned char HonorFollowupTo

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

Definition at line 109 of file send.c.

bool IgnoreListReplyTo

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

Definition at line 110 of file send.c.

unsigned char Include

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

Definition at line 111 of file send.c.

bool Metoo

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

Definition at line 112 of file send.c.

bool NmRecord

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

Definition at line 113 of file send.c.

bool PgpReplyinline

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

Definition at line 114 of file send.c.

char* PostIndentString

Config: Suffix message to add after reply text.

Definition at line 115 of file send.c.

bool PostponeEncrypt

Config: Self-encrypt postponed messages.

Definition at line 116 of file send.c.

char* PostponeEncryptAs

Config: Fallback encryption key for postponed messages.

Definition at line 117 of file send.c.

unsigned char Recall

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

Definition at line 118 of file send.c.

bool ReplySelf

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

Definition at line 119 of file send.c.

unsigned char ReplyTo

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

Definition at line 120 of file send.c.

bool ReplyWithXorig

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

Definition at line 121 of file send.c.

bool ReverseName

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

Definition at line 122 of file send.c.

bool ReverseRealname

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

Definition at line 123 of file send.c.

bool SigDashes

Config: Insert '– ' before the signature.

Definition at line 124 of file send.c.

char* Signature

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

Definition at line 125 of file send.c.

bool SigOnTop

Config: Insert the signature before the quoted text.

Definition at line 126 of file send.c.

bool UseFrom

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

Definition at line 127 of file send.c.