I'd forgotten that adding a "charset" specification to the Content-Type
header is also needed. In the *new* set of patches below, besides I
corrected some other errors, I added a '-y' option to specify utf-8
character set:
$ mail -s Hello -e quoted-printable -y "text/plain;charset=utf-8" \
[email protected] < message.txt
Index: collect.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/collect.c,v
retrieving revision 1.34
diff -u -p -r1.34 collect.c
--- collect.c 17 Jan 2014 18:42:30 -0000 1.34
+++ collect.c 19 Sep 2023 13:30:14 -0000
@@ -87,7 +87,7 @@ collect(struct header *hp, int printhead
* refrain from printing a newline after
* the headers (since some people mind).
*/
- t = GTO|GSUBJECT|GCC|GNL;
+ t = GTO|GSUBJECT|GENCODING|GTYPE|GCC|GNL;
getsub = 0;
if (hp->h_subject == NULL && value("interactive") != NULL &&
(value("ask") != NULL || value("asksub") != NULL))
@@ -208,7 +208,7 @@ cont:
/*
* Grab a bunch of headers.
*/
- grabh(hp, GTO|GSUBJECT|GCC|GBCC);
+ grabh(hp, GTO|GSUBJECT|GENCODING|GTYPE|GCC|GBCC);
goto cont;
case 't':
/*
@@ -328,7 +328,7 @@ cont:
*/
rewind(collf);
puts("-------\nMessage contains:");
- puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
+ puthead(hp, stdout,
GTO|GSUBJECT|GENCODING|GTYPE|GCC|GBCC|GNL);
while ((t = getc(collf)) != EOF)
(void)putchar(t);
goto cont;
Index: def.h
===================================================================
RCS file: /cvs/src/usr.bin/mail/def.h,v
retrieving revision 1.17
diff -u -p -r1.17 def.h
--- def.h 28 Jan 2022 06:18:41 -0000 1.17
+++ def.h 19 Sep 2023 13:30:14 -0000
@@ -158,12 +158,14 @@ struct headline {
#define GSUBJECT 2 /* Likewise, Subject: line */
#define GCC 4 /* And the Cc: line */
#define GBCC 8 /* And also the Bcc: line */
-#define GMASK (GTO|GSUBJECT|GCC|GBCC)
+#define GMASK (GTO|GSUBJECT|GENCODING|GTYPE|GCC|GBCC)
/* Mask of places from whence */
#define GNL 16 /* Print blank line after */
#define GDEL 32 /* Entity removed from list */
#define GCOMMA 64 /* detract puts in commas */
+#define GENCODING 128 /* Content-Transfer-Encoding: line */
+#define GTYPE 256 /* Content-Type: line */
/*
* Structure used to pass about the current
@@ -173,6 +175,8 @@ struct header {
struct name *h_to; /* Dynamic "To:" string */
char *h_from; /* User-specified "From:" string */
char *h_subject; /* Subject string */
+ char *h_encoding; /* Content-Transfer-Encoding string */
+ char *h_type; /* Content-Type string */
struct name *h_cc; /* Carbon copies string */
struct name *h_bcc; /* Blind carbon copies */
struct name *h_smopts; /* Sendmail options */
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.bin/mail/extern.h,v
retrieving revision 1.29
diff -u -p -r1.29 extern.h
--- extern.h 16 Sep 2018 02:38:57 -0000 1.29
+++ extern.h 19 Sep 2023 13:30:14 -0000
@@ -163,7 +163,7 @@ void load(char *);
struct var *
lookup(char *);
int mail(struct name *, struct name *, struct name *, struct name *,
- char *, char *);
+ char *, char *, char *, char *);
void mail1(struct header *, int);
void makemessage(FILE *, int);
void mark(int);
Index: mail.1
===================================================================
RCS file: /cvs/src/usr.bin/mail/mail.1,v
retrieving revision 1.83
diff -u -p -r1.83 mail.1
--- mail.1 31 Mar 2022 17:27:25 -0000 1.83
+++ mail.1 19 Sep 2023 13:30:15 -0000
@@ -45,6 +45,8 @@
.Op Fl c Ar list
.Op Fl r Ar from-addr
.Op Fl s Ar subject
+.Op Fl e Ar transfer-encoding
+.Op Fl y Ar content-type
.Ar to-addr ...
.Ek
.Nm mail
@@ -77,6 +79,8 @@ Causes
.Nm mail
to output all sorts of information useful for debugging
.Nm mail .
+.It Fl e Ar encoding
+Add a Content-Transfer-Enconding header on command line.
.It Fl E
Don't send messages with an empty body.
.It Fl f
@@ -133,6 +137,8 @@ except that locking is done.
Verbose mode.
The details of
delivery are displayed on the user's terminal.
+.It Fl y Ar content-type
+Add a Content-Type header on command line.
.El
.Ss Startup actions
At startup time,
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/main.c,v
retrieving revision 1.35
diff -u -p -r1.35 main.c
--- main.c 26 Jan 2021 18:21:47 -0000 1.35
+++ main.c 19 Sep 2023 13:30:15 -0000
@@ -103,6 +103,8 @@ main(int argc, char **argv)
struct name *to, *cc, *bcc, *smopts;
char *fromaddr;
char *subject;
+ char *encoding;
+ char *type;
char *ef;
char nosrc = 0;
char *rc;
@@ -136,7 +138,9 @@ main(int argc, char **argv)
smopts = NULL;
fromaddr = NULL;
subject = NULL;
- while ((i = getopt(argc, argv, "EINb:c:dfinr:s:u:v")) != -1) {
+ encoding = NULL;
+ type = NULL;
+ while ((i = getopt(argc, argv, "EINb:c:de:finr:s:u:vy:")) != -1) {
switch (i) {
case 'u':
/*
@@ -158,6 +162,10 @@ main(int argc, char **argv)
case 'd':
debug++;
break;
+ case 'e':
+ /* Set Content-Transfer-Enconding */
+ encoding = optarg;
+ break;
case 'r':
/*
* Set From: address
@@ -198,6 +206,10 @@ main(int argc, char **argv)
*/
assign("verbose", "");
break;
+ case 'y':
+ /* Set Content-Type */
+ type = optarg;
+ break;
case 'I':
/*
* We're interactive
@@ -241,8 +253,8 @@ main(int argc, char **argv)
/*
* Check for inconsistent arguments.
*/
- if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL ||
- fromaddr != NULL))
+ if (to == NULL && (subject != NULL || encoding != NULL ||
+ type != NULL || cc != NULL || bcc != NULL || fromaddr != NULL))
errx(1, "You must specify direct recipients with -s, -c, -b, "
"or -r");
/*
@@ -269,7 +281,7 @@ main(int argc, char **argv)
rc = "~/.mailrc";
load(expand(rc));
if (!rcvmode) {
- mail(to, cc, bcc, smopts, fromaddr, subject);
+ mail(to, cc, bcc, smopts, fromaddr, subject, encoding, type);
/*
* why wait?
*/
@@ -338,7 +350,8 @@ usage(void)
{
fprintf(stderr, "usage: %s [-dEIinv] [-b list] [-c list] "
- "[-r from-addr] [-s subject] to-addr ...\n", __progname);
+ "[-r from-addr] [-s subject] [-e encoding] [-y content-type ] "
+ "to-addr ...\n", __progname);
fprintf(stderr, " %s [-dEIiNnv] -f [file]\n", __progname);
fprintf(stderr, " %s [-dEIiNnv] [-u user]\n", __progname);
exit(1);
Index: names.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/names.c,v
retrieving revision 1.25
diff -u -p -r1.25 names.c
--- names.c 28 Jun 2019 13:35:02 -0000 1.25
+++ names.c 19 Sep 2023 13:30:15 -0000
@@ -252,7 +252,7 @@ outof(struct name *names, FILE *fo, stru
goto cant;
}
fprintf(fout, "From %s %s", myname, date);
- puthead(hp, fout, GTO|GSUBJECT|GCC|GNL);
+ puthead(hp, fout, GTO|GSUBJECT|GENCODING|GTYPE|GCC|GNL);
while ((c = getc(fo)) != EOF)
(void)putc(c, fout);
rewind(fo);
Index: send.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/send.c,v
retrieving revision 1.26
diff -u -p -r1.26 send.c
--- send.c 8 Mar 2023 04:43:11 -0000 1.26
+++ send.c 19 Sep 2023 13:30:15 -0000
@@ -279,13 +279,15 @@ statusput(struct message *mp, FILE *obuf
*/
int
mail(struct name *to, struct name *cc, struct name *bcc, struct name *smopts,
- char *fromaddr, char *subject)
+ char *fromaddr, char *subject, char *encoding, char *type)
{
struct header head;
head.h_to = to;
head.h_from = fromaddr;
head.h_subject = subject;
+ head.h_encoding = encoding;
+ head.h_type = type;
head.h_cc = cc;
head.h_bcc = bcc;
head.h_smopts = smopts;
@@ -306,6 +308,8 @@ sendmail(void *v)
head.h_to = extract(str, GTO);
head.h_from = NULL;
head.h_subject = NULL;
+ head.h_encoding = NULL;
+ head.h_type = NULL;
head.h_cc = NULL;
head.h_bcc = NULL;
head.h_smopts = NULL;
@@ -482,7 +486,7 @@ infix(struct header *hp, FILE *fi)
return(fi);
}
(void)rm(tempname);
- (void)puthead(hp, nfo, GTO|GSUBJECT|GCC|GBCC|GNL|GCOMMA);
+ (void)puthead(hp, nfo,
GTO|GSUBJECT|GENCODING|GTYPE|GCC|GBCC|GNL|GCOMMA);
c = getc(fi);
while (c != EOF) {
(void)putc(c, nfo);
@@ -508,7 +512,7 @@ infix(struct header *hp, FILE *fi)
}
/*
- * Dump the to, subject, cc header on the
+ * Dump the to, subject, encoding, content-type, cc header on the
* passed file buffer.
*/
int
@@ -525,6 +529,12 @@ puthead(struct header *hp, FILE *fo, int
fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++;
if (hp->h_subject != NULL && w & GSUBJECT)
fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++;
+ if (hp->h_encoding != NULL && w & GENCODING)
+ fprintf(fo, "Content-Transfer-Encoding: %s\n",
+ hp->h_encoding), gotcha++;
+ if (hp->h_type != NULL && w & GTYPE)
+ fprintf(fo, "Content-Type: %s\n",
+ hp->h_type), gotcha++;
if (hp->h_cc != NULL && w & GCC)
fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++;
if (hp->h_bcc != NULL && w & GBCC)
Index: tty.c
===================================================================
RCS file: /cvs/src/usr.bin/mail/tty.c,v
retrieving revision 1.23
diff -u -p -r1.23 tty.c
--- tty.c 8 Mar 2023 04:43:11 -0000 1.23
+++ tty.c 19 Sep 2023 13:30:15 -0000
@@ -132,6 +132,18 @@ grabh(struct header *hp, int gflags)
goto out;
hp->h_subject = s;
}
+ if (gflags & GENCODING) {
+ s = readtty("Content-Transfer-Encoding: ", hp->h_encoding);
+ if (s == NULL)
+ goto out;
+ hp->h_encoding = s;
+ }
+ if (gflags & GTYPE) {
+ s = readtty("Content-Type: ", hp->h_type);
+ if (s == NULL)
+ goto out;
+ hp->h_type = s;
+ }
if (gflags & GCC) {
s = readtty("Cc: ", detract(hp->h_cc, 0));
if (s == NULL)
--
Walter