pEp-standards #6
2 changed files with 47 additions and 2 deletions
11
README.md
11
README.md
|
@ -1,7 +1,14 @@
|
|||
# gpgmymail
|
||||
|
||||
Takes an email from stdin and encrypts it using the recipient's PGP key,
|
||||
provided as an argument when calling the script.
|
||||
Takes an email from stdin and encrypts it to stdout using the recipient's PGP
|
||||
key, provided as an argument when calling the script.
|
||||
|
||||
Leaves a `X-gpgmymail-Status` header on the email, which has the following
|
||||
statuses:
|
||||
|
||||
* `entered` - the email has entered the encryption function, but not been
|
||||
encrypted
|
||||
* `encrypted` - the encryption function has encrypted the email
|
||||
|
||||
Written to be a Sieve filter to be used with `sieve_extprograms`. Can be used
|
||||
in a Sieve filter e.g.:
|
||||
|
|
38
gpgmymail
38
gpgmymail
|
@ -24,6 +24,12 @@ works well for emails created with this tool. When encrypting, the tool
|
|||
preserves all headers in the original email in the encrypted part, and
|
||||
copies relevant headers to the output. When decrypting, any headers are
|
||||
ignored, and only the encrypted headers are restored.
|
||||
|
||||
Emails exiting this script will have the 'X-gpgmymail-Status' header, which has
|
||||
the following options:
|
||||
|
||||
- entered: the email has entered the encrypt() function
|
||||
- encrypted: the email has been encrypted
|
||||
"""
|
||||
|
||||
import argparse
|
||||
|
@ -42,6 +48,7 @@ import gnupg
|
|||
|
||||
# constants
|
||||
DEFAULT_ENCODING='utf-8' # default is latin-1 which fails w some unicode chars
|
||||
PEP_SUBJECT='=?utf-8?Q?p=E2=89=A1p?='
|
||||
|
||||
def is_message_encrypted(message: email.message.Message) -> bool:
|
||||
"""Determines whether or not an email message is encrypted.
|
||||
|
@ -169,6 +176,27 @@ def decode_email(message: email.message.Message) -> email.message.Message:
|
|||
|
||||
return decoded_bytes_to_return_value(decoded_bytes)
|
||||
|
||||
def set_email_header(
|
||||
message: email.message.Message,
|
||||
name: str,
|
||||
value: str
|
||||
) -> None:
|
||||
"""
|
||||
Set the header of an email Message. Will either replace the first instance
|
||||
of the header, or if the header is not present, will add the header.
|
||||
|
||||
Note: Python passes objects as references, so there is no need for a return
|
||||
value.
|
||||
|
||||
:param message: the Message object to be modified
|
||||
:param name: the email header to set
|
||||
:param value: the value to set the header to
|
||||
"""
|
||||
if message.get(name):
|
||||
message.replace_header(name, value)
|
||||
else:
|
||||
message.add_header(name, value)
|
||||
|
||||
def encrypt(
|
||||
message: email.message.Message,
|
||||
recipients: typing.List[str],
|
||||
|
@ -198,6 +226,9 @@ def encrypt(
|
|||
|
||||
:return: The encrypted email as a string"""
|
||||
|
||||
# mark the email as having passed through us
|
||||
set_email_header(message, 'X-gpgmymail-Status', 'entered')
|
||||
|
||||
# exclusion criteria:
|
||||
# some mail clients like Thunderbird don't like twice-encrypted emails,
|
||||
# so we return the message as-is if it's already encrypted
|
||||
|
@ -254,6 +285,13 @@ def encrypt(
|
|||
if key.lower() not in headers_not_to_override:
|
||||
encmsg[key] = value
|
||||
|
||||
# mark as confirming to pEp: https://blog.jak-linux.org/2019/06/13/encrypted-email-storage/#pretty-easy-privacy-pp
|
||||
set_email_header(encmsg, 'Subject', PEP_SUBJECT)
|
||||
set_email_header(encmsg, 'X-pEp-Version', '2.1')
|
||||
|
||||
# we have encrypted the email, set our gpgmymail header appropriately
|
||||
set_email_header(encmsg, 'X-gpgmymail-Status', 'encrypted')
|
||||
|
||||
return encmsg.as_string()
|
||||
|
||||
def decrypt(message: email.message.Message, *, encoding: str = DEFAULT_ENCODING) -> str:
|
||||
|
|
Loading…
Reference in a new issue