.I codeset
.RB "| " \-notextcodeset ]
.RB [ \-reformat " | " \-noreformat ]
+.RB [ \-replacetextplain " | " \-noreplacetextplain ]
.RB [ \-fixboundary " | " \-nofixboundary ]
.RB [ \-fixcte " | " \-nofixcte ]
.RB [ \-file
multipart/alternative part, if present. If not, it creates a
multipart/alternative part.
.PP
+The
+.B \-replacetextplain
+switch broadens the applicability of
+.B \-reformat
+by always replacing a corresponding text/plain part, if one exists.
+If
+.B \-verbose
+if enabled, the replacement will be shown as two steps: a removal of
+the text/plain part followed by the usual insertion of a new part.
+.PP
.B \-reformat
requires a profile entry for each text part subtype to be reformatted.
The mhfixmsg-format-text/subtype profile entries are based on external
.RB ` "\-decodetext 8bit"'
.RB ` \-notextcodeset '
.RB ` \-reformat '
+.RB ` \-noreplacetextplain '
.RB ` \-fixboundary '
.RB ` \-fixcte '
.RB ` \-noverbose '
-nodecodetext
-[no]textcodeset
-[no]reformat
+ -[no]replacetextplain
-[no]fixboundary
-[no]fixcte
-file file
check "$expected" "$actual"
+# check -replacetextplain
+cat >"$expected" <<EOF
+To: recipient@example.com
+From: sender@example.com
+Subject: mhfixmsg replacement of bad text/plain part test
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="----=_Part_876302"
+
+------=_Part_876302
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: 8bit
+
+Yes, the text/plain part really was empty.
+
+------=_Part_876302
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+<html><head>
+<title>eticket</title>
+</head>
+<body>
+ Yes, the text/plain part really was empty.
+</body>
+</html>
+
+------=_Part_876302--
+EOF
+
+cat >`mhpath new` <<'EOF'
+To: recipient@example.com
+From: sender@example.com
+Subject: mhfixmsg replacement of bad text/plain part test
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="----=_Part_876302"
+
+------=_Part_876302
+Content-Type: text/plain; charset="iso-8859-15"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline
+
+
+
+------=_Part_876302
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+<html><head>
+<title>eticket</title>
+</head>
+<body>
+ Yes, the text/plain part really was empty.
+</body>
+</html>
+
+------=_Part_876302--
+EOF
+
+mhfixmsg last -replacetextplain -outfile "$actual"
+check "$expected" "$actual"
+
+# check -noreplacetextplain
+cat >"$expected" <<EOF
+To: recipient@example.com
+From: sender@example.com
+Subject: mhfixmsg replacement of bad text/plain part test
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="----=_Part_876302"
+
+------=_Part_876302
+Content-Type: text/plain; charset="iso-8859-15"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline
+
+
+
+------=_Part_876302
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline
+
+<html><head>
+<title>eticket</title>
+</head>
+<body>
+ Yes, the text/plain part really was empty.
+</body>
+</html>
+
+------=_Part_876302--
+EOF
+
+mhfixmsg last -replacetextplain -noreplacetextplain -outfile "$actual"
+check "$expected" "$actual"
+
+
# check rmmproc
cat >"$MH_TEST_DIR/Mail/rmmproc" <<'EOF'
mv "$1" "$1.backup"
X("notextcodeset", 0, NTEXTCODESETSW) \
X("reformat", 0, REFORMATSW) \
X("noreformat", 0, NREFORMATSW) \
+ X("replacetextplain", 0, REPLACETEXTPLAINSW) \
+ X("noreplacetextplain", 0, NREPLACETEXTPLAINSW) \
X("fixboundary", 0, FIXBOUNDARYSW) \
X("nofixboundary", 0, NFIXBOUNDARYSW) \
X("fixcte", 0, FIXCTESW) \
int fixboundary;
int fixcte;
int reformat;
+ int replacetextplain;
int decodetext;
char *textcodeset;
} fix_transformations;
static char *update_attr (char *, const char *, const char *e);
static int fix_multipart_cte (CT, int *);
static int set_ce (CT, int);
-static int ensure_text_plain (CT *, CT, int *);
+static int ensure_text_plain (CT *, CT, int *, int);
static CT build_text_plain_part (CT);
static CT divide_part (CT);
static void copy_ctinfo (CI, CI);
int status = OK;
fix_transformations fx;
fx.reformat = fx.fixcte = fx.fixboundary = 1;
+ fx.replacetextplain = 0;
fx.decodetext = CE_8BIT;
fx.textcodeset = NULL;
case NREFORMATSW:
fx.reformat = 0;
continue;
+ case REPLACETEXTPLAINSW:
+ fx.replacetextplain = 1;
+ continue;
+ case NREPLACETEXTPLAINSW:
+ fx.replacetextplain = 0;
+ continue;
case FILESW:
if (! (cp = *argp++) || (*cp == '-' && cp[1]))
status = fix_multipart_cte (*ctp, &message_mods);
}
if (status == OK && fx->reformat) {
- status = ensure_text_plain (ctp, NULL, &message_mods);
+ status =
+ ensure_text_plain (ctp, NULL, &message_mods, fx->replacetextplain);
}
if (status == OK && fx->decodetext) {
status = decode_text_parts (*ctp, fx->decodetext, &message_mods);
/* Make sure each text part has a corresponding text/plain part. */
static int
-ensure_text_plain (CT *ct, CT parent, int *message_mods) {
+ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) {
int status = OK;
switch ((*ct)->c_type) {
if (parent && parent->c_type == CT_MULTIPART &&
parent->c_subtype == MULTI_ALTERNATE) {
struct multipart *mp = (struct multipart *) parent->c_ctparams;
- struct part *part;
+ struct part *part, *prev;
int new_subpart_number = 1;
/* See if there is a sibling text/plain. */
- for (part = mp->mp_parts; part; part = part->mp_next) {
+ for (prev = part = mp->mp_parts; part; part = part->mp_next) {
++new_subpart_number;
if (part->mp_part->c_type == CT_TEXT &&
part->mp_part->c_subtype == TEXT_PLAIN) {
- has_text_plain = 1;
+ if (replacetextplain) {
+ struct part *old_part;
+ if (part == mp->mp_parts) {
+ old_part = mp->mp_parts;
+ mp->mp_parts = part->mp_next;
+ } else {
+ old_part = prev->mp_next;
+ prev->mp_next = part->mp_next;
+ }
+ if (verbosw) {
+ report (parent->c_partno, parent->c_file,
+ "remove text/plain part %s",
+ old_part->mp_part->c_partno);
+ }
+ free_content (old_part->mp_part);
+ free (old_part);
+ } else {
+ has_text_plain = 1;
+ }
break;
}
+ prev = part;
}
if (! has_text_plain) {
for (part = mp->mp_parts; status == OK && part; part = part->mp_next) {
if ((*ct)->c_type == CT_MULTIPART) {
- status = ensure_text_plain (&part->mp_part, *ct, message_mods);
+ status = ensure_text_plain (&part->mp_part, *ct, message_mods,
+ replacetextplain);
}
}
break;
struct exbody *e;
e = (struct exbody *) (*ct)->c_ctparams;
- status = ensure_text_plain (&e->eb_content, *ct, message_mods);
+ status = ensure_text_plain (&e->eb_content, *ct, message_mods,
+ replacetextplain);
}
break;
}