~sircmpwn/core.sr.ht

8cea995b8f63b2603322bb6218abbf7ba38dd842 — Conrad Hoffmann 5 months ago 3e97507
Remove dependency on PGPy

It's mostly unused by now. The only small gotcha is that we stop signing
the error email (sent when catching otherwise unhandled exceptions).

Signed-off-by: Conrad Hoffmann <ch@bitfehler.net>
2 files changed, 8 insertions(+), 61 deletions(-)

M setup.py
M srht/email.py
M setup.py => setup.py +0 -1
@@ 34,7 34,6 @@ setup(
      'bleach',
      'requests',
      'BeautifulSoup4',
      'pgpy',
      'pygments',
      'cryptography',
      'prometheus_client',

M srht/email.py => srht/email.py +8 -60
@@ 7,13 7,9 @@ from srht.crypto import encrypt_request_authorization
from srht.config import cfg, cfgi, cfgb, get_origin
import base64
import smtplib
import pgpy
import requests
import traceback

site_key = cfg("mail", "pgp-privkey", default=None)
if site_key:
    site_key, _ = pgpy.PGPKey.from_file(site_key)
smtp_host = cfg("mail", "smtp-host", default=None)
smtp_port = cfgi("mail", "smtp-port", default=None)
smtp_user = cfg("mail", "smtp-user", default=None)


@@ 24,17 20,6 @@ error_to = cfg("mail", "error-to", default=None)
error_from = cfg("mail", "error-from", default=None)
meta_url = get_origin("meta.sr.ht")

def micalg_for(hash_alg):
    return {
        pgpy.constants.HashAlgorithm.MD5: "pgp-md5",
        pgpy.constants.HashAlgorithm.SHA1: "pgp-sha1",
        pgpy.constants.HashAlgorithm.RIPEMD160: "pgp-ripemd160",
        pgpy.constants.HashAlgorithm.SHA256: "pgp-sha256",
        pgpy.constants.HashAlgorithm.SHA384: "pgp-sha384",
        pgpy.constants.HashAlgorithm.SHA512: "pgp-sha512",
        pgpy.constants.HashAlgorithm.SHA224: "pgp-sha224",
    }[hash_alg]

def lookup_key(user):
    """
    Looks up the preferred PGP key for the given username and their OAuth token.


@@ 59,7 44,7 @@ def format_headers(**headers):
        headers['Reply-To'] = formataddr(parseaddr(headers['Reply-To']))
    return headers

def prepare_email(body, to, subject, encrypt_key=None, **headers):
def prepare_email(body, to, subject, **headers):
    headers['Subject'] = subject
    headers.setdefault('From', smtp_from or smtp_user)
    headers.setdefault('To', to)


@@ 68,49 53,12 @@ def prepare_email(body, to, subject, encrypt_key=None, **headers):
    headers = format_headers(**headers)

    text_part = MIMEText(body)
    multipart = MIMEMultipart()
    multipart.attach(text_part)

    if site_key:
        signature = site_key.sign(text_part.as_string().replace('\n', '\r\n'))
        sig_part = Message()
        sig_part['Content-Type'] = 'application/pgp-signature; name="signature.asc"'
        sig_part['Content-Description'] = 'OpenPGP digital signature'
        sig_part.set_payload(str(signature))

        multipart = MIMEMultipart(_subtype="signed",
                micalg=micalg_for(signature.hash_algorithm),
                protocol="application/pgp-signature")
        multipart.attach(text_part)
        multipart.attach(sig_part)
    else:
        multipart = MIMEMultipart()
        multipart.attach(text_part)

    if not encrypt_key:
        for key in headers:
            multipart[key] = headers[key]
        return multipart
    else:
        pubkey, _ = pgpy.PGPKey.from_blob(encrypt_key.replace('\r', '').encode())
        pgp_msg = pgpy.PGPMessage.new(multipart.as_string(unixfrom=False))
        if pubkey.get_uid(to):
            # https://github.com/SecurityInnovation/PGPy/issues/367
            encrypted = str(pubkey.encrypt(pgp_msg, user=to))
        else:
            encrypted = str(pubkey.encrypt(pgp_msg))
        ver_part = Message()
        ver_part['Content-Type'] = 'application/pgp-encrypted'
        ver_part.set_payload("Version: 1")
        enc_part = Message()
        enc_part['Content-Type'] = 'application/octet-stream; name="message.asc"'
        enc_part['Content-Description'] = 'OpenPGP encrypted message'
        enc_part.set_payload(encrypted)
        wrapped = MIMEMultipart(_subtype="encrypted", protocol="application/pgp-encrypted")
        wrapped.attach(ver_part)
        wrapped.attach(enc_part)
        for key in headers:
            wrapped[key] = headers[key]
        return wrapped

    for key in headers:
        multipart[key] = headers[key]
    return multipart

def start_smtp():
    if smtp_encryption == 'tls':


@@ 125,8 73,8 @@ def start_smtp():
    return smtp


def send_email(body, to, subject, encrypt_key=None, **headers):
    message = prepare_email(body, to, subject, encrypt_key, **headers)
def send_email(body, to, subject, **headers):
    message = prepare_email(body, to, subject, **headers)
    if not smtp_host:
        print("Not configured to send email. The email we tried to send was:")
        print(message)