format-patch: make cover letters always text/plain

When formatting a series of patches using --attach and --cover-letter, the cover letter lacks the closing MIME boundary, violating RFC 2046. Certain clients, such as Thunderbird, discard the message body in such a case. Since the cover letter is just one part and sending it as multipart/mixed is not very useful, always emit it as text/plain, avoiding the boundary problem altogether. Reported-by: Patrick Hemmer <git@stormcloud9.net> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed May 2, 2018 at 02:20 UTC 50cd54ef4e6f4279683b61417a35de7297b55b9d
4 files changed +16 -5
builtin/log.c
+1 -1
@@ -1019,7 +1019,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
1019 open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
1020 return;
1021
1022 - log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte);
1022 + log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
1023
1024 for (i = 0; !need_8bit_cte && i < nr; i++) {
1025 const char *buf = get_commit_buffer(list[i], NULL);
log-tree.c
+4 -3
@@ -362,7 +362,8 @@ void fmt_output_email_subject(struct strbuf *sb, struct rev_info *opt)
362
363 void log_write_email_headers(struct rev_info *opt, struct commit *commit,
364 const char **extra_headers_p,
365 - int *need_8bit_cte_p)
365 + int *need_8bit_cte_p,
366 + int maybe_multipart)
367 {
368 const char *extra_headers = opt->extra_headers;
369 const char *name = oid_to_hex(opt->zero_commit ?
@@ -385,7 +386,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
386 opt->ref_message_ids->items[i].string);
387 graph_show_oneline(opt->graph);
388 }
388 - if (opt->mime_boundary) {
389 + if (opt->mime_boundary && maybe_multipart) {
390 static char subject_buffer[1024];
391 static char buffer[1024];
392 struct strbuf filename = STRBUF_INIT;
@@ -610,7 +611,7 @@ void show_log(struct rev_info *opt)
611
612 if (cmit_fmt_is_mail(opt->commit_format)) {
613 log_write_email_headers(opt, commit, &extra_headers,
613 - &ctx.need_8bit_cte);
614 + &ctx.need_8bit_cte, 1);
615 ctx.rev = opt;
616 ctx.print_email_subject = 1;
617 } else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
log-tree.h
+2 -1
@@ -27,7 +27,8 @@ void format_decorations_extended(struct strbuf *sb, const struct commit *commit,
27 void show_decorations(struct rev_info *opt, struct commit *commit);
28 void log_write_email_headers(struct rev_info *opt, struct commit *commit,
29 const char **extra_headers_p,
30 - int *need_8bit_cte_p);
30 + int *need_8bit_cte_p,
31 + int maybe_multipart);
32 void load_ref_decorations(struct decoration_filter *filter, int flags);
33
34 #define FORMAT_PATCH_NAME_MAX 64
t/t4014-format-patch.sh
+9
@@ -1661,6 +1661,15 @@ test_expect_success 'format-patch --base with --attach' '
1661 test_write_lines 1 2 >expect &&
1662 test_cmp expect actual
1663 '
1664 +test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
1665 + test_when_finished "rm -fr patches" &&
1666 + git format-patch -o patches --cover-letter --attach=mimemime --base=HEAD~ -1 &&
1667 + ! egrep "^--+mimemime" patches/0000*.patch &&
1668 + egrep "^--+mimemime$" patches/0001*.patch >output &&
1669 + test_line_count = 2 output &&
1670 + egrep "^--+mimemime--$" patches/0001*.patch >output &&
1671 + test_line_count = 1 output
1672 +'
1673
1674 test_expect_success 'format-patch --pretty=mboxrd' '
1675 sp=" " &&