bashhtml-emailsmime

Send S/MIME encrypted html email with bash


How do you send an encrypted and html-formatted email through the command line?
Here is the code I have so far:

# Encrypt email with a certificate
openssl cms -encrypt -in "/tmp/email_to_be_sent.html" -out "/tmp/encrypted.txt" -from $SENDER -to $RECEIVER -subject "Test: Encrypted message" -des3 "/tmp/$CERT.pem" 
# Send the encrypted email
cat "/tmp/encrypted.txt" | sendmail -f $SENDER $RECEIVER

The generated encrypted email /tmp/encrypted.txt is as follow

To: recipient@mail.com
From: sender@mail.com
Subject: Test: Encrypted message
MIME-Version: 1.0
Content-Disposition: attachment; filename="smime.p7m"
Content-Type: application/pkcs7-mime; smime-type=enveloped-data;name="smime.p7m"
Content-Transfer-Encoding: base64

MIIDjAYJKoZIhvcNAQcDoIIDfTCCA3kCAQAxggFZMIIBVQIBADA9MDcxHDAaBgNVBAoME0V1cm9wZWFu
AxAlApQsmjzCwQoonT57JetCp7DHJdHWU1bkLIZWPPBRwa2EB0ZdxOXIvtg7rJavnnbxeTghblM45Pur
A+6BDKJbWvXFyxb...

The problem is, once in the recipient inbox and decrypted, the message is not html formatted and html code like <html><body></body></html> is still readable inside the message.


Solution

  • S/MIME requires the original message to be enveloped. This means that the original message is encrypted and this fact and the type of encryption is added to the outer message headers, so the client knows how to handle the message contents.

    Because of this, the message headers that define the original message format need to be inside the S/MIME envelope, so the client knows which content type it is after decrypting the message.

    The correct way is to extract these headers from the original message, then add them before the original message body. Note that these headers must start on the first line, and that after these headers a blank line is required before the original message body starts.

    Headers that should be moved into the enveloped message data are

    "Moved" means that they should be included in the enveloped message data and removed from the outer message headers.

    The remaining headers should be left in the envelope message. The openssl cms -encrypt command will then add the above headers as required for S/MIME encrypted messages.

    Example

    Original message

    From: someone@somedomain.net
    To: recipient@otherdomain.net
    Subject: It's a test
    MIME-Version: 1.0
    Content-Type: text/plain;
        charset=UTF-8
    Content-Transfer-Encoding: 7bit
    X-Custom-Header: Additional data
    
    This is the message text.
    
    Good night.
    

    Moved headers before encryption (note the additional blank line)

    From: someone@somedomain.net
    To: recipient@otherdomain.net
    Subject: It's a test
    X-Custom-Header: Additional data
    
    MIME-Version: 1.0
    Content-Type: text/plain;
        charset=UTF-8
    Content-Transfer-Encoding: 7bit
    
    This is the message text.
    
    Good night.
    

    Message after encryption

    From: someone@somedomain.net
    To: recipient@otherdomain.net
    Subject: It's a test
    X-Custom-Header: Additional data
    MIME-Version: 1.0
    Content-Disposition: attachment; filename="smime.p7m"
    Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name="smime.p7m"
    Content-Transfer-Encoding: base64
    
    MIJ5lAYJKoZIhvcNAQcDoIJ5hTCCeYECAQAxggHZMIIB1QIBADCBvDCBtjEaMBgG
    A1UEAwwRc2F2aWduYW5vIENFUlQtaTIxJTAjBgNVBAoMHHNhdmlnbmFubyBzb2Z0
    d2FyZSBzb2x1dGlvbnMxHjAcBgNVBAsMFUNlcnRpZmljYXRpb24gU2VydmljZTEL
    (more encrypted data removed)