Archived Forum Post

Index of archived forum posts

Question:

How to save an encrypted email and later load and send it?

May 10 '16 at 11:32

i want save a prepared mail to the FileSystem (Android) insted send it instant. But i also use this:

CkCert userCertificate = …..
ckEMail.AddEncryptCert(userCertificate);
ckEMail.SetSigningCert(userCertificate);
ckEMail.put_SendSigned(true);
ckEMail.put_SendEncrypted(true);
after that i call:
ckEMail.SaveEml(mailPath);
But if i later use:
ckEMail.LoadEml(mailPath);
smtp.SendEmail(ckEMail);

the mail is sent decrypted.

What i have to do to save a encrypted mail and later load and send it encrypted??


Answer

... OKAY Problem Solved!!! No Almost no But... just Solved!! :-D

THX


Answer

When SendEmail is called, it renders the email to MIME, and then sends the MIME. Rendering the email involves signing and encrypting. Technically, SendEmail is equivalent to first calling mailman.RenderToMime, and then calling mailman.SendMime. For example:

// In pseudo-code
string renderedMime = mailman.RenderToMime();
bool success = mailman.SendMime(fromAddr, recipients, renderedMime);
When an email is stored within an Email object (CkEmail in C++), it is not stored in it's assembled MIME format. It's stored in an internal object model. RenderToMime assembles the email to MIME, applying whatever transformations are needed (such as signing or encrypting).

If you wish to store the signed + encrypted email to a file, then call RenderToMime and save the MIME string to the file. To later load and send, load the string from the file and pass it directly to SendMime.

When MIME is loaded into an Email object, if it is signed/encrypted it will be automatically "unwrapped" -- meaning the signature is verified and the email is decrypted. The results of the signature verification and/or decryption are available in various properties of the Email class.

You've probably noticed that SendMime has arguments for FROM and RECIPIENTS. This is to allow for sending email where the From address and recipients can differ from what is found in the headers of the MIME. If you saved the MIME string to a file, and then re-load, the only way to get the FROM and RECIPIENTS is to parse the MIME. There are three solutions:

  1. Save the From/Recipients to a 2nd file, in an easy to parse format such as XML or JSON.
  2. Load the MIME into an Email object just for the sake of getting the From/To/CC addresses.
  3. Load the MIME into a Chilkat Mime object to get the From/To/CC header fields. The Chilkat Mime object will not automatically decrypt the MIME like the Email object does. Therefore, loading into a Mime object would be better for performance.

Answer

hey this is a good Answer!! BUT there is a small different with an Error at the End if you send the Mail with SendMime(....) instead of sending with SendEmail(...)

What i do is as you said:

  1. Save the Mime String to a file ...
  2. then later Load the Mime String FROM that File
  3. get the From and To Fields from the Chilkat Mime object
  4. call SendMime(....)

=> Error because of the From Email Field

If i do almost the same but use SaveEml() and LoadEml() and then use the SendEmail() Command i got success. It looks like the SendEmail() command filters the Name Part from the EMail-Address but not the SendMime() command ...

here the both Log's (first SendEmail() second with SendMime())

 sendSmtpEmail:
      sendWithPipelining:
        sendMailFrom:
          mailFrom: howard@rnd.loc
          sendCmdToSmtp:
            SmtpCmdSent: MAIL FROM:<howard@rnd.loc><CRLF>
          --sendCmdToSmtp
        --sendMailFrom
        sendRcptTo:
          sendCmdToSmtp:
            SmtpCmdSent: RCPT TO:<howard@rnd.loc><CRLF>
          --sendCmdToSmtp
        --sendRcptTo
        sendCmdToSmtp:
          SmtpCmdSent: DATA<CRLF>
        --sendCmdToSmtp
        readSmtpResponse:
          SmtpCmdResp: 250 2.1.0 Sender OK
        --readSmtpResponse
        readRcptTo:
          readSmtpResponse:
            SmtpCmdResp: 250 2.1.5 Recipient OK
          --readSmtpResponse
          recipient: howard@rnd.loc
        --readRcptTo
        readSmtpResponse:
          SmtpCmdResp: 354 Start mail input; end with <CRLF>.<CRLF>
        --readSmtpResponse
      --sendWithPipelining
      mimeDataSize: 575
      sendDataToSmtp:
        numBytesSent: 575
      --sendDataToSmtp
      sendCmdToSmtp:
        SmtpCmdSent: <CRLF>.<CRLF>
      --sendCmdToSmtp
      readSmtpResponse:
        SmtpCmdResp: 250 2.6.0 ***** Queued mail for delivery
      --readSmtpResponse
    --sendSmtpEmail
  --sendMimeInner
--sendEmailInner
Success.

 sendSmtpEmail:
    sendWithPipelining:
      sendMailFrom:
        mailFrom: Howard <howard@rnd.loc>
        sendCmdToSmtp:
          SmtpCmdSent: MAIL FROM:<Howard <howard@rnd.loc>><CRLF>
        --sendCmdToSmtp
      --sendMailFrom
      sendRcptTo:
        sendCmdToSmtp:
          SmtpCmdSent: RCPT TO:<howard@rnd.loc><CRLF>
        --sendCmdToSmtp
      --sendRcptTo
      sendCmdToSmtp:
        SmtpCmdSent: DATA<CRLF>
      --sendCmdToSmtp
      readSmtpResponse:
        SmtpCmdResp: 501 5.1.7 Invalid address
      --readSmtpResponse
      readRcptTo:
        readSmtpResponse:
          SmtpCmdResp: 503 5.5.2 Need mail command
        --readSmtpResponse
        bad_address: howard@rnd.loc
      --readRcptTo
      readSmtpResponse:
        SmtpCmdResp: 503 5.5.2 Need mail command
      --readSmtpResponse
      smtpRset:
        Sending RSET command.
        smtpSendGet2:
          sendCmdToSmtp:
            SmtpCmdSent: RSET<CRLF>
          --sendCmdToSmtp
          readSmtpResponse:
            SmtpCmdResp: 250 2.0.0 Resetting
          --readSmtpResponse
        --smtpSendGet2
      --smtpRset
    --sendWithPipelining
  --sendSmtpEmail
