Browse Source

Merge branch 'develop'

tags/fmail-0.2.1^0
parent
commit
b0cb062a32
4 changed files with 74 additions and 11 deletions
  1. +5
    -0
      NEWS
  2. +1
    -1
      configure.ac
  3. +1
    -1
      man/fmail.1.in
  4. +67
    -9
      src/fmail.c

+ 5
- 0
NEWS View File

@@ -1,3 +1,8 @@
Changes in fmail 0.2.1 (2019-02-13)

* Use 7bit encoding for attachments when possible.


Changes in fmail 0.2.0 (2019-01-12)

* Prune path components in an attachment’s filename.


+ 1
- 1
configure.ac View File

@@ -1,6 +1,6 @@
dnl Configure template for the fmail package

AC_INIT([fmail], [0.2.0],
AC_INIT([fmail], [0.2.1],
[dgouttegattat@incenp.org])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])


+ 1
- 1
man/fmail.1.in View File

@@ -110,7 +110,7 @@ Add a
.B User-Agent:
header.
.TP
.BR -D "; " --date
.BR -D ", " --date
Add an automatically generated
.B Date:
header with the current date.


+ 67
- 9
src/fmail.c View File

@@ -134,6 +134,47 @@ generate_boundary(char *buffer, size_t len)
return buffer;
}

static int
check_7bit_encoding(const char *filename)
{
FILE *f;
int c, ok = 1;
unsigned n;

if ( ! (f = fopen(filename, "r")) )
return 0; /* We'll error out later. */

while ( ! feof(f) && ! ok ) {
c = fgetc(f);

if ( c == 0 || c == '\r' || c > 127 )
ok = 0;
else if ( c == '\n' )
n = 0;
else
n += 1;

if ( n > 998 )
ok = 0;
}

fclose(f);

return ok;
}

static void
mime7bit_encode_stream(FILE *in, FILE *out)
{
int c;

while ( (c = fgetc(in)) != EOF ) {
if ( c == '\n' )
fputc('\r', out);
fputc(c, out);
}
}

static void
qp_encode_stream(FILE *in, FILE *out)
{
@@ -530,33 +571,50 @@ get_basename(const char *filename)
return last_slash ? last_slash + 1 : filename;
}

typedef enum {
ENCODING_7BIT = 0,
ENCODING_QP,
ENCODING_BASE64
} encoding_t;

const char *encoding_names[] = { "7bit", "quoted-printable", "base64" };
void (*encoding_funcs[])(FILE *, FILE *) = {
mime7bit_encode_stream,
qp_encode_stream,
base64_encode_stream
};

static void
process_attachment(const char *filename, magic_t ctx, FILE *out)
{
const char *mime;
int binary;
encoding_t encoding;
FILE *f;

if ( (mime = magic_file(ctx, filename)) ) {
const char *last_eq;

last_eq = strrchr(mime, '=');
binary = strcmp(last_eq, "=binary") ? 0 : 1;
if ( strcmp(last_eq, "=binary") == 0 )
encoding = ENCODING_BASE64;
else if ( strcmp(last_eq, "=us-ascii") == 0 && check_7bit_encoding(filename) )
encoding = ENCODING_7BIT;
else
encoding = ENCODING_QP;
}
else {
mime = "application/octet-stream";
binary = 1;
encoding = ENCODING_BASE64;
}

fprintf(out, "Content-Type: %s\r\n", mime);
fprintf(out, "Content-Transfer-Encoding: %s\r\n", binary ? "base64" : "quoted-printable");
fprintf(out, "Content-Transfer-Encoding: %s\r\n", encoding_names[encoding]);
fprintf(out, "Content-Disposition: attachment; filename=%s\r\n\r\n", get_basename(filename));

f = fopen(filename, "r");
if ( binary )
base64_encode_stream(f, out);
else
qp_encode_stream(f, out);
if ( ! (f = fopen(filename, "r")) )
err(EXIT_FAILURE, "cannot open attachment '%s'", filename);

encoding_funcs[encoding](f, out);
fclose(f);

fprintf(out, "\r\n");


Loading…
Cancel
Save