From 06abbc0edda0eb79ba3afd28ff7f8e9ec366dee5 Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Thu, 2 Jun 2022 19:37:06 +0200 Subject: [PATCH 1/3] Don't break Content-Type header with LF --- gpg-mailgate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpg-mailgate.py b/gpg-mailgate.py index 879a27a..0b35bbd 100755 --- a/gpg-mailgate.py +++ b/gpg-mailgate.py @@ -221,7 +221,7 @@ def encrypt_all_payloads_mime( message, gpg_to_cmdline ): if 'Content-Type' in message: message.replace_header('Content-Type', "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary) else: - message['Content-Type'] = "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary + message['Content-Type'] = "multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"%s\"\n" % boundary return [ pgp_ver_part, encrypt_payload(encrypted_part, gpg_to_cmdline, check_nested) ] From 65d2a774867226db9bbfdc3c1688a6a0bc284c71 Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Thu, 2 Jun 2022 19:43:27 +0200 Subject: [PATCH 2/3] Don't break Content-Type header with LF - part 2 --- gpg-mailgate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpg-mailgate.py b/gpg-mailgate.py index 0b35bbd..30b8337 100755 --- a/gpg-mailgate.py +++ b/gpg-mailgate.py @@ -219,7 +219,7 @@ def encrypt_all_payloads_mime( message, gpg_to_cmdline ): # This also modifies the boundary in the body of the message, ie it gets parsed. if 'Content-Type' in message: - message.replace_header('Content-Type', "multipart/encrypted; protocol=\"application/pgp-encrypted\";\nboundary=\"%s\"\n" % boundary) + message.replace_header('Content-Type', "multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"%s\"\n" % boundary) else: message['Content-Type'] = "multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"%s\"\n" % boundary From 937046eb1739483896dc21c23c3fb032f42395b9 Mon Sep 17 00:00:00 2001 From: "Piotr F. Mieszkowski" Date: Thu, 2 Jun 2022 19:56:32 +0200 Subject: [PATCH 3/3] Use CRLF for line-endings Mail RFCs use CRLF for line endings and it turns out things may break in strange ways if only LF is used. --- gpg-mailgate.py | 22 +++++++++++----------- lacre/text.py | 3 +++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/gpg-mailgate.py b/gpg-mailgate.py index 30b8337..202f35a 100755 --- a/gpg-mailgate.py +++ b/gpg-mailgate.py @@ -181,7 +181,7 @@ def encrypt_all_payloads_inline( message, gpg_to_cmdline ): def encrypt_all_payloads_mime( message, gpg_to_cmdline ): # Convert a plain text email into PGP/MIME attachment style. Modeled after enigmail. pgp_ver_part = email.message.Message() - pgp_ver_part.set_payload("Version: 1\n") + pgp_ver_part.set_payload("Version: 1"+text.EOL) pgp_ver_part.set_type("application/pgp-encrypted") pgp_ver_part.set_param('PGP/MIME version identification', "", 'Content-Description' ) @@ -200,10 +200,10 @@ def encrypt_all_payloads_mime( message, gpg_to_cmdline ): additionalSubHeader="" encoding = sys.getdefaultencoding() if 'Content-Type' in message and not message['Content-Type'].startswith('multipart'): - additionalSubHeader="Content-Type: "+message['Content-Type']+"\n" + additionalSubHeader="Content-Type: "+message['Content-Type']+text.EOL (base, encoding) = text.parse_content_type(message['Content-Type']) LOG.debug(f"Identified encoding as {encoding}") - encrypted_part.set_payload(additionalSubHeader+"\n" +message.get_payload(decode=True).decode(encoding)) + encrypted_part.set_payload(additionalSubHeader+text.EOL +message.get_payload(decode=True).decode(encoding)) check_nested = True else: processed_payloads = generate_message_from_payloads(message) @@ -219,9 +219,9 @@ def encrypt_all_payloads_mime( message, gpg_to_cmdline ): # This also modifies the boundary in the body of the message, ie it gets parsed. if 'Content-Type' in message: - message.replace_header('Content-Type', "multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"%s\"\n" % boundary) + message.replace_header('Content-Type', f"multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"{boundary}\""+text.EOL) else: - message['Content-Type'] = "multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"%s\"\n" % boundary + message['Content-Type'] = f"multipart/encrypted; protocol=\"application/pgp-encrypted\"; boundary=\"{boundary}\""+text.EOL return [ pgp_ver_part, encrypt_payload(encrypted_part, gpg_to_cmdline, check_nested) ] @@ -289,17 +289,17 @@ def smime_encrypt( raw_message, recipients ): p7 = s.encrypt( BIO.MemoryBuffer( raw_message.as_string() ) ) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() - out.write('From: ' + from_addr + '\n') - out.write('To: ' + raw_message['To'] + '\n') + out.write('From: ' + from_addr + text.EOL) + out.write('To: ' + raw_message['To'] + text.EOL) if raw_message['Cc']: - out.write('Cc: ' + raw_message['Cc'] + '\n') + out.write('Cc: ' + raw_message['Cc'] + text.EOL) if raw_message['Bcc']: - out.write('Bcc: ' + raw_message['Bcc'] + '\n') + out.write('Bcc: ' + raw_message['Bcc'] + text.EOL) if raw_message['Subject']: - out.write('Subject: '+ raw_message['Subject'] + '\n') + out.write('Subject: '+ raw_message['Subject'] + text.EOL) if conf.config_item_equals('default', 'add_header', 'yes'): - out.write('X-GPG-Mailgate: Encrypted by GPG Mailgate\n') + out.write('X-GPG-Mailgate: Encrypted by GPG Mailgate' + text.EOL) s.write(out, p7) diff --git a/lacre/text.py b/lacre/text.py index 4459670..9b3247f 100644 --- a/lacre/text.py +++ b/lacre/text.py @@ -1,5 +1,8 @@ import sys +# The standard way to encode line-ending in email: +EOL = "\r\n" + PGP_INLINE_BEGIN = b"-----BEGIN PGP MESSAGE-----" PGP_INLINE_END = b"-----END PGP MESSAGE-----"