*
* @authors
* Copyright (C) 1996-2002,2009-2012 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 2019 Pietro Cerutti <gahr@gahr.ch>
*
* @copyright
* This program is free software: you can redistribute it and/or modify it under
#include <errno.h>
#include <fcntl.h>
#include <iconv.h>
-#include <inttypes.h>
+#include <inttypes.h> // IWYU pragma: keep
#include <limits.h>
#include <signal.h>
#include <stdbool.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
-#include "config/lib.h"
+#include "address/lib.h"
#include "email/lib.h"
+#include "core/lib.h"
#include "mutt.h"
#include "sendlib.h"
#include "context.h"
#include "copy.h"
#include "curs_lib.h"
#include "filter.h"
+#include "format_flags.h"
#include "globals.h"
#include "handler.h"
-#include "hook.h"
-#include "mailbox.h"
+#include "mutt_mailbox.h"
#include "mutt_parse.h"
#include "mutt_window.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "options.h"
+#include "pager.h"
#include "send.h"
#include "smtp.h"
#include "state.h"
#else
#define EX_OK 0
#endif
+#ifdef USE_AUTOCRYPT
+#include "autocrypt/autocrypt.h"
+#endif
/* These Config Variables are only used in sendlib.c */
bool C_Allow8bit; ///< Config: Allow 8-bit messages, don't use quoted-printable or base64
bool C_UserAgent; ///< Config: Add a 'User-Agent' head to outgoing mail
short C_WrapHeaders; ///< Config: Width to wrap headers in outgoing messages
+#define MUTT_RANDTAG_LEN 16
+
+/**
+ * struct B64Context - Cursor for the Base64 conversion
+ */
+struct B64Context
+{
+ char buffer[3];
+ short size;
+ short linelen;
+};
+
+/**
+ * struct ContentState - Info about the body of an email
+ */
+struct ContentState
+{
+ bool from;
+ int whitespace;
+ bool dot;
+ int linelen;
+ bool was_cr;
+};
+
+/**
+ * The next array/enum pair is used to to keep track of user headers that
+ * override pre-defined headers NeoMutt would emit. Keep the array sorted and
+ * in sync with the enum.
+ */
+static const char *const userhdrs_override_headers[] = {
+ "content-type:",
+ "user-agent:",
+};
+
+enum UserHdrsOverrideIdx
+{
+ USERHDRS_OVERRIDE_CONTENT_TYPE,
+ USERHDRS_OVERRIDE_USER_AGENT,
+};
+
+struct UserHdrsOverride
+{
+ bool is_overridden[mutt_array_size(userhdrs_override_headers)];
+};
+
/**
* encode_quoted - Encode text as quoted printable
* @param fc Cursor for converting a file's encoding
{
/* If the last character is "quoted", then be sure to move all three
* characters to the next line. Otherwise, just move the last
- * character...
- */
+ * character... */
if (line[linelen - 3] == '=')
{
line[linelen - 3] = 0;
else if ((c != 9) && ((c < 32) || (c > 126) || (c == '=')))
{
/* Check to make sure there is enough room for the quoted character.
- * If not, wrap to the next line.
- */
+ * If not, wrap to the next line. */
if (linelen > 73)
{
line[linelen++] = '=';
else
{
/* Don't worry about wrapping the line here. That will happen during
- * the next iteration when I'll also know what the next character is.
- */
+ * the next iteration when I'll also know what the next character is. */
line[linelen++] = c;
}
}
}
}
-/**
- * struct B64Context - Cursor for the Base64 conversion
- */
-struct B64Context
-{
- char buffer[3];
- short size;
- short linelen;
-};
-
/**
* b64_init - Set up the base64 conversion
* @param bctx Cursor for the base64 conversion
char encoded[11];
size_t ret;
- if (!bctx->size)
+ if (bctx->size == 0)
return;
if (bctx->linelen >= 72)
*/
int mutt_write_mime_header(struct Body *a, FILE *fp)
{
+ if (!a || !fp)
+ return -1;
+
+ int len;
+ int tmplen;
+ char buf[256] = { 0 };
+
fprintf(fp, "Content-Type: %s/%s", TYPE(a), a->subtype);
if (!TAILQ_EMPTY(&a->parameter))
{
- size_t len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
+ len = 25 + mutt_str_strlen(a->subtype); /* approximate len. of content-type */
struct Parameter *np = NULL;
TAILQ_FOREACH(np, &a->parameter, entries)
{
- char *tmp = NULL;
-
- if (!np->value)
+ if (!np->attribute || !np->value)
continue;
- fputc(';', fp);
-
- char buf[256];
- buf[0] = 0;
- tmp = mutt_str_strdup(np->value);
- const int encode = rfc2231_encode_string(&tmp);
- mutt_addr_cat(buf, sizeof(buf), tmp, MimeSpecials);
-
- /* Dirty hack to make messages readable by Outlook Express
- * for the Mac: force quotes around the boundary parameter
- * even when they aren't needed.
- */
-
- if ((mutt_str_strcasecmp(np->attribute, "boundary") == 0) && (strcmp(buf, tmp) == 0))
+ struct ParameterList pl_conts = rfc2231_encode_string(np->attribute, np->value);
+ struct Parameter *cont = NULL;
+ TAILQ_FOREACH(cont, &pl_conts, entries)
{
- snprintf(buf, sizeof(buf), "\"%s\"", tmp);
- }
+ fputc(';', fp);
- FREE(&tmp);
+ buf[0] = 0;
+ mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
- const int tmplen = mutt_str_strlen(buf) + mutt_str_strlen(np->attribute) + 1;
+ /* Dirty hack to make messages readable by Outlook Express
+ * for the Mac: force quotes around the boundary parameter
+ * even when they aren't needed.
+ */
+ if (!mutt_str_strcasecmp(cont->attribute, "boundary") &&
+ !mutt_str_strcmp(buf, cont->value))
+ snprintf(buf, sizeof(buf), "\"%s\"", cont->value);
- if (len + tmplen + 2 > 76)
- {
- fputs("\n\t", fp);
- len = tmplen + 8;
- }
- else
- {
- fputc(' ', fp);
- len += tmplen + 1;
+ tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
+ if (len + tmplen + 2 > 76)
+ {
+ fputs("\n\t", fp);
+ len = tmplen + 1;
+ }
+ else
+ {
+ fputc(' ', fp);
+ len += tmplen + 1;
+ }
+
+ fprintf(fp, "%s=%s", cont->attribute, buf);
}
- fprintf(fp, "%s%s=%s", np->attribute, encode ? "*" : "", buf);
+ mutt_param_free(&pl_conts);
}
}
if (a->disposition < sizeof(dispstr) / sizeof(char *))
{
fprintf(fp, "Content-Disposition: %s", dispstr[a->disposition]);
+ len = 21 + mutt_str_strlen(dispstr[a->disposition]);
if (a->use_disp && (a->disposition != DISP_INLINE))
{
if (fn)
{
- char *tmp = NULL;
-
/* Strip off the leading path... */
char *t = strrchr(fn, '/');
if (t)
else
t = fn;
- char buf[256];
- buf[0] = 0;
- tmp = mutt_str_strdup(t);
- const int encode = rfc2231_encode_string(&tmp);
- mutt_addr_cat(buf, sizeof(buf), tmp, MimeSpecials);
- FREE(&tmp);
- fprintf(fp, "; filename%s=%s", encode ? "*" : "", buf);
+ struct ParameterList pl_conts = rfc2231_encode_string("filename", t);
+ struct Parameter *cont = NULL;
+ TAILQ_FOREACH(cont, &pl_conts, entries)
+ {
+ fputc(';', fp);
+ buf[0] = 0;
+ mutt_addr_cat(buf, sizeof(buf), cont->value, MimeSpecials);
+
+ tmplen = mutt_str_strlen(buf) + mutt_str_strlen(cont->attribute) + 1;
+ if (len + tmplen + 2 > 76)
+ {
+ fputs("\n\t", fp);
+ len = tmplen + 1;
+ }
+ else
+ {
+ fputc(' ', fp);
+ len += tmplen + 1;
+ }
+
+ fprintf(fp, "%s=%s", cont->attribute, buf);
+ }
+
+ mutt_param_free(&pl_conts);
}
}
if (a->encoding != ENC_7BIT)
fprintf(fp, "Content-Transfer-Encoding: %s\n", ENCODING(a->encoding));
- if (C_CryptProtectedHeadersWrite && a->mime_headers)
+ if ((C_CryptProtectedHeadersWrite
+#ifdef USE_AUTOCRYPT
+ || C_Autocrypt
+#endif
+ ) &&
+ a->mime_headers)
+ {
mutt_rfc822_write_header(fp, a->mime_headers, NULL, MUTT_WRITE_HEADER_MIME, false, false);
+ }
/* Do NOT add the terminator here!!! */
return ferror(fp) ? -1 : 0;
/* This is pretty gross, but it's the best solution for now... */
if (((WithCrypto & APPLICATION_PGP) != 0) && (a->type == TYPE_APPLICATION) &&
- (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0))
+ (mutt_str_strcmp(a->subtype, "pgp-encrypted") == 0) && !a->filename)
{
fputs("Version: 1\n", fp);
return 0;
/**
* mutt_generate_boundary - Create a unique boundary id for a MIME part
- * @param parm MIME part
+ * @param pl MIME part
*/
-void mutt_generate_boundary(struct ParameterList *parm)
+void mutt_generate_boundary(struct ParameterList *pl)
{
char rs[MUTT_RANDTAG_LEN + 1];
mutt_rand_base32(rs, sizeof(rs) - 1);
rs[MUTT_RANDTAG_LEN] = 0;
- mutt_param_set(parm, "boundary", rs);
+ mutt_param_set(pl, "boundary", rs);
}
-/**
- * struct ContentState - Info about the body of an email
- */
-struct ContentState
-{
- bool from;
- int whitespace;
- bool dot;
- int linelen;
- bool was_cr;
-};
-
/**
* update_content_info - Cache some info about an email
* @param info Info about an Attachment
if (was_cr)
{
was_cr = false;
- if (ch != '\n')
- {
- info->binary = true;
- }
- else
+ if (ch == '\n')
{
if (whitespace)
info->space = true;
linelen = 0;
continue;
}
+
+ info->binary = true;
}
linelen++;
* in.
*/
static size_t convert_file_to(FILE *fp, const char *fromcode, int ncodes,
- const char **tocodes, int *tocode, struct Content *info)
+ char const *const *tocodes, int *tocode, struct Content *info)
{
char bufi[256], bufu[512], bufo[4 * sizeof(bufi)];
size_t ret;
const char *ib = bufi;
char *ob = bufu;
size_t obl = sizeof(bufu);
- n = iconv(cd1, (ICONV_CONST char **) (ibl ? &ib : 0), &ibl, &ob, &obl);
+ n = iconv(cd1, (ICONV_CONST char **) ((ibl != 0) ? &ib : 0), &ibl, &ob, &obl);
/* assert(n == (size_t)(-1) || !n); */
if ((n == (size_t)(-1)) && (((errno != EINVAL) && (errno != E2BIG)) || (ib == bufi)))
{
}
}
- if (!ret)
+ if (ret == 0)
{
/* Find best score */
ret = (size_t)(-1);
{
*tocode = i;
ret = score[i];
- if (!ret)
+ if (ret == 0)
break;
}
}
continue;
fcode = mutt_str_substr_dup(c, c1);
- ret = convert_file_to(fp, fcode, ncodes, (const char **) tcode, &cn, info);
+ ret = convert_file_to(fp, fcode, ncodes, (char const *const *) tcode, &cn, info);
if (ret != (size_t)(-1))
{
*fromcode = fcode;
else
{
/* There is only one fromcode */
- ret = convert_file_to(fp, fromcodes, ncodes, (const char **) tcode, &cn, info);
+ ret = convert_file_to(fp, fromcodes, ncodes, (char const *const *) tcode, &cn, info);
if (ret != (size_t)(-1))
{
*tocode = tcode[cn];
fp = fopen(fname, "r");
if (!fp)
{
- mutt_debug(LL_DEBUG1, "%s: %s (errno %d).\n", fname, strerror(errno), errno);
+ mutt_debug(LL_DEBUG1, "%s: %s (errno %d)\n", fname, strerror(errno), errno);
return NULL;
}
if (b && (b->type == TYPE_TEXT) && (!b->noconv && !b->force_charset))
{
char *chs = mutt_param_get(&b->parameter, "charset");
- char *fchs = b->use_disp ?
- ((C_AttachCharset && *C_AttachCharset) ? C_AttachCharset : C_Charset) :
- C_Charset;
+ char *fchs = b->use_disp ? (C_AttachCharset ? C_AttachCharset : C_Charset) : C_Charset;
if (C_Charset && (chs || C_SendCharset) &&
(convert_file_from_to(fp, fchs, chs ? chs : C_SendCharset, &fromcode,
&tocode, info) != (size_t)(-1)))
* The longest match is used so that we can match 'ps.gz' when 'gz' also
* exists.
*/
-int mutt_lookup_mime_type(struct Body *att, const char *path)
+enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
{
FILE *fp = NULL;
char *p = NULL, *q = NULL, *ct = NULL;
char buf[PATH_MAX];
- char subtype[256], xtype[256];
- int szf, sze, cur_sze;
- int type;
+ char subtype[256] = { 0 };
+ char xtype[256] = { 0 };
+ int sze, cur_sze = 0;
bool found_mimetypes = false;
+ enum ContentType type = TYPE_OTHER;
- *subtype = '\0';
- *xtype = '\0';
- type = TYPE_OTHER;
- cur_sze = 0;
-
- szf = mutt_str_strlen(path);
+ int szf = mutt_str_strlen(path);
for (int count = 0; count < 4; count++)
{
/* can't use strtok() because we use it in an inner loop below, so use
- * a switch statement here instead.
- */
+ * a switch statement here instead. */
switch (count)
{
/* last file with last entry to match wins type/xtype */
snprintf(buf, sizeof(buf), "%s/.mime.types", NONULL(HomeDir));
break;
default:
- mutt_debug(LL_DEBUG1, "Internal error, count = %d.\n", count);
+ mutt_debug(LL_DEBUG1, "Internal error, count = %d\n", count);
goto bye; /* shouldn't happen */
}
/* weed out any comments */
p = strchr(buf, '#');
if (p)
- *p = 0;
+ *p = '\0';
/* remove any leading space. */
ct = buf;
{
sze = mutt_str_strlen(p);
if ((sze > cur_sze) && (szf >= sze) &&
- ((mutt_str_strcasecmp(path + szf - sze, p) == 0) ||
- (mutt_str_strcasecmp(path + szf - sze, p) == 0)) &&
+ (mutt_str_strcasecmp(path + szf - sze, p) == 0) &&
((szf == sze) || (path[szf - sze - 1] == '.')))
{
/* get the content-type */
}
*p++ = 0;
- for (q = p; *q && !ISSPACE(*q); q++)
+ for (q = p; *q && !IS_SPACE(*q); q++)
;
- mutt_str_substr_cpy(subtype, p, q, sizeof(subtype));
+ mutt_str_substr_copy(p, q, subtype, sizeof(subtype));
type = mutt_check_mime_type(ct);
if (type == TYPE_OTHER)
{
if (a->type == TYPE_MULTIPART)
{
- if (a->encoding != ENC_7BIT)
- a->encoding = ENC_7BIT;
-
+ a->encoding = ENC_7BIT;
transform_to_7bit(a->parts, fp_in);
}
else if (mutt_is_message_type(a->type, a->subtype))
transform_to_7bit(a->parts, fp_in);
mutt_copy_hdr(fp_in, fp_out, a->offset, a->offset + a->length,
- CH_MIME | CH_NONEWLINE | CH_XMIT, NULL);
+ CH_MIME | CH_NONEWLINE | CH_XMIT, NULL, 0);
fputs("MIME-Version: 1.0\n", fp_out);
mutt_write_mime_header(a->parts, fp_out);
*/
void mutt_stamp_attachment(struct Body *a)
{
- a->stamp = time(NULL);
+ a->stamp = mutt_date_epoch();
}
/**
struct Body *body = NULL;
FILE *fp = NULL;
CopyMessageFlags cmflags;
- int pgp = WithCrypto ? e->security : 0;
+ SecurityFlags pgp = WithCrypto ? e->security : SEC_NO_FLAGS;
if (WithCrypto)
{
}
}
- mutt_copy_message_ctx(fp, m, e, cmflags, chflags);
+ mutt_copy_message(fp, m, e, cmflags, chflags, 0);
fflush(fp);
rewind(fp);
- body->email = mutt_email_new();
+ body->email = email_new();
body->email->offset = 0;
/* we don't need the user headers here */
body->email->env = mutt_rfc822_read_header(fp, body->email, false, false);
*/
static void run_mime_type_query(struct Body *att)
{
- FILE *fp, *fp_err;
- char cmd[STR_COMMAND];
+ FILE *fp = NULL, *fp_err = NULL;
char *buf = NULL;
size_t buflen;
int dummy = 0;
pid_t pid;
+ struct Buffer *cmd = mutt_buffer_pool_get();
- mutt_file_expand_fmt_quote(cmd, sizeof(cmd), C_MimeTypeQueryCommand, att->filename);
+ mutt_buffer_file_expand_fmt_quote(cmd, C_MimeTypeQueryCommand, att->filename);
- pid = mutt_create_filter(cmd, NULL, &fp, &fp_err);
+ pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp, &fp_err);
if (pid < 0)
{
- mutt_error(_("Error running \"%s\""), cmd);
+ mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
+ mutt_buffer_pool_release(&cmd);
return;
}
+ mutt_buffer_pool_release(&cmd);
buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0);
if (buf)
struct Body *att = mutt_body_new();
att->filename = mutt_str_strdup(path);
- if (C_MimeTypeQueryCommand && *C_MimeTypeQueryCommand && C_MimeTypeQueryFirst)
+ if (C_MimeTypeQueryCommand && C_MimeTypeQueryFirst)
run_mime_type_query(att);
/* Attempt to determine the appropriate content-type based on the filename
- * suffix.
- */
+ * suffix. */
if (!att->subtype)
mutt_lookup_mime_type(att, path);
- if (!att->subtype && C_MimeTypeQueryCommand && *C_MimeTypeQueryCommand && !C_MimeTypeQueryFirst)
+ if (!att->subtype && C_MimeTypeQueryCommand && !C_MimeTypeQueryFirst)
{
run_mime_type_query(att);
}
((info->lobin == 0) || ((info->lobin + info->hibin + info->ascii) / info->lobin >= 10)))
{
/* Statistically speaking, there should be more than 10% "lobin"
- * chars if this is really a binary file...
- */
+ * chars if this is really a binary file... */
att->type = TYPE_TEXT;
att->subtype = mutt_str_strdup("plain");
}
{
if (a->encoding == ENC_BINARY)
return ENC_BINARY;
- else if (a->encoding == ENC_8BIT)
+ if (a->encoding == ENC_8BIT)
e = ENC_8BIT;
}
*/
struct Body *mutt_make_multipart(struct Body *b)
{
- struct Body *new = mutt_body_new();
- new->type = TYPE_MULTIPART;
- new->subtype = mutt_str_strdup("mixed");
- new->encoding = get_toplevel_encoding(b);
+ struct Body *new_body = mutt_body_new();
+ new_body->type = TYPE_MULTIPART;
+ new_body->subtype = mutt_str_strdup("mixed");
+ new_body->encoding = get_toplevel_encoding(b);
do
{
- mutt_generate_boundary(&new->parameter);
- if (check_boundary(mutt_param_get(&new->parameter, "boundary"), b))
- mutt_param_delete(&new->parameter, "boundary");
- } while (!mutt_param_get(&new->parameter, "boundary"));
- new->use_disp = false;
- new->disposition = DISP_INLINE;
- new->parts = b;
+ mutt_generate_boundary(&new_body->parameter);
+ if (check_boundary(mutt_param_get(&new_body->parameter, "boundary"), b))
+ mutt_param_delete(&new_body->parameter, "boundary");
+ } while (!mutt_param_get(&new_body->parameter, "boundary"));
+ new_body->use_disp = false;
+ new_body->disposition = DISP_INLINE;
+ new_body->parts = b;
- return new;
+ return new_body;
}
/**
}
/**
- * mutt_write_address_list - wrapper around mutt_write_address()
- * @param addr Address list
+ * mutt_write_addrlist - wrapper around mutt_write_address()
+ * @param al Address list
* @param fp File to write to
* @param linelen Line length to use
* @param display True if these addresses will be displayed to the user
* So we can handle very large recipient lists without needing a huge temporary
* buffer in memory
*/
-void mutt_write_address_list(struct Address *addr, FILE *fp, int linelen, bool display)
+void mutt_write_addrlist(struct AddressList *al, FILE *fp, int linelen, bool display)
{
- struct Address *tmp = NULL;
char buf[1024];
int count = 0;
- while (addr)
+ struct Address *a = NULL;
+ TAILQ_FOREACH(a, al, entries)
{
- tmp = addr->next;
- addr->next = NULL;
- buf[0] = 0;
- mutt_addr_write(buf, sizeof(buf), addr, display);
+ buf[0] = '\0';
+ mutt_addr_write(buf, sizeof(buf), a, display);
size_t len = mutt_str_strlen(buf);
if (count && (linelen + len > 74))
{
}
else
{
- if (count && addr->mailbox)
+ if (count && a->mailbox)
{
fputc(' ', fp);
linelen++;
linelen += len;
}
fputs(buf, fp);
- addr->next = tmp;
- if (!addr->group && addr->next && addr->next->mailbox)
+ struct Address *next = TAILQ_NEXT(a, entries);
+ if (!a->group && next && next->mailbox)
{
linelen++;
fputc(',', fp);
}
- addr = addr->next;
count++;
}
fputc('\n', fp);
static int print_val(FILE *fp, const char *pfx, const char *value,
CopyHeaderFlags chflags, size_t col)
{
- while (value && *value)
+ while (value && (value[0] != '\0'))
{
if (fputc(*value, fp) == EOF)
return -1;
}
if (*value == '\n')
{
- if (*(value + 1) && pfx && *pfx && (fputs(pfx, fp) == EOF))
+ if ((value[1] != '\0') && pfx && (pfx[0] != '\0') && (fputs(pfx, fp) == EOF))
return -1;
/* for display, turn folding spaces into folding tabs */
- if ((chflags & CH_DISPLAY) && ((*(value + 1) == ' ') || (*(value + 1) == '\t')))
+ if ((chflags & CH_DISPLAY) && ((value[1] == ' ') || (value[1] == '\t')))
{
value++;
- while (*value && (*value == ' ' || *value == '\t'))
+ while ((value[0] != '\0') && ((value[0] == ' ') || (value[0] == '\t')))
value++;
if (fputc('\t', fp) == EOF)
return -1;
const char *pfx, int wraplen, CopyHeaderFlags chflags)
{
const char *p = value;
- char buf[8192] = "";
+ char buf[8192] = { 0 };
int first = 1, col = 0, l = 0;
const bool display = (chflags & CH_DISPLAY);
- mutt_debug(5, "pfx=[%s], tag=[%s], flags=%d value=[%s]\n", pfx, tag, chflags,
- NONULL(value));
+ mutt_debug(LL_DEBUG5, "pfx=[%s], tag=[%s], flags=%d value=[%s]\n", pfx, tag,
+ chflags, NONULL(value));
if (tag && *tag && (fprintf(fp, "%s%s: ", NONULL(pfx), tag) < 0))
return -1;
- col = mutt_str_strlen(tag) + (tag && *tag ? 2 : 0) + mutt_str_strlen(pfx);
+ col = mutt_str_strlen(tag) + ((tag && (tag[0] != '\0')) ? 2 : 0) + mutt_str_strlen(pfx);
- while (p && *p)
+ while (p && (p[0] != '\0'))
{
int fold = 0;
const char *next = mutt_str_find_word(p);
l = MIN(sizeof(buf) - 1, next - p);
memcpy(buf, p, l);
- buf[l] = 0;
+ buf[l] = '\0';
/* determine width: character cells for display, bytes for sending
* (we get pure ascii only) */
const int w = mutt_mb_width(buf, col, display);
const int enc = mutt_str_startswith(buf, "=?", CASE_MATCH);
- mutt_debug(5, "word=[%s], col=%d, w=%d, next=[0x0%x]\n", buf, col, w, *next);
+ mutt_debug(LL_DEBUG5, "word=[%s], col=%d, w=%d, next=[0x0%x]\n", buf, col, w, *next);
/* insert a folding \n before the current word's lwsp except for
* header name, first word on a line (word longer than wrap width)
* and encoded words */
- if (!first && !enc && col && (col + w >= wraplen))
+ if (!first && !enc && col && ((col + w) >= wraplen))
{
col = mutt_str_strlen(pfx);
fold = 1;
if (display && fold)
{
char *pc = buf;
- while (*pc && (*pc == ' ' || *pc == '\t'))
+ while ((pc[0] != '\0') && ((pc[0] == ' ') || (pc[0] == '\t')))
{
pc++;
col--;
* XXX this covers ASCII space only, for display we probably
* want something like iswspace() here */
const char *sp = next;
- while (*sp && (*sp == ' ' || *sp == '\t'))
+ while ((sp[0] != '\0') && ((sp[0] == ' ') || (sp[0] == '\t')))
sp++;
- if (*sp == '\n')
+ if (sp[0] == '\n')
{
next = sp;
col = 0;
*/
static char *unfold_header(char *s)
{
- char *p = s, *q = s;
+ char *p = s;
+ char *q = s;
- while (p && *p)
+ while (p && (p[0] != '\0'))
{
/* remove CRLF prior to FWSP, turn \t into ' ' */
- if ((*p == '\r') && *(p + 1) && (*(p + 1) == '\n') && *(p + 2) &&
- ((*(p + 2) == ' ') || (*(p + 2) == '\t')))
+ if ((p[0] == '\r') && (p[1] == '\n') && ((p[2] == ' ') || (p[2] == '\t')))
{
*q++ = ' ';
p += 3;
continue;
}
/* remove LF prior to FWSP, turn \t into ' ' */
- else if ((*p == '\n') && *(p + 1) && ((*(p + 1) == ' ') || (*(p + 1) == '\t')))
+ else if ((p[0] == '\n') && ((p[1] == ' ') || (p[1] == '\t')))
{
*q++ = ' ';
p += 2;
*q++ = *p++;
}
if (q)
- *q = 0;
+ q[0] = '\0';
return s;
}
if (!(chflags & CH_DISPLAY) && ((pfxw + max <= wraplen) || is_from))
{
valbuf = mutt_str_substr_dup(start, end);
- mutt_debug(5, "buf[%s%s] short enough, max width = %d <= %d\n", NONULL(pfx),
- valbuf, max, wraplen);
+ mutt_debug(LL_DEBUG5, "buf[%s%s] short enough, max width = %d <= %d\n",
+ NONULL(pfx), valbuf, max, wraplen);
if (pfx && *pfx)
{
if (fputs(pfx, fp) == EOF)
/* skip over any leading whitespace (WSP, as defined in RFC5322)
* NOTE: mutt_str_skip_email_wsp() does the wrong thing here.
* See tickets 3609 and 3716. */
- while (*t == ' ' || *t == '\t')
+ while ((*t == ' ') || (*t == '\t'))
t++;
valbuf = mutt_str_substr_dup(t, end);
int mutt_write_one_header(FILE *fp, const char *tag, const char *value,
const char *pfx, int wraplen, CopyHeaderFlags chflags)
{
- char *p = (char *) value, *last = NULL, *line = NULL;
+ char *last = NULL, *line = NULL;
int max = 0, w, rc = -1;
int pfxw = mutt_strwidth(pfx);
char *v = mutt_str_strdup(value);
else
wraplen = C_WrapHeaders;
}
- else if ((wraplen <= 0) || (wraplen > MuttIndexWindow->cols))
- wraplen = MuttIndexWindow->cols;
+ else if (wraplen <= 0)
+ wraplen = 78;
if (tag)
{
/* if header is short enough, simply print it */
if (!display && (mutt_strwidth(tag) + 2 + pfxw + mutt_strwidth(v) <= wraplen))
{
- mutt_debug(5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
+ mutt_debug(LL_DEBUG5, "buf[%s%s: %s] is short enough\n", NONULL(pfx), tag, v);
if (fprintf(fp, "%s%s: %s\n", NONULL(pfx), tag, v) <= 0)
goto out;
rc = 0;
}
}
- p = v;
+ char *p = v;
last = v;
line = v;
while (p && *p)
/* find maximum line width in current header */
if (p)
- *p = 0;
+ *p = '\0';
w = mutt_mb_width(line, 0, display);
if (w > max)
max = w;
return rc;
}
+/**
+ * userhdrs_override_cmp - Compare a user-defined header with an element of the userhdrs_override_headers list
+ * @param a Pointer to the string containing the user-defined header
+ * @param b Pointer to an element of the userhdrs_override_headers list
+ * @retval -1 a precedes b
+ * @retval 0 a and b are identical
+ * @retval 1 b precedes a
+ */
+static int userhdrs_override_cmp(const void *a, const void *b)
+{
+ const char *ca = a;
+ const char *cb = *(const char **) b;
+ return mutt_str_strncasecmp(ca, cb, strlen(cb));
+}
+
+/**
+ * write_userhdrs - Write user-defined headers and keep track of the interesting ones
+ * @param fp FILE pointer where to write the headers
+ * @param userhdrs List of headers to write
+ * @param privacy Omit headers that could identify the user
+ * @retval obj UserHdrsOverride struct containing a bitmask of which unique headers were written
+ */
+static struct UserHdrsOverride write_userhdrs(FILE *fp, const struct ListHead *userhdrs, bool privacy)
+{
+ struct UserHdrsOverride overrides = { { 0 } };
+
+ struct ListNode *tmp = NULL;
+ STAILQ_FOREACH(tmp, userhdrs, entries)
+ {
+ char *const colon = strchr(tmp->data, ':');
+ if (!colon)
+ {
+ continue;
+ }
+
+ const char *const value = mutt_str_skip_email_wsp(colon + 1);
+ if (*value == '\0')
+ {
+ continue; /* don't emit empty fields. */
+ }
+
+ /* check whether the current user-header is an override */
+ size_t curr_override = (size_t) -1;
+ const char *const *idx = bsearch(tmp->data, userhdrs_override_headers,
+ mutt_array_size(userhdrs_override_headers),
+ sizeof(char *), userhdrs_override_cmp);
+ if (idx != NULL)
+ {
+ curr_override = idx - userhdrs_override_headers;
+ overrides.is_overridden[curr_override] = true;
+ }
+
+ if (privacy && (curr_override == USERHDRS_OVERRIDE_USER_AGENT))
+ {
+ continue;
+ }
+
+ *colon = '\0';
+ mutt_write_one_header(fp, tmp->data, value, NULL, 0, CH_NO_FLAGS);
+ *colon = ':';
+ }
+
+ return overrides;
+}
+
/**
* mutt_rfc822_write_header - Write out one RFC822 header line
* @param fp File to write to
bool privacy, bool hide_protected_subject)
{
char buf[1024];
- char *p = NULL, *q = NULL;
- bool has_agent = false; /* user defined user-agent header field exists */
if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy)
fputs(mutt_date_make_date(buf, sizeof(buf)), fp);
/* UseFrom is not consulted here so that we can still write a From:
- * field if the user sets it with the 'my_hdr' command
- */
- if (env->from && !privacy)
+ * field if the user sets it with the 'my_hdr' command */
+ if (!TAILQ_EMPTY(&env->from) && !privacy)
{
- buf[0] = 0;
- mutt_addr_write(buf, sizeof(buf), env->from, false);
+ buf[0] = '\0';
+ mutt_addrlist_write(buf, sizeof(buf), &env->from, false);
fprintf(fp, "From: %s\n", buf);
}
- if (env->sender && !privacy)
+ if (!TAILQ_EMPTY(&env->sender) && !privacy)
{
- buf[0] = 0;
- mutt_addr_write(buf, sizeof(buf), env->sender, false);
+ buf[0] = '\0';
+ mutt_addrlist_write(buf, sizeof(buf), &env->sender, false);
fprintf(fp, "Sender: %s\n", buf);
}
- if (env->to)
+ if (!TAILQ_EMPTY(&env->to))
{
fputs("To: ", fp);
- mutt_write_address_list(env->to, fp, 4, 0);
+ mutt_write_addrlist(&env->to, fp, 4, 0);
}
else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
#ifdef USE_NNTP
#endif
fputs("To:\n", fp);
- if (env->cc)
+ if (!TAILQ_EMPTY(&env->cc))
{
fputs("Cc: ", fp);
- mutt_write_address_list(env->cc, fp, 4, 0);
+ mutt_write_addrlist(&env->cc, fp, 4, 0);
}
else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
#ifdef USE_NNTP
#endif
fputs("Cc:\n", fp);
- if (env->bcc)
+ if (!TAILQ_EMPTY(&env->bcc))
{
if ((mode == MUTT_WRITE_HEADER_POSTPONE) || (mode == MUTT_WRITE_HEADER_EDITHDRS) ||
((mode == MUTT_WRITE_HEADER_NORMAL) && C_WriteBcc))
{
fputs("Bcc: ", fp);
- mutt_write_address_list(env->bcc, fp, 5, 0);
+ mutt_write_addrlist(&env->bcc, fp, 5, 0);
}
}
else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
{
if (hide_protected_subject &&
((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE)))
- mutt_write_one_header(fp, "Subject", C_CryptProtectedHeadersSubject, NULL, 0, 0);
+ mutt_write_one_header(fp, "Subject", C_CryptProtectedHeadersSubject, NULL, 0, CH_NO_FLAGS);
else
- mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, 0);
+ mutt_write_one_header(fp, "Subject", env->subject, NULL, 0, CH_NO_FLAGS);
}
else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
fputs("Subject:\n", fp);
if (env->message_id && !privacy)
fprintf(fp, "Message-ID: %s\n", env->message_id);
- if (env->reply_to)
+ if (!TAILQ_EMPTY(&env->reply_to))
{
fputs("Reply-To: ", fp);
- mutt_write_address_list(env->reply_to, fp, 10, 0);
+ mutt_write_addrlist(&env->reply_to, fp, 10, 0);
}
else if (mode == MUTT_WRITE_HEADER_EDITHDRS)
fputs("Reply-To:\n", fp);
- if (env->mail_followup_to)
+ if (!TAILQ_EMPTY(&env->mail_followup_to))
+ {
#ifdef USE_NNTP
if (!OptNewsSend)
#endif
{
fputs("Mail-Followup-To: ", fp);
- mutt_write_address_list(env->mail_followup_to, fp, 18, 0);
+ mutt_write_addrlist(&env->mail_followup_to, fp, 18, 0);
}
+ }
+
+ /* Add any user defined headers */
+ struct UserHdrsOverride userhdrs_overrides = write_userhdrs(fp, &env->userhdrs, privacy);
if ((mode == MUTT_WRITE_HEADER_NORMAL) || (mode == MUTT_WRITE_HEADER_POSTPONE))
{
}
/* Add the MIME headers */
- fputs("MIME-Version: 1.0\n", fp);
- mutt_write_mime_header(attach, fp);
+ if (!userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_CONTENT_TYPE])
+ {
+ fputs("MIME-Version: 1.0\n", fp);
+ mutt_write_mime_header(attach, fp);
+ }
}
if (!STAILQ_EMPTY(&env->in_reply_to))
fputc('\n', fp);
}
- /* Add any user defined headers */
- struct ListNode *tmp = NULL;
- STAILQ_FOREACH(tmp, &env->userhdrs, entries)
+#ifdef USE_AUTOCRYPT
+ if (C_Autocrypt)
{
- p = strchr(tmp->data, ':');
- if (p)
- {
- q = p;
-
- *p = '\0';
-
- p = mutt_str_skip_email_wsp(p + 1);
- if (!*p)
- {
- *q = ':';
- continue; /* don't emit empty fields. */
- }
-
- /* check to see if the user has overridden the user-agent field */
- if (mutt_str_startswith(tmp->data, "user-agent", CASE_IGNORE))
- {
- has_agent = true;
- if (privacy)
- {
- *q = ':';
- continue;
- }
- }
-
- mutt_write_one_header(fp, tmp->data, p, NULL, 0, 0);
- *q = ':';
- }
+ if (mode == MUTT_WRITE_HEADER_NORMAL)
+ mutt_autocrypt_write_autocrypt_header(env, fp);
+ if (mode == MUTT_WRITE_HEADER_MIME)
+ mutt_autocrypt_write_gossip_headers(env, fp);
}
+#endif
- if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent && !has_agent)
+ if ((mode == MUTT_WRITE_HEADER_NORMAL) && !privacy && C_UserAgent &&
+ !userhdrs_overrides.is_overridden[USERHDRS_OVERRIDE_USER_AGENT])
{
/* Add a vanity header */
fprintf(fp, "User-Agent: NeoMutt/%s%s\n", PACKAGE_VERSION, GitVer);
}
- return ferror(fp) == 0 ? 0 : -1;
+ return (ferror(fp) == 0) ? 0 : -1;
}
/**
static char *gen_msgid(void)
{
char buf[128];
- time_t now;
unsigned char rndid[MUTT_RANDTAG_LEN + 1];
mutt_rand_base32(rndid, sizeof(rndid) - 1);
rndid[MUTT_RANDTAG_LEN] = 0;
- now = time(NULL);
- struct tm *tm = gmtime(&now);
const char *fqdn = mutt_fqdn(false);
if (!fqdn)
fqdn = NONULL(ShortHostname);
- snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm->tm_year + 1900,
- tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rndid, fqdn);
+ struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
+ snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
+ tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
return mutt_str_strdup(buf);
}
pid_t ppid = getppid();
/* we want the delivery to continue even after the main process dies,
- * so we put ourselves into another session right away
- */
+ * so we put ourselves into another session right away */
setsid();
/* next we close all open files */
/* C_SendmailWait > 0: interrupt waitpid() after C_SendmailWait seconds
* C_SendmailWait = 0: wait forever
- * C_SendmailWait < 0: don't wait
- */
+ * C_SendmailWait < 0: don't wait */
if (C_SendmailWait > 0)
{
SigAlrm = 0;
}
else
{
- st = (C_SendmailWait > 0 && errno == EINTR && SigAlrm) ? S_BKG : S_ERR;
+ st = ((C_SendmailWait > 0) && (errno == EINTR) && SigAlrm) ? S_BKG : S_ERR;
if ((C_SendmailWait > 0) && tempfile && *tempfile)
{
unlink(*tempfile);
}
/**
- * add_args - Add an Address to a dynamic array
+ * add_args_one - Add an Address to a dynamic array
* @param[out] args Array to add to
* @param[out] argslen Number of entries in array
* @param[out] argsmax Allocated size of the array
* @param[in] addr Address to add
* @retval ptr Updated array
*/
-static char **add_args(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
+static char **add_args_one(char **args, size_t *argslen, size_t *argsmax, struct Address *addr)
{
- for (; addr; addr = addr->next)
+ /* weed out group mailboxes, since those are for display only */
+ if (addr->mailbox && !addr->group)
{
- /* weed out group mailboxes, since those are for display only */
- if (addr->mailbox && !addr->group)
- {
- if (*argslen == *argsmax)
- mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
- args[(*argslen)++] = addr->mailbox;
- }
+ if (*argslen == *argsmax)
+ mutt_mem_realloc(&args, (*argsmax += 5) * sizeof(char *));
+ args[(*argslen)++] = addr->mailbox;
+ }
+ return args;
+}
+
+/**
+ * add_args - Add a list of Addresses to a dynamic array
+ * @param[out] args Array to add to
+ * @param[out] argslen Number of entries in array
+ * @param[out] argsmax Allocated size of the array
+ * @param[in] al Addresses to add
+ * @retval ptr Updated array
+ */
+static char **add_args(char **args, size_t *argslen, size_t *argsmax, struct AddressList *al)
+{
+ if (!al)
+ return args;
+
+ struct Address *a = NULL;
+ TAILQ_FOREACH(a, al, entries)
+ {
+ args = add_args_one(args, argslen, argsmax, a);
}
return args;
}
* @retval 0 Success
* @retval -1 Failure
*/
-int mutt_invoke_sendmail(struct Address *from, struct Address *to, struct Address *cc,
- struct Address *bcc, const char *msg, int eightbit)
+int mutt_invoke_sendmail(struct AddressList *from, struct AddressList *to,
+ struct AddressList *cc, struct AddressList *bcc,
+ const char *msg, int eightbit)
{
char *ps = NULL, *path = NULL, *s = NULL, *childout = NULL;
char **args = NULL;
{
char cmd[1024];
- mutt_expando_format(cmd, sizeof(cmd), 0, MuttIndexWindow->cols,
- NONULL(C_Inews), nntp_format_str, 0, 0);
+ mutt_expando_format(cmd, sizeof(cmd), 0, sizeof(cmd), NONULL(C_Inews),
+ nntp_format_str, 0, MUTT_FORMAT_NO_FLAGS);
if (!*cmd)
{
i = nntp_post(Context->mailbox, msg);
if (C_EnvelopeFromAddress)
{
args = add_option(args, &argslen, &argsmax, "-f");
- args = add_args(args, &argslen, &argsmax, C_EnvelopeFromAddress);
+ args = add_args_one(args, &argslen, &argsmax, C_EnvelopeFromAddress);
}
- else if (from && !from->next)
+ else if (!TAILQ_EMPTY(from) && !TAILQ_NEXT(TAILQ_FIRST(from), entries))
{
args = add_option(args, &argslen, &argsmax, "-f");
args = add_args(args, &argslen, &argsmax, from);
struct stat st;
if ((stat(childout, &st) == 0) && (st.st_size > 0))
- mutt_do_pager(_("Output of the delivery process"), childout, 0, NULL);
+ mutt_do_pager(_("Output of the delivery process"), childout,
+ MUTT_PAGER_NO_FLAGS, NULL);
}
}
}
{
if (final)
{
- if (env->bcc && !(env->to || env->cc))
+ if (!TAILQ_EMPTY(&env->bcc) && TAILQ_EMPTY(&env->to) && TAILQ_EMPTY(&env->cc))
{
/* some MTA's will put an Apparently-To: header field showing the Bcc:
* recipients if there is no To: or Cc: field, so attempt to suppress
- * it by using an empty To: field.
- */
- env->to = mutt_addr_new();
- env->to->group = 1;
- env->to->next = mutt_addr_new();
+ * it by using an empty To: field. */
+ struct Address *to = mutt_addr_new();
+ to->group = true;
+ mutt_addrlist_append(&env->to, to);
+ mutt_addrlist_append(&env->to, mutt_addr_new());
char buf[1024];
- buf[0] = 0;
+ buf[0] = '\0';
mutt_addr_cat(buf, sizeof(buf), "undisclosed-recipients", AddressSpecials);
- env->to->mailbox = mutt_str_strdup(buf);
+ to->mailbox = mutt_str_strdup(buf);
}
mutt_set_followup_to(env);
rfc2047_decode(&item->data);
}
- mutt_addr_free(&env->mail_followup_to);
+ mutt_addrlist_clear(&env->mail_followup_to);
/* back conversions */
rfc2047_decode_envelope(env);
* @retval 0 Success
* @retval -1 Failure
*/
-static int bounce_message(FILE *fp, struct Email *e, struct Address *to,
- const char *resent_from, struct Address *env_from)
+static int bounce_message(FILE *fp, struct Email *e, struct AddressList *to,
+ const char *resent_from, struct AddressList *env_from)
{
if (!e)
return -1;
fprintf(fp_tmp, "Resent-Message-ID: %s\n", msgid_str);
FREE(&msgid_str);
fputs("Resent-To: ", fp_tmp);
- mutt_write_address_list(to, fp_tmp, 11, 0);
- mutt_copy_header(fp, e, fp_tmp, chflags, NULL);
+ mutt_write_addrlist(to, fp_tmp, 11, 0);
+ mutt_copy_header(fp, e, fp_tmp, chflags, NULL, 0);
fputc('\n', fp_tmp);
mutt_file_copy_bytes(fp, fp_tmp, e->content->length);
if (mutt_file_fclose(&fp_tmp) != 0)
* mutt_bounce_message - Bounce an email message
* @param fp Handle of message
* @param e Email
- * @param to Address to bounce to
+ * @param to AddressList to bounce to
* @retval 0 Success
* @retval -1 Failure
*/
-int mutt_bounce_message(FILE *fp, struct Email *e, struct Address *to)
+int mutt_bounce_message(FILE *fp, struct Email *e, struct AddressList *to)
{
- if (!fp || !e || !to)
+ if (!fp || !e || !to || TAILQ_EMPTY(to))
return -1;
const char *fqdn = mutt_fqdn(true);
resent_from[0] = '\0';
struct Address *from = mutt_default_from();
+ struct AddressList from_list = TAILQ_HEAD_INITIALIZER(from_list);
+ mutt_addrlist_append(&from_list, from);
/* mutt_default_from() does not use $realname if the real name is not set
* in $from, so we add it here. The reason it is not added in
* mutt_default_from() is that during normal sending, we execute
* send-hooks and set the realname last so that it can be changed based
- * upon message criteria.
- */
+ * upon message criteria. */
if (!from->personal)
from->personal = mutt_str_strdup(C_Realname);
- if (fqdn)
- mutt_addr_qualify(from, fqdn);
+ mutt_addrlist_qualify(&from_list, fqdn);
- rfc2047_encode_addrlist(from, "Resent-From");
- if (mutt_addrlist_to_intl(from, &err))
+ rfc2047_encode_addrlist(&from_list, "Resent-From");
+ if (mutt_addrlist_to_intl(&from_list, &err))
{
mutt_error(_("Bad IDN %s while preparing resent-from"), err);
FREE(&err);
- mutt_addr_free(&from);
+ mutt_addrlist_clear(&from_list);
return -1;
}
- mutt_addr_write(resent_from, sizeof(resent_from), from, false);
+ mutt_addrlist_write(resent_from, sizeof(resent_from), &from_list, false);
#ifdef USE_NNTP
OptNewsSend = false;
/* prepare recipient list. idna conversion appears to happen before this
* function is called, since the user receives confirmation of the address
- * list being bounced to.
- */
- struct Address *resent_to = mutt_addr_copy_list(to, false);
- rfc2047_encode_addrlist(resent_to, "Resent-To");
-
- int rc = bounce_message(fp, e, resent_to, resent_from, from);
-
- mutt_addr_free(&resent_to);
- mutt_addr_free(&from);
+ * list being bounced to. */
+ struct AddressList resent_to = TAILQ_HEAD_INITIALIZER(resent_to);
+ mutt_addrlist_copy(&resent_to, to, false);
+ rfc2047_encode_addrlist(&resent_to, "Resent-To");
+ int rc = bounce_message(fp, e, &resent_to, resent_from, &from_list);
+ mutt_addrlist_clear(&resent_to);
+ mutt_addrlist_clear(&from_list);
return rc;
}
* @retval -1 Failure
*/
int mutt_write_fcc(const char *path, struct Email *e, const char *msgid,
- bool post, char *fcc, char **finalpath)
+ bool post, const char *fcc, char **finalpath)
{
struct Message *msg = NULL;
char tempfile[PATH_MAX];
mutt_folder_hook(path, NULL);
#endif
struct Mailbox *m_fcc = mx_path_resolve(path);
+ bool old_append = m_fcc->append;
struct Context *ctx_fcc = mx_mbox_open(m_fcc, MUTT_APPEND | MUTT_QUIET);
if (!ctx_fcc)
{
- mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting.\n", path);
+ mutt_debug(LL_DEBUG1, "unable to open mailbox %s in append-mode, aborting\n", path);
mailbox_free(&m_fcc);
goto done;
}
/* We need to add a Content-Length field to avoid problems where a line in
- * the message body begins with "From "
- */
+ * the message body begins with "From " */
if ((ctx_fcc->mailbox->magic == MUTT_MMDF) || (ctx_fcc->mailbox->magic == MUTT_MBOX))
{
mutt_mktemp(tempfile, sizeof(tempfile));
}
/* post == 1 => postpone message.
- * post == 0 => Normal mode.
- */
+ * post == 0 => Normal mode. */
mutt_rfc822_write_header(
msg->fp, e->env, e->content, post ? MUTT_WRITE_HEADER_POSTPONE : MUTT_WRITE_HEADER_NORMAL,
false, C_CryptProtectedHeadersRead && mutt_should_hide_protected_subject(e));
* Message-ID: of message replied to. Save it using a special X-Mutt-
* header so it can be picked up if the message is recalled at a later
* point in time. This will allow the message to be marked as replied if
- * the same mailbox is still open.
- */
+ * the same mailbox is still open. */
if (post && msgid)
fprintf(msg->fp, "X-Mutt-References: %s\n", msgid);
/* (postponement) save the Fcc: using a special X-Mutt- header so that
- * it can be picked up when the message is recalled
- */
+ * it can be picked up when the message is recalled */
if (post && fcc)
fprintf(msg->fp, "X-Mutt-Fcc: %s\n", fcc);
if (e->security & SEC_SIGN)
{
fputc('S', msg->fp);
- if (C_PgpSignAs && *C_PgpSignAs)
+ if (C_PgpSignAs)
fprintf(msg->fp, "<%s>", C_PgpSignAs);
}
if (e->security & SEC_INLINE)
fputc('I', msg->fp);
+#ifdef USE_AUTOCRYPT
+ if (e->security & SEC_AUTOCRYPT)
+ fputc('A', msg->fp);
+ if (e->security & SEC_AUTOCRYPT_OVERRIDE)
+ fputc('Z', msg->fp);
+#endif
fputc('\n', msg->fp);
}
if (e->security & SEC_ENCRYPT)
{
fputc('E', msg->fp);
- if (C_SmimeEncryptWith && *C_SmimeEncryptWith)
+ if (C_SmimeEncryptWith)
fprintf(msg->fp, "C<%s>", C_SmimeEncryptWith);
}
if (e->security & SEC_OPPENCRYPT)
if (e->security & SEC_SIGN)
{
fputc('S', msg->fp);
- if (C_SmimeSignAs && *C_SmimeSignAs)
+ if (C_SmimeSignAs)
fprintf(msg->fp, "<%s>", C_SmimeSignAs);
}
if (e->security & SEC_INLINE)
#ifdef MIXMASTER
/* (postponement) if the mail is to be sent through a mixmaster
- * chain, save that information
- */
+ * chain, save that information */
if (post && !STAILQ_EMPTY(&e->chain))
{
if (fp_tmp)
{
- char sasha[1024];
- int lines = 0;
-
mutt_write_mime_body(e->content, fp_tmp);
- /* make sure the last line ends with a newline. Emacs doesn't ensure
- * this will happen, and it can cause problems parsing the mailbox
- * later.
- */
+ /* make sure the last line ends with a newline. Emacs doesn't ensure this
+ * will happen, and it can cause problems parsing the mailbox later. */
fseek(fp_tmp, -1, SEEK_END);
if (fgetc(fp_tmp) != '\n')
{
fflush(fp_tmp);
if (ferror(fp_tmp))
{
- mutt_debug(LL_DEBUG1, "%s: write failed.\n", tempfile);
+ mutt_debug(LL_DEBUG1, "%s: write failed\n", tempfile);
mutt_file_fclose(&fp_tmp);
unlink(tempfile);
mx_msg_commit(ctx_fcc->mailbox, msg); /* XXX really? */
}
/* count the number of lines */
+ int lines = 0;
+ char line_buf[1024];
rewind(fp_tmp);
- while (fgets(sasha, sizeof(sasha), fp_tmp))
+ while (fgets(line_buf, sizeof(line_buf), fp_tmp))
lines++;
fprintf(msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello(fp_tmp));
fprintf(msg->fp, "Lines: %d\n\n", lines);
if (fclose(fp_tmp) != 0)
rc = -1;
/* if there was an error, leave the temp version */
- if (!rc)
+ if (rc == 0)
unlink(tempfile);
}
else
set_noconv_flags(e->content, false);
done:
+ m_fcc->append = old_append;
#ifdef RECORD_FOLDER_HOOK
/* We ran a folder hook for the destination mailbox,
* now we run it for the user's current mailbox */