DomainKeysSign Method (MailMessage, String, Byte, String)
Signs a mail message with DomainKeys and DKIM signatures.

Namespace: MailBee.Security
Assembly: MailBee.NET (in MailBee.NET.dll) Version: 12.5.0 build 687 for .NET 4.5
Syntax
public MailMessage Sign(
	MailMessage msg,
	string[] headersToSign,
	byte[] privateKey,
	string selector
)

Parameters

msg
Type: MailBee.MimeMailMessage
The mail message to be signed.
headersToSign
Type: SystemString
The array of the names of the headers to be included in the signature, or a null reference (Nothing in Visual Basic) if all the message headers should be included in the signature.
privateKey
Type: SystemByte
The binary contents of the DomainKeys/DKIM private key.
selector
Type: SystemString
The prefix of the sub-domain serving DomainKeys/DKIM for the sender domain.

Return Value

Type: MailMessage
The signed mail message.
Exceptions
ExceptionCondition
MailBeeInvalidArgumentExceptionmsg or privateKey or selector is a null reference (Nothing in Visual Basic) or the message to be signed does not include the header specifying the sender (Sender or From or X-Sender header) or headersToSign array (if not null) does not list the name of that header or the sender's e-mail address domain is empty.
MailBeeExceptionAn error occurred and ThrowExceptions is true.
Remarks

This methods and its overloads are for advanced DomainKeys/DKIM signing. In most cases, you can choose DomainKeysSign(Boolean, String, String, Boolean, String, DomainKeysTypes) method which is easier to use (although not so flexible). Moreover, in ideal case it should be your your mail server's job to sign outgoing e-mails with DomainKeys/DKIM signatures. Use MailBee only if you cannot enable this feature on your mail server.

To sign a message with DomainKeys/DKIM signatures, you must have a private key. For instance, you can create it with OpenSSL utility (see DomainKeys topic for more information). The key data is actually the bytes retrieved from base64 decoding of the key file. Thus, if you have a key file, you can directly use Sign(MailMessage, String, String, Boolean, String) overload.

Note Note
When composing and sending a new message, no headers get changed after the message had been signed and the signature remains valid. See Sign(MailMessage, String, String, Boolean, String) topic for a simple code sample. If you, however, sign an existing message (for instance, forwarding a message previously received from a POP3 server), then read the below on how to correctly create the signature.

DK/DKIM standard requires the message to be signed must have Sender or From or X-Sender header and the e-mail address in that header must contain non-empty domain part. You can include all the headers into the signature (passing a null reference as headersToSign value) so that any change in the headers the message originally had would make the signature invalid. In this case, you must set all the headers prior to signing the message and make sure MailBee won't change these headers during sending.

Alternatively, you may include only certain headers into the signature (at least Sender or From) so that other headers can be changed. This is useful if you want to make sure the signature won't appear invalid when some headers get changed after the message has been signed. Typical case is when the mail server alters the headers of the signed message (changes Date, Message-ID or other headers).

In other words, make sure that all headers listed in the signature have not changed their value after signing. To do this, either do not list these headers in the signature omitting them in headersToSign array or add these headers to the message AFTER it has been signed. Adding new headers does not invalidate the signature, while changing the existing headers does.

In the sample code to this topic, we take care of Date and Message-ID because we sign an existing message, not a new one. Thus, Date and Message-ID may already be present in the message being signed. Then, when MailBee sends the message, it by default sets Date and Message-ID to new values and this action makes the signature invalid. Four ways to prevent this:

  1. Set Date and Message-ID manually BEFORE signing and suppress automatic setting of these values by MailBee during sending. The sample code to this topic uses this method.
  2. Simply clear Date and Message-ID prior to signing. This way, Date and Message-ID headers won't be included into the signature at all and thus automatic setting of these headers by MailBee during sending won't invalidate the signature. The recommended and the easiest method.
  3. Sign only certain headers of the message (using headersToSign parameter). In this case, if Message-ID and Date headers are not included into the signature and you are free to modify them as you wish. Use this method if your mail server may change some headers and for some reason the message being signed already has these headers (i.e. you can't add them AFTER signing).
  4. Just suppress automatic setting of Message-ID and Date headers by MailBee during sending. In this case, the message being sent will retain the original Message-ID and Date values. This approach is not recommended because any e-mail ever sent should have unique Message-ID and having two messages with same Message-ID may cause some mail systems to think that such messages are duplicates.

If you want to sign empty headers as well (to avoid tampering them), set KeepEmptyHeaders property of Builder object to true.

To make MailBee automatically DK/DKIM sign all outgoing e-mail messages created from certain MailMessage instance, call SetDomainKeysSignOnSend(Boolean, Boolean, String, String, Boolean, String, DomainKeysTypes) method of Builder object.

Note Note
Be sure to enable FipsMode if the current system is FIPS-compliant.
Examples
This console sample loads a message from file, signs it with DomainKeys signature (DomainKeys private key is taken from a file), and sends it out. Date and Message-ID headers are assigned BEFORE signing because they may already exist in the loaded message and thus would be included in the signature. Later, when the message gets sent, they would be set automatically and thus the signature would become invalid. We overcome this by manual settings of these headers before signing and disabling their automatic setting at the moment of sending.
Note Note
Alternatively, we could simply clear Date and Message-ID prior to signing to prevent inclusion of these headers into the signature.
using System;
using System.IO;
using MailBee;
using MailBee.Mime;
using MailBee.Security;
using MailBee.SmtpMail;

class Sample
{
    static void Main(string[] args)
    {
        // Load the message from file.
        MailMessage msg = new MailMessage();
        msg.LoadMessage(@"C:\Docs\msg.eml");

        // Set new values of Date and Message-ID. These values will be included
        // into the signature.
        msg.Date = DateTime.Now;
        msg.SetUniqueMessageID(null);

        // Here we load the private key from file only to demonstrate
        // how to use Sign method with binary array. We could simply use
        // another overload and pass a filename.
        byte[] privateKey = null;
        using (Stream stream = new FileStream(@"C:\Temp\private.der", FileMode.Open, FileAccess.Read))
        {
            privateKey = new byte[stream.Length];
            stream.Read(privateKey, 0, privateKey.Length);
        }

        // We will send the message with this object.
        Smtp mailer = new Smtp();

        // Sign the message and assign the signed message for sending.
        // We assume "dk" is sub-domain for which DomainKeys DNS record of the
        // sending domain is defined. I.e. if the sending domain is company.com
        // (email is sent from "someone@company.com"), then DNS records of
        // "dk._domainkey.company.com" domain must contain DomainKeys info.
        // "._domainkey." suffix is required by DomainKeys standard.
        DomainKeys dk = new DomainKeys();
        mailer.Message = dk.Sign(msg, null, privateKey, "dk");

        // Suppress automatic setting of Date and Message-ID during sending.
        mailer.Message.Builder.SetDateOnSend = false;
        mailer.Message.Builder.SetMessageIDOnSend = false;

        // Send the message via SMTP server (authentication is not used in this sample).
        mailer.SmtpServers.Add("mail.company.com");
        mailer.Send();
    }
}
See Also