How to sign a mail with smime with python and the module cryptography?

602 Views Asked by At

I want to send a signed mail with smime with the module cryptography. But all my mail programms can't detect the subject if I sign the mail. If I don't sign the mail it shows the subject.

import smtplib
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
from email.utils import formataddr, formatdate

from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import pkcs7
from jinja2 import Template

email_from = "[email protected]"
email_to = "[email protected]"

message = MIMEMultipart("mixed")
message["Subject"] = Header("mail subject", "utf-8").encode()
message["From"] = formataddr(("Sender", email_from))
message["To"] = email_to
message["Date"] = formatdate(localtime=True)
message["Auto-Submitted"] = "auto-generated"

html_template = (
    Path(EMAIL_TEMPLATES_DIR) / f"{template}.html"
).read_text()
html_j2_template = Template(html_template)
html = html_j2_template.render(environment)
message.attach(MIMEText(html, "html"))

ca_cert = open(CA_CERT_PATH, "rb").read()
ca_key = open(CA_KEY_PATH, "rb").read()

cert = x509.load_pem_x509_certificate(ca_cert)
key = serialization.load_pem_private_key(ca_key, None)
options = [pkcs7.PKCS7Options.DetachedSignature]
signed_text = (
    pkcs7.PKCS7SignatureBuilder()
    .set_data(message.as_bytes())
    .add_signer(cert, key, hashes.SHA256())
    .sign(serialization.Encoding.SMIME, options)
)

with smtplib.SMTP() as server:
    server.connect(25)
    server.sendmail(email_from, email_to, signed_text)

And here the version with the module email for python>=3.6.

import smtplib
from email.headerregistry import Address
from email.message import EmailMessage
from email.utils import formatdate

from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import pkcs7
from jinja2 import Template

email_from = "[email protected]"
email_to = "[email protected]"

message = EmailMessage()
message["Subject"] = subject_template
message["From"] = Address("Sendder", email_from)
message["To"] = Address("Receiver", email_to)
message["Date"] = formatdate(localtime=True)
message["Auto-Submitted"] = "auto-generated"

html_template = (
    Path(EMAIL_TEMPLATES_DIR) / f"{template}.html"
).read_text()
html_j2_template = Template(html_template)
html = html_j2_template.render(environment)
message.set_content(html, subtype="html")

ca_cert = open(CA_CERT_PATH, "rb").read()
ca_key = open(CA_KEY_PATH, "rb").read()

cert = x509.load_pem_x509_certificate(ca_cert)
key = serialization.load_pem_private_key(ca_key, None)
options = [pkcs7.PKCS7Options.DetachedSignature]
signed_text = (
    pkcs7.PKCS7SignatureBuilder()
    .set_data(message.as_bytes())
    .add_signer(cert, key, hashes.SHA256())
    .sign(serialization.Encoding.SMIME, options)
)

with smtplib.SMTP() as server:
    server.connect(25)
    server.sendmail(email_from, email_to, signed_text)
0

There are 0 best solutions below