1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-29 12:04:02 +00:00
This commit is contained in:
r350178982 2025-04-21 17:58:43 +08:00
parent 1ea9f19d78
commit 0fa64a1192
2 changed files with 73 additions and 49 deletions

View File

@ -1002,7 +1002,7 @@ def send_html_email(subject, con_template, con_context, from_email, to_email,
"""
# get logo path
from seahub.utils.mail import add_smime_sign
from seahub.utils.mail import SmimeEmailMessage
logo_path = LOGO_PATH
custom_logo_file = os.path.join(MEDIA_ROOT, CUSTOM_LOGO_PATH)
if os.path.exists(custom_logo_file):
@ -1022,13 +1022,9 @@ def send_html_email(subject, con_template, con_context, from_email, to_email,
if reply_to is not None:
headers['Reply-to'] = reply_to
msg = EmailMessage(subject, t.render(con_context), from_email,
msg = SmimeEmailMessage(subject, t.render(con_context), from_email,
to_email, headers=headers)
msg.content_subtype = "html"
sig_part = add_smime_sign(msg)
if sig_part:
msg.attach(sig_part)
msg.send()
def gen_dir_share_link(token):

View File

@ -2,10 +2,14 @@
import os
import logging
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.serialization import pkcs7
from cryptography import x509
import base64
from django.core.mail.message import SafeMIMEMultipart
from django.template import loader
from django.core.mail import EmailMessage
@ -17,53 +21,80 @@ from seahub import settings
logger = logging.getLogger(__name__)
def add_smime_sign(msg):
if not ENABLE_SMIME:
return None
class SmimeEmailMessage(EmailMessage):
CERTS_DIR = getattr(settings, 'SMIME_CERTS_DIR', '/opt/seafile/seahub-data/certs')
cert_file = os.path.join(CERTS_DIR, 'cert.pem')
key_file = os.path.join(CERTS_DIR, 'private_key.pem')
if not os.path.exists(cert_file):
logger.warning('smime cert file %s does not exists.' % cert_file)
return None
def __init__(self, *args, **kwargs):
super(SmimeEmailMessage, self).__init__(*args, **kwargs)
if not os.path.exists(key_file):
logger.warning('smime key file %s does not exists.' % key_file)
return None
# Load the private key
with open(key_file, "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
def _signed(self, msg):
if not ENABLE_SMIME:
return msg
# Load the certificate
with open(cert_file, "rb") as f:
certificate = x509.load_pem_x509_certificate(f.read())
msg.mixed_subtype = "signed"
CERTS_DIR = getattr(settings, 'SMIME_CERTS_DIR', '/opt/seafile/seahub-data/certs')
cert_file = os.path.join(CERTS_DIR, 'cert.pem')
key_file = os.path.join(CERTS_DIR, 'private_key.pem')
msg_payload = msg.message().as_string().encode()
if not os.path.exists(cert_file):
logger.warning(f'smime cert file {cert_file} does not exist.')
return msg
if not os.path.exists(key_file):
logger.warning(f'smime key file {key_file} does not exist.')
return msg
try:
# Load the private key
with open(key_file, "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
# Load the certificate
with open(cert_file, "rb") as f:
certificate = x509.load_pem_x509_certificate(f.read())
except Exception as e:
logger.error(e)
return msg
builder = pkcs7.PKCS7SignatureBuilder() \
.set_data(msg_payload) \
.add_signer(certificate, private_key, hashes.SHA256())
pkcs7_signature = builder.sign(serialization.Encoding.SMIME, [pkcs7.PKCS7Options.DetachedSignature])
original_msg = msg
msg_payload = msg.as_string().encode()
# Base64 encode the signature for S/MIME
signature_b64 = base64.b64encode(pkcs7_signature).decode()
builder = pkcs7.PKCS7SignatureBuilder() \
.set_data(msg_payload) \
.add_signer(certificate, private_key, hashes.SHA256())
pkcs7_signature = builder.sign(serialization.Encoding.SMIME, [pkcs7.PKCS7Options.DetachedSignature])
# Create the S/MIME signature part
sig_part = MIMEApplication(
signature_b64,
"pkcs7-signature",
)
sig_part.set_param("name", "smime.p7s")
sig_part.add_header("Content-Disposition", "attachment", filename="smime.p7s")
signature = base64.b64encode(pkcs7_signature).decode()
return sig_part
signed_msg = SafeMIMEMultipart(
_subtype='signed',
protocol='application/pkcs7-signature',
micalg='sha-256'
)
for header in ['Subject', 'From', 'To', 'Date']:
if header in original_msg.keys():
signed_msg[header] = original_msg[header]
signed_msg.attach(original_msg)
sig_part = MIMEApplication(
signature,
'pkcs7-signature',
name='smime.p7s',
)
sig_part.add_header(
'Content-Disposition',
'attachment; filename="smime.p7s"'
)
signed_msg.attach(sig_part)
return signed_msg
def message(self):
original_msg = super().message()
return self._signed(original_msg)
def send_html_email_with_dj_template(recipients, subject, dj_template, context={}):
"""
@ -92,15 +123,12 @@ def send_html_email_with_dj_template(recipients, subject, dj_template, context={
t = loader.get_template(dj_template)
html_message = t.render(context)
mail = EmailMessage(subject=subject, body=html_message, to=[recipients])
mail = SmimeEmailMessage(subject=subject, body=html_message, to=[recipients])
mail.content_subtype = "html"
try:
sig_part = add_smime_sign(mail)
if sig_part:
mail.attach(sig_part)
mail.send()
return True
except Exception as e:
logger.error(e)
logger.exception(e)
return False