Browse Source

Use 7bit-encoding for attachments when possible.

Avoid Quoted-Printable encoding for attachment when possible
(if the attachment appears to be US-ASCII and does not contain any
line longer than 998 characters).

Some mail clients (Gnus?) seem to have problems extracting
attached OpenPGP keys if they are encoded in Quoted-Printable.
develop
Damien Goutte-Gattat 2 years ago
parent
commit
0686642b01
  1. 70
      src/fmail.c

70
src/fmail.c

@ -134,6 +134,45 @@ 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;
f = fopen(filename, "r");
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 +569,48 @@ 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);
encoding_funcs[encoding](f, out);
fclose(f);
fprintf(out, "\r\n");

Loading…
Cancel
Save