encrypt forwarded emails to gpg-enabled mailbox

This commit is contained in:
Son NK 2020-03-08 23:07:23 +01:00
parent 5d5131f32c
commit 612e4f6717
2 changed files with 41 additions and 1 deletions

View File

@ -4,9 +4,11 @@ from app.config import GNUPGHOME
gpg = gnupg.GPG(gnupghome=GNUPGHOME) gpg = gnupg.GPG(gnupghome=GNUPGHOME)
class PGPException(Exception): class PGPException(Exception):
pass pass
def load_public_key(public_key: str) -> str: def load_public_key(public_key: str) -> str:
"""Load a public key into keyring and return the fingerprint. If error, raise Exception""" """Load a public key into keyring and return the fingerprint. If error, raise Exception"""
import_result = gpg.import_keys(public_key) import_result = gpg.import_keys(public_key)

View File

@ -31,13 +31,17 @@ It should contain the following info:
""" """
import time import time
from email import encoders
from email.message import Message from email.message import Message
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.parser import Parser from email.parser import Parser
from email.policy import SMTPUTF8 from email.policy import SMTPUTF8
from smtplib import SMTP from smtplib import SMTP
from typing import Optional from typing import Optional
from aiosmtpd.controller import Controller from aiosmtpd.controller import Controller
import gnupg
from app.config import ( from app.config import (
EMAIL_DOMAIN, EMAIL_DOMAIN,
@ -47,6 +51,7 @@ from app.config import (
ADMIN_EMAIL, ADMIN_EMAIL,
SUPPORT_EMAIL, SUPPORT_EMAIL,
POSTFIX_SUBMISSION_TLS, POSTFIX_SUBMISSION_TLS,
GNUPGHOME,
) )
from app.email_utils import ( from app.email_utils import (
get_email_name, get_email_name,
@ -74,6 +79,7 @@ from app.models import (
) )
from app.utils import random_string from app.utils import random_string
from server import create_app from server import create_app
from app import pgp_utils
# fix the database connection leak issue # fix the database connection leak issue
@ -255,6 +261,31 @@ def should_append_alias(msg, alias):
return True return True
def prepare_pgp_message(orig_msg: Message, pgp_fingerprint: str):
msg = MIMEMultipart("encrypted", protocol="application/pgp-encrypted")
# copy all headers from original message except the "Content-Type"
for i in reversed(range(len(orig_msg._headers))):
header_name = orig_msg._headers[i][0].lower()
if header_name != "Content-Type".lower():
msg[header_name] = orig_msg._headers[i][1]
first = MIMEApplication(
_subtype="pgp-encrypted", _encoder=encoders.encode_7or8bit, _data=""
)
first.set_payload("Version: 1")
msg.attach(first)
second = MIMEApplication("octet-stream", _encoder=encoders.encode_7or8bit)
second.add_header("Content-Disposition", "inline")
# encrypt original message
encrypted_data = pgp_utils.encrypt(orig_msg.as_string(), pgp_fingerprint)
second.set_payload(encrypted_data)
msg.attach(second)
return msg
def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str: def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
"""return *status_code message*""" """return *status_code message*"""
alias = rcpt_to.lower() # alias@SL alias = rcpt_to.lower() # alias@SL
@ -267,7 +298,14 @@ def handle_forward(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> str:
LOG.d("alias %s cannot be created on-the-fly, return 510", alias) LOG.d("alias %s cannot be created on-the-fly, return 510", alias)
return "510 Email not exist" return "510 Email not exist"
mailbox_email = gen_email.mailbox_email() mailbox = gen_email.mailbox
mailbox_email = mailbox.email
# create PGP email if needed
if mailbox.pgp_finger_print:
LOG.d("Encrypt message using mailbox %s", mailbox)
msg = prepare_pgp_message(msg, mailbox.pgp_finger_print)
forward_email = get_or_create_forward_email(msg["From"], gen_email) forward_email = get_or_create_forward_email(msg["From"], gen_email)
forward_log = ForwardEmailLog.create(forward_id=forward_email.id) forward_log = ForwardEmailLog.create(forward_id=forward_email.id)