How do I serialize a mail message?

后端 未结 3 530
野的像风
野的像风 2021-02-08 05:02

I get the following when tying to serialize a mial message using the los foratter.

Error: Sys.WebForms.PageRequestManagerServerErrorException: Error serializing value \'

相关标签:
3条回答
  • 2021-02-08 05:13

    Sadly, the System.Net.Mail.MailMessage class is not marked as serializable. So, yes, you'll need to do it yourself. There's a technique described in the following blog post that can give you an idea of how you might proceed: How to Serialize a MailMessage ... basically, you will need to pull out each of the properties individually. Quote:

    To serialize the properties of a MailMessage object you can create a new class and create a property of MailMessage type for it that embeds your MailMessage in the class. In this new class you can implement IXmlSerializable interface to manually serialize its MailMessage. Here I create this class and call it SerializableMailMessage [...]

    [code implementation of WriteXml() and ReadXml() methods follow; see source link]

    0 讨论(0)
  • 2021-02-08 05:16

    For those looking for the full source code on how to serialize MailMessage into XML written by Keyvan Nayyeri, here is the link to his github:

    https://github.com/keyvan/Gopi/blob/master/Gopi/Gopi/SerializableMailMessage.cs

    And here is the archive of his blog that is now defunct:

    http://web.archive.org/web/20131124074822/http://keyvan.io/how-to-serialize-a-mailmessage

    Just in case the link above might become dead too, here I re-post his blog here:

    How to Serialize a MailMessage

    There are two MailMessage classes in .NET. First one is in System.Web.Mail namespace and is obsolete in .NET 2.0 and later and the second one is available in System.Net.Mail. I don't care about the obsolete one so I just show how you can serialize instances of System.Net.Mail.MailMessage class.

    To serialize the properties of a MailMessage object you can create a new class and create a property of MailMessage type for it that embeds your MailMessage in the class. In this new class you can implement IXmlSerializable interface to manually serialize its MailMessage.

    Serialization

    Serialization side of the work is as simple as implementing the WriteXml method. The below code is what I've written to do this.

    public void WriteXml(XmlWriter writer)
    {
        if (this != null)
        {
            writer.WriteStartElement("MailMessage");
            writer.WriteAttributeString("Priority", Convert.ToInt16(this.Priority).ToString());
            writer.WriteAttributeString("IsBodyHtml", this.IsBodyHtml.ToString());
    
            // From
            writer.WriteStartElement("From");
            if (!string.IsNullOrEmpty(this.From.DisplayName))
                writer.WriteAttributeString("DisplayName", this.From.DisplayName);
            writer.WriteRaw(this.From.Address);
            writer.WriteEndElement();
    
            // To
            writer.WriteStartElement("To");
            writer.WriteStartElement("Addresses");
            foreach (MailAddress address in this.To)
            {
                writer.WriteStartElement("Address");
                if (!string.IsNullOrEmpty(address.DisplayName))
                    writer.WriteAttributeString("DisplayName", address.DisplayName);
                writer.WriteRaw(address.Address);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            // CC
            if (this.CC.Count > 0)
            {
                writer.WriteStartElement("CC");
                writer.WriteStartElement("Addresses");
                foreach (MailAddress address in this.CC)
                {
                    writer.WriteStartElement("Address");
                    if (!string.IsNullOrEmpty(address.DisplayName))
                        writer.WriteAttributeString("DisplayName", address.DisplayName);
                    writer.WriteRaw(address.Address);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
    
            // Bcc
            if (this.Bcc.Count > 0)
            {
                writer.WriteStartElement("Bcc");
                writer.WriteStartElement("Addresses");
                foreach (MailAddress address in this.Bcc)
                {
                    writer.WriteStartElement("Address");
                    if (!string.IsNullOrEmpty(address.DisplayName))
                        writer.WriteAttributeString("DisplayName", address.DisplayName);
                    writer.WriteRaw(address.Address);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
    
            // Subject
            writer.WriteStartElement("Subject");
            writer.WriteRaw(this.Subject);
            writer.WriteEndElement();
    
            // Body
            writer.WriteStartElement("Body");
            writer.WriteCData(Body);
            writer.WriteEndElement();
    
            writer.WriteEndElement();
        }
    }
    

    Following same approach you can serialize other properties like Attachments. Next week I'll release the new version of Gopi that contains the updated code that serializes everything so you can wait shortly to get your hands on the code.

    Deserialization

    public void ReadXml(XmlReader reader)
    {
        XmlDocument xml = new XmlDocument();
        xml.Load(reader);
    
        // Properties
        XmlNode rootNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage");
        this.IsBodyHtml = Convert.ToBoolean(rootNode.Attributes["IsBodyHtml"].Value);
        this.Priority = (MailPriority)Convert.ToInt16(rootNode.Attributes["Priority"].Value);
    
        // From
        XmlNode fromNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/From");
        string fromDisplayName = string.Empty;
        if (fromNode.Attributes["DisplayName"] != null)
            fromDisplayName = fromNode.Attributes["DisplayName"].Value;
        MailAddress fromAddress = new MailAddress(fromNode.InnerText, fromDisplayName);
        this.From = fromAddress;
    
        // To
        XmlNode toNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/To/Addresses");
        foreach (XmlNode node in toNode.ChildNodes)
        {
            string toDisplayName = string.Empty;
            if (node.Attributes["DisplayName"] != null)
                toDisplayName = node.Attributes["DisplayName"].Value;
            MailAddress toAddress = new MailAddress(node.InnerText, toDisplayName);
            this.To.Add(toAddress);
        }
    
        // CC
        XmlNode ccNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/CC/Addresses");
        foreach (XmlNode node in ccNode.ChildNodes)
        {
            string ccDisplayName = string.Empty;
            if (node.Attributes["DisplayName"] != null)
                ccDisplayName = node.Attributes["DisplayName"].Value;
            MailAddress ccAddress = new MailAddress(node.InnerText, ccDisplayName);
            this.CC.Add(ccAddress);
        }
    
        // Bcc
        XmlNode bccNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Bcc/Addresses");
        foreach (XmlNode node in bccNode.ChildNodes)
        {
            string bccDisplayName = string.Empty;
            if (node.Attributes["DisplayName"] != null)
                bccDisplayName = node.Attributes["DisplayName"].Value;
            MailAddress bccAddress = new MailAddress(node.InnerText, bccDisplayName);
            this.Bcc.Add(bccAddress);
        }
    
        // Subject
        XmlNode subjectNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Subject");
        this.Subject = subjectNode.InnerText;
    
        // Body
        XmlNode bodyNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Body");
        this.Body = bodyNode.InnerText;
    }
    

    Above code uses a helper method to get an XmlNode for different sections.

    public XmlNode GetConfigSection(XmlDocument xml, string nodePath)
    {
        return xml.SelectSingleNode(nodePath);
    }
    

    This code is self-explanatory and doesn't need any comment but note that you need to update XPath expressions for your class names. Of course, I could use reflection to make this code more general but sometimes I'm a bad guy!!

    0 讨论(0)
  • 2021-02-08 05:23

    I know this is an older post, but I also had the issue where I needed to serialize the MailAddress class so I created a serializable version. If you're in a position to use a custom MailAddress class instead of the System.Net.Mail.MailAddress class, this may work for you.

    /// <summary>
    /// Serializable implementation of <see cref="System.Net.Mail.MailAddress"/>.
    /// </summary>
    [Serializable]
    public class MailAddress : System.Net.Mail.MailAddress, ISerializable
    {
        // Keep reference to the display name encoding so we can serialize/deserialize the value
        private readonly Encoding _displayNameEncoding;
    
        public MailAddress(string address)
            : this(address, null, null)
        {
        }
    
        public MailAddress(string address, string displayName)
            : this(address, displayName, null)
        {
        }
    
        public MailAddress(string address, string displayName, Encoding displayNameEncoding)
            : base(address, displayName, displayNameEncoding)
        {
            // Keep reference to the supplied displayNameEncoding so we can serialize/deserialize this value
            _displayNameEncoding = displayNameEncoding ?? Encoding.GetEncoding("utf-8");
        }
    
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Address", base.Address);
            info.AddValue("DisplayName", base.DisplayName);
            info.AddValue("DisplayNameEncoding", _displayNameEncoding);
        }
    
        protected MailAddress(SerializationInfo info, StreamingContext context)
            : this(info.GetString("Address"), info.GetString("DisplayName"), (Encoding)info.GetValue("DisplayNameEncoding", typeof (Encoding)))
        {
        }
    }
    
    0 讨论(0)
提交回复
热议问题