--sendMimeInner
Failed.

----- UPDATE ---- here is the Mime String from the Mail:

MIME-Version: 1.0
Date: Mon, 09 May 2016 16:29:12 +0200
Message-ID: <A875F9C208C33FA8D83B10465FC0BC61FB717F02@unknown>
Content-Type: multipart/alternative; boundary="------------010106030000010800030407"
X-Priority: 3 (Normal)
Subject: After First Android Mail... :-)
From: Howard <howard@rnd.loc>
To: Howard <howard@rnd.loc>

--------------010106030000010800030407
Content-Type: text/plain; format=flowed
Content-Transfer-Encoding: 7bit

Greetings from Howard
--------------010106030000010800030407--

Answer

Thanks Howard,

Yes.. the MIME API is going to simply return the MIME header field values, as-is, without any special parsing. The Email object knows that the MIME is email, and semantically treats certain header fields specially, such as To, CC, etc. What you could do is this:

  1. Load into the MIME object as before.
  2. Instantiate an empty email object.
  3. Get the contents of the "To" header from the MIME object, and pass it to Email.AddMultipleTo.
  4. Then get the email addresses from the Email object (NumTo, GetToAddr(index))
  5. Do the same for CC.

You could, of course, just load the MIME into a temporary Email object just for the purpose of getting the To/CC addresses, but this is somewhat expensive because the Email will be automatically decrypted/verified. (That's a lot of work for just needing the To/CC addresses.) However, if you find that the load only takes a small fraction of a second, and if that's no big deal, then do it. The cost of .5 seconds can be negligible, or huge -- it all depends on what you're doing...


Answer

Hey, thx again... and again ALMOST done :-D .. SOOORY!!!

I use the "Empty Mail + To Mime Header" Version and it really works like you described.

BUT: i missed the BCC Field!!

the Problem is the smtp.RenderToMime(...) function. it returns the Mime but without the BCC Part!!

Is there any something that i missed again?? :-)


Answer

Thanks Howard,

The BCC field has been a thorn in Chilkat's side forever. The whole point of BCC is that the recipients are blind carbon copied. If the BCC recipients are stored in the Email's MIME header, then they're no longer blind. What's the point of BCC then? May was well be CC. So Chilkat does not store BCC recipients in the header at all.

If you wish to save BCC recipients in the header, then you would get each BCC recipient using NumBcc/GetBcc, and explicitly write them to a header(s) of your own choosing via the AddHeaderField method. For example, emailObject.AddHeaderField("SavedBccAddrs","....")

When loading, get the "SavedBccAddrs" header, include them in the list of email recipients for the SendMime, and remove from the header. (If you don't remove from the header, they are no longer really BCC, because the recipients can be seen by anybody who views the header..)


Answer

... and after i removed my own Field ... i have to Put the "Bcc's" back to the Mime Header in a Field Called "Bcc"?? or what is the right way to send it?


Answer

No.. the BCC addresses should never be in the MIME header when sending. The BCC addresses are passed to the SMTP server during the SMTP session, but are not in the MIME. That's what makes them "blind". The recipients are unaware of the other blind recipients.

Here's a sample SMTP session:

telnet: > telnet mx1.example.com smtp
telnet: Trying 192.0.2.2...
telnet: Connected to mx1.example.com.
telnet: Escape character is '^]'.
server: 220 mx1.example.com ESMTP server ready Tue, 20 Jan 2004 22:33:36 +0200
client: HELO client.example.com
server: 250 mx1.example.com
client: MAIL FROM: <sender@example.com>
server: 250 Sender <sender@example.com> Ok
client: RCPT TO: <recipient1@example.com>
server: 250 Recipient <recipient1@example.com> Ok
client: RCPT TO: <recipient2@example.com>
server: 250 Recipient <recipient2@example.com> Ok
client: RCPT TO: <recipient3@example.com>
server: 250 Recipient <recipient3@example.com> Ok
client: DATA
server: 354 Ok Send data ending with <crlf>.<crlf>
client: From: sender@example.com
client: To: recipient@example.com
client: Subject: Test message
client: 
client: This is a test message.
client: .
server: 250 Message received: 20040120203404.CCCC18555.mx1.example.com@client.example.com
client: QUIT
server: 221 mx1.example.com ESMTP server closing connection

All recipients, including BCC recipients, are passed in "RCPT TO" commands -- but the BCC recipients are not in the MIME header.

You can also see that the actual recipients of the email are determined by the addresses passed in the RCPT TO commands. You can put "santa_claus@northpole.org" in the MIME header, and then pass "admin@chilkatsoft.com" in the RCPT TO, and I'll receive an email that looks like it was addressed to Santa Claus. Of course, some mail servers won't allow such a thing...