{"thread":{"id":"50914","subject":"[PATCH] send-email: default to quoted-printable when CR is present","startedAt":"2019-04-10T23:35:07Z","lastAt":"2019-04-13T22:46:13Z","messageCount":4,"participants":["brian m. carlson","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"373621","messageId":"20190410233450.765424-1-sandals@crustytoothpaste.net","threadId":"50914","inReplyTo":null,"subject":"[PATCH] send-email: default to quoted-printable when CR is present","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2019-04-10T23:34:50Z","receivedAt":"2019-04-10T23:35:07Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"In 7a36987fff (\"send-email: add an auto option for transfer encoding\",\n2018-07-08), git send-email learned how to automatically determine the\ntransfer encoding for a patch. However, the only criterion considered\nwas the length of the lines.\n\nAnother case we need to consider is that of carriage returns. Because\nemails have CRLF endings when canonicalized, we don't want to write raw\ncarriage returns into a patch, lest they be stripped off as an artifact\nof the transport. Ensure that we choose quoted-printable encoding if the\npatch we're sending contains carriage returns.\n\nNote that we are guaranteed to always correctly encode carriage returns\nwhen writing quoted-printable since we explicitly specify the line\nending as \"\\n\", forcing MIME::QuotedPrint to encode our carriage return\nas \"=OD\".\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\n git-send-email.perl   |  2 +-\n t/t9001-send-email.sh | 14 ++++++++++++++\n 2 files changed, 15 insertions(+), 1 deletion(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 8200d58cdc..751cabf479 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -1872,7 +1872,7 @@ sub apply_transfer_encoding {\n \t$message = MIME::Base64::decode($message)\n \t\tif ($from eq 'base64');\n \n-\t$to = ($message =~ /.{999,}/) ? 'quoted-printable' : '8bit'\n+\t$to = ($message =~ /(?:.{999,}|\\r)/) ? 'quoted-printable' : '8bit'\n \t\tif $to eq 'auto';\n \n \tdie __(\"cannot send message as 7bit\")\ndiff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh\nindex ee1efcc59d..1e3ac3c384 100755\n--- a/t/t9001-send-email.sh\n+++ b/t/t9001-send-email.sh\n@@ -481,6 +481,20 @@ test_expect_success $PREREQ 'long lines with auto encoding are quoted-printable'\n \tgrep \"Content-Transfer-Encoding: quoted-printable\" msgtxt1\n '\n \n+test_expect_success $PREREQ 'carriage returns with auto encoding are quoted-printable' '\n+\tclean_fake_sendmail &&\n+\tcp $patches cr.patch &&\n+\tprintf \"this is a line\\r\\n\" >>cr.patch &&\n+\tgit send-email \\\n+\t\t--from=\"Example <nobody@example.com>\" \\\n+\t\t--to=nobody@example.com \\\n+\t\t--smtp-server=\"$(pwd)/fake.sendmail\" \\\n+\t\t--transfer-encoding=auto \\\n+\t\t--no-validate \\\n+\t\tcr.patch &&\n+\tgrep \"Content-Transfer-Encoding: quoted-printable\" msgtxt1\n+'\n+\n for enc in auto quoted-printable base64\n do\n \ttest_expect_success $PREREQ \"--validate passes with encoding $enc\" '\n"},{"id":"373671","messageId":"CAPig+cT5-r=QqVDcD7viJj0-fPp+6OjnKq8aP4NLwKNdrAHFKw@mail.gmail.com","threadId":"50914","inReplyTo":"20190410233450.765424-1-sandals@crustytoothpaste.net","subject":"Re: [PATCH] send-email: default to quoted-printable when CR is present","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-04-11T17:44:06Z","receivedAt":"2019-04-11T17:44:20Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Apr 10, 2019 at 7:35 PM brian m. carlson\n<sandals@crustytoothpaste.net> wrote:\n> [...]\n> Note that we are guaranteed to always correctly encode carriage returns\n> when writing quoted-printable since we explicitly specify the line\n> ending as \"\\n\", forcing MIME::QuotedPrint to encode our carriage return\n> as \"=OD\".\n\ns/=OD/=0D/\n\n(That is, replace capital \"O\" with zero \"0\".)\n"},{"id":"373696","messageId":"20190412000107.GK12419@genre.crustytoothpaste.net","threadId":"50914","inReplyTo":"CAPig+cT5-r=QqVDcD7viJj0-fPp+6OjnKq8aP4NLwKNdrAHFKw@mail.gmail.com","subject":"Re: [PATCH] send-email: default to quoted-printable when CR is present","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2019-04-12T00:01:07Z","receivedAt":"2019-04-12T00:01:19Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On Thu, Apr 11, 2019 at 01:44:06PM -0400, Eric Sunshine wrote:\n> On Wed, Apr 10, 2019 at 7:35 PM brian m. carlson\n> <sandals@crustytoothpaste.net> wrote:\n> > [...]\n> > Note that we are guaranteed to always correctly encode carriage returns\n> > when writing quoted-printable since we explicitly specify the line\n> > ending as \"\\n\", forcing MIME::QuotedPrint to encode our carriage return\n> > as \"=OD\".\n> \n> s/=OD/=0D/\n> \n> (That is, replace capital \"O\" with zero \"0\".)\n\nAh, yes. Thanks for pointing that out.\n\nI'll wait to see if there's any other feedback and then reroll.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"373806","messageId":"20190413224551.882125-1-sandals@crustytoothpaste.net","threadId":"50914","inReplyTo":"20190410233450.765424-1-sandals@crustytoothpaste.net","subject":"[PATCH v2] send-email: default to quoted-printable when CR is present","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2019-04-13T22:45:51Z","receivedAt":"2019-04-13T22:46:13Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"In 7a36987fff (\"send-email: add an auto option for transfer encoding\",\n2018-07-08), git send-email learned how to automatically determine the\ntransfer encoding for a patch. However, the only criterion considered\nwas the length of the lines.\n\nAnother case we need to consider is that of carriage returns. Because\nemails have CRLF endings when canonicalized, we don't want to write raw\ncarriage returns into a patch, lest they be stripped off as an artifact\nof the transport. Ensure that we choose quoted-printable encoding if the\npatch we're sending contains carriage returns.\n\nNote that we are guaranteed to always correctly encode carriage returns\nwhen writing quoted-printable since we explicitly specify the line\nending as \"\\n\", forcing MIME::QuotedPrint to encode our carriage return\nas \"=0D\".\n\nSigned-off-by: brian m. carlson <sandals@crustytoothpaste.net>\n---\nChanges from v1:\n* Fix typo \"=OD\" for \"=0D\".\n\n git-send-email.perl   |  2 +-\n t/t9001-send-email.sh | 14 ++++++++++++++\n 2 files changed, 15 insertions(+), 1 deletion(-)\n\ndiff --git a/git-send-email.perl b/git-send-email.perl\nindex 8200d58cdc..751cabf479 100755\n--- a/git-send-email.perl\n+++ b/git-send-email.perl\n@@ -1872,7 +1872,7 @@ sub apply_transfer_encoding {\n \t$message = MIME::Base64::decode($message)\n \t\tif ($from eq 'base64');\n \n-\t$to = ($message =~ /.{999,}/) ? 'quoted-printable' : '8bit'\n+\t$to = ($message =~ /(?:.{999,}|\\r)/) ? 'quoted-printable' : '8bit'\n \t\tif $to eq 'auto';\n \n \tdie __(\"cannot send message as 7bit\")\ndiff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh\nindex ee1efcc59d..1e3ac3c384 100755\n--- a/t/t9001-send-email.sh\n+++ b/t/t9001-send-email.sh\n@@ -481,6 +481,20 @@ test_expect_success $PREREQ 'long lines with auto encoding are quoted-printable'\n \tgrep \"Content-Transfer-Encoding: quoted-printable\" msgtxt1\n '\n \n+test_expect_success $PREREQ 'carriage returns with auto encoding are quoted-printable' '\n+\tclean_fake_sendmail &&\n+\tcp $patches cr.patch &&\n+\tprintf \"this is a line\\r\\n\" >>cr.patch &&\n+\tgit send-email \\\n+\t\t--from=\"Example <nobody@example.com>\" \\\n+\t\t--to=nobody@example.com \\\n+\t\t--smtp-server=\"$(pwd)/fake.sendmail\" \\\n+\t\t--transfer-encoding=auto \\\n+\t\t--no-validate \\\n+\t\tcr.patch &&\n+\tgrep \"Content-Transfer-Encoding: quoted-printable\" msgtxt1\n+'\n+\n for enc in auto quoted-printable base64\n do\n \ttest_expect_success $PREREQ \"--validate passes with encoding $enc\" '\n"}]}