示例#1
0
        /// <summary>
        /// Signs the given mail item using the provided signer. The mailItem object will be updated so that it includes the signature.
        /// </summary>
        /// <param name="domainSigner">The domain and its signer</param>
        /// <param name="mailItem">The mail item to sign</param>
        /// <returns></returns>
        public void SignMessage(DomainElementSigner domainSigner, MailItem mailItem)
        {
            using (Stream stream = mailItem.GetMimeReadStream())
            {
                stream.Seek(0, SeekOrigin.Begin);

                Logger.LogDebug("Parsing the MimeMessage");
                MimeMessage message = MimeMessage.Load(stream, true);

                Logger.LogDebug("Signing the message");
                lock (settingsMutex)
                {
                    message.Sign(domainSigner.Signer, eligibleHeaders, headerCanonicalization, bodyCanonicalization);
                }
                var value = message.Headers[HeaderId.DkimSignature];
                Logger.LogDebug("Got signing header: " + value);

                // we first need to create a memory stream, because if WriteTo is called with mailItem Stream directly, it throws an exception somehow.
                MemoryStream memoryOutputStream = new MemoryStream();
                message.WriteTo(FormatOptions.Default, memoryOutputStream);
                memoryOutputStream.Seek(0, SeekOrigin.Begin);

                using (Stream outputStream = mailItem.GetMimeWriteStream())
                {
                    memoryOutputStream.WriteTo(outputStream);
                    outputStream.Close();
                }

                stream.Close();
            }
        }
示例#2
0
        /// <summary>
        /// Signs the given mail item using the provided signer. The mailItem object will be updated so that it includes the signature.
        /// </summary>
        /// <param name="domainSigner">The domain and its signer</param>
        /// <param name="mailItem">The mail item to sign</param>
        /// <returns></returns>
        public void SignMessage(DomainElementSigner domainSigner, MailItem mailItem)
        {
            // MailItem.GetMimeWriteStream() internally uses
            // Microsoft.Exchange.Data.Mime.MimeDocument.GetLoadStream(), which may reformat the
            // message using different formatting than is originally read from
            // MailItem.GetMimeReadStream().  To prevent these formatting changes from invalidating
            // the DKIM signature, we must read then write then re-read the message to ensure that
            // any formatting changes are made before we sign the message.
            using (MemoryStream memStream = new MemoryStream())
            {
                using (Stream inputStream = mailItem.GetMimeReadStream())
                {
                    inputStream.Seek(0, SeekOrigin.Begin);
#if EX_2007_SP3 || EX_2010 || EX_2010_SP1 || EX_2010_SP2 || EX_2010_SP3
                    byte[] buffer = new byte[16 * 1024];
                    int    size;
                    while ((size = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        memStream.Write(buffer, 0, size);
                    }
#else
                    inputStream.CopyTo(memStream);
#endif
                }
                memStream.Seek(0, SeekOrigin.Begin);
                using (Stream outputStream = mailItem.GetMimeWriteStream())
                {
                    memStream.WriteTo(outputStream);
                }
            }

            using (Stream inputStream = mailItem.GetMimeReadStream())
            {
                inputStream.Seek(0, SeekOrigin.Begin);
                Logger.LogDebug("Parsing the MimeMessage");
                MimeMessage message = MimeMessage.Load(inputStream, true);
                // 'inputStream' cannot be disposed until we are done with 'message'

                Logger.LogDebug("Signing the message");
                lock (settingsMutex)
                {
                    message.Sign(domainSigner.Signer, eligibleHeaders, headerCanonicalization, bodyCanonicalization);
                }
                var value = message.Headers[HeaderId.DkimSignature];
                Logger.LogDebug("Got signing header: " + value);

                // The Stream returned by mailItem.GetMimeWriteStream() will throw an exception if
                // Stream.Write() is called after Stream.Flush() has been called, but
                // MimeMessage.WriteTo(FormatOptions, Stream) may call Stream.Flush() before the full
                // message has been written.  To avoid exceptions we must buffer the message in a
                // MemoryStream.
                using (MemoryStream memStream = new MemoryStream())
                {
                    message.WriteTo(FormatOptions.Default, memStream);
                    memStream.Seek(0, SeekOrigin.Begin);
                    using (Stream outputStream = mailItem.GetMimeWriteStream())
                    {
                        memStream.WriteTo(outputStream);
                    }
                }
            }
        }