'How to attach in SMIME m2crypto a file in python?

I' am trying to implement a SMIME Mail with a encrypted text and attachment. So far I did the following:

#Example for parameter values:
#subject = "abc"
#content = "some text"
#attachment = some file
#destination = "[email protected]"
#sender = "[email protected]"

def smime_mail(subject, content, attachment, destination, sender):
   # Preperation
   msg_bytes = content.encode()
   msg_bio = BIO.MemoryBuffer(msg_bytes)
   sign_key = "/opt/sign_key.pem"
   sign_cert = "/opt/sign_cert.pem"
   ricipient_cert = "/opt/ricipient.pem"
   smime = SMIME.SMIME()

   # Load sign key/cert and sign
   smime.load_key(sign_key, sign_cert)
   p7 = smime.sign(msg_bio, flags=SMIME.PKCS7_Text)
   msg_bio = BIO.MemoryBuffer(msg_bytes)
   sk = X509.X509_Stack()
   sk.push(X509.load_cert(ricipient_cert))
   smime.set_x509_stack(sk)
   smime.set_cipher(SMIME.Cipher('aes_256_cbc'))
   tmp_bio = BIO.MemoryBuffer()
   smime.write(tmp_bio, p7)

   # Encrypt
   p7 = smime.encrypt(tmp_bio)

   # Format Mail
   out = BIO.MemoryBuffer()
   out.write(f'From: {sender}\r\n')
   out.write(f'To: {destination}\r\n')
   out.write(f'Subject: {subject}\r\n')
   out.write(out, p7)
   out.close()

   # Mail send
   smtp = smtplib.SMTP('localhost')
   smtp.sendmail(sender, destination, out.read())
   smtp.quit()

The code works and I get a encrypted/sign mail to my outlook.

Now my problem is, I cant find a example how to add a attachment to my SMIME mail. Do I have to put a "MIMEMultipart()" Object into my buffer instead of my "content" variable?

It would be nice if someone can give me a example, how to put a attachment in this code or where I have to look for. :)



Solution 1:[1]

The steps would be:

  • create a MIMEMultipart message
  • attach the files to it, as you would do "normally"
  • pass the entire MIMEMultipart message as bytes to SMIME and sign it

The way I did it:

files = ["foo/a.txt", "bar/b.txt"]

msg = MIMEMultipart()
msg.attach(MIMEText("Hello world!", "plain"))

for filename in files:
    with open(filename, "rb") as f:
        msg.attach(MIMEApplication(f.read(), NAME=os.path.basename(f)))

msg_bytes = msg.as_bytes()
msg_bio = BIO.MemoryBuffer(msg_bytes)
...

etc. - the remaining part (the signing and the sending) are in the code snippet in the question.

I also found an article where the author does it in a similar way.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 natka_m