/// <devdoc>
        /// Creates a MailMessage using the body parameter.
        /// </devdoc>
        public MailMessage CreateMailMessage(string recipients, IDictionary replacements, string body, Control owner) {
            if (owner == null) {
                throw new ArgumentNullException("owner");
            }

            string from = From;
            if (String.IsNullOrEmpty(from)) {
                System.Net.Configuration.SmtpSection smtpSection = RuntimeConfig.GetConfig().Smtp;
                if (smtpSection == null || smtpSection.Network == null || String.IsNullOrEmpty(smtpSection.From)) {
                    throw new HttpException(SR.GetString(SR.MailDefinition_NoFromAddressSpecified));
                }
                else {
                    from = smtpSection.From;
                }
            }

            MailMessage message = null;
            try {
                message = new MailMessage(from, recipients);
                if (!String.IsNullOrEmpty(CC)) {
                    message.CC.Add(CC);
                }
                if (!String.IsNullOrEmpty(Subject)) {
                    message.Subject = Subject;
                }

                message.Priority = Priority;

                if (replacements != null && !String.IsNullOrEmpty(body)) {
                    foreach (object key in replacements.Keys) {
                        string fromString = key as string;
                        string toString = replacements[key] as string;

                        if ((fromString == null) || (toString == null)) {
                            throw new ArgumentException(SR.GetString(SR.MailDefinition_InvalidReplacements));
                        }
                        // DevDiv 151177
                        // According to http://msdn2.microsoft.com/en-us/library/ewy2t5e0.aspx, some special 
                        // constructs (starting with "$") are recognized in the replacement patterns. References of
                        // these constructs will be replaced with predefined strings in the final output. To use the 
                        // character "$" as is in the replacement patterns, we need to replace all references of single "$"
                        // with "$$", because "$$" in replacement patterns are replaced with a single "$" in the 
                        // final output. 
                        toString = toString.Replace("$", "$$");
                        body = Regex.Replace(body, fromString, toString, RegexOptions.IgnoreCase);
                    }
                }
                // If there are any embedded objects, we need to construct an alternate view with text/html
                // And add all of the embedded objects as linked resouces
                if (EmbeddedObjects.Count > 0) {
                    string viewContentType = (IsBodyHtml ? MediaTypeNames.Text.Html : MediaTypeNames.Text.Plain);
                    AlternateView view = AlternateView.CreateAlternateViewFromString(body, null, viewContentType);
                    foreach (EmbeddedMailObject part in EmbeddedObjects) {
                        string path = part.Path;
                        if (String.IsNullOrEmpty(path)) {
                            throw ExceptionUtil.PropertyNullOrEmpty("EmbeddedMailObject.Path");
                        }
                        if (!UrlPath.IsAbsolutePhysicalPath(path)) {
                            VirtualPath virtualPath = VirtualPath.Combine(owner.TemplateControlVirtualDirectory,
                                VirtualPath.Create(path));
                            path = virtualPath.AppRelativeVirtualPathString;
                        }

                        // The FileStream will be closed by MailMessage.Dispose()
                        LinkedResource lr = null;
                        try {
                            Stream stream = null;
                            try {
                                stream = owner.OpenFile(path);
                                lr = new LinkedResource(stream);
                            }
                            catch {
                                if (stream != null) {
                                    ((IDisposable)stream).Dispose();
                                }
                                throw;
                            }
                            lr.ContentId = part.Name;
                            lr.ContentType.Name = UrlPath.GetFileName(path);
                            view.LinkedResources.Add(lr);
                        }
                        catch {
                            if (lr != null) {
                                lr.Dispose();
                            }
                            throw;
                        }
                    }
                    message.AlternateViews.Add(view);
                }
                else if (!String.IsNullOrEmpty(body)) {
                    message.Body = body;
                }

                message.IsBodyHtml = IsBodyHtml;
                return message;
            }
            catch {
                if (message != null) {
                    message.Dispose();
                }
                throw;
            }
        }
        /// <devdoc>
        /// Creates a MailMessage using the BodyFileName property.
        /// </devdoc>
        public MailMessage CreateMailMessage(string recipients, IDictionary replacements, Control owner) {
            if (owner == null) {
                throw new ArgumentNullException("owner");
            }

            string body = String.Empty;
            string bodyFileName = BodyFileName;
            if (!String.IsNullOrEmpty(bodyFileName)) {
                string path = bodyFileName;
                if (!UrlPath.IsAbsolutePhysicalPath(path)) {
                    // Relative so we need to add the template source directory to the path
                    path = UrlPath.Combine(owner.AppRelativeTemplateSourceDirectory, path);
                }

                TextReader reader = new StreamReader(owner.OpenFile(path));
                try {
                    body = reader.ReadToEnd();
                }
                finally {
                    reader.Close();
                }
            }
            return CreateMailMessage(recipients, replacements, body, owner);
        }