DomainKeysSign Method (MailMessage, String, Byte, String) |
Namespace: MailBee.Security
public MailMessage Sign( MailMessage msg, string[] headersToSign, byte[] privateKey, string selector )
Exception | Condition |
---|---|
MailBeeInvalidArgumentException | msg 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. |
MailBeeException | An error occurred and ThrowExceptions is true. |
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 |
---|
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:
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 |
---|
Be sure to enable FipsMode if the current system is FIPS-compliant. |
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(); } }