如何序列化邮件消息?

Posted

技术标签:

【中文标题】如何序列化邮件消息?【英文标题】:How do I serialize a mail message? 【发布时间】:2010-11-10 11:01:44 【问题描述】:

我在使用 los foratter 序列化 mial 消息时得到以下信息。

错误:Sys.WebForms.PageRequestManagerServerErrorException:序列化“System.Net.Mail.MailMessage”类型的值“System.Net.Mail.MailMessage”时出错。”

有没有一种简单的方法来序列化这个对象,还是我必须单独序列化每个属性?

【问题讨论】:

你想把它序列化到哪里? 我正在尝试将其放入字节数组中。 【参考方案1】:

我知道这是一篇较旧的帖子,但我也遇到了需要序列化 ​​MailAddress 类的问题,因此我创建了一个可序列化的版本。如果您能够使用自定义 MailAddress 类而不是 System.Net.Mail.MailAddress 类,这可能对您有用。

/// <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)))
    
    

【讨论】:

【参考方案2】:

对于那些寻找如何将 MailMessage 序列化为由 Keyvan Nayyeri 编写的 XML 的完整源代码的人,这里是他的 github 的链接:

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

以下是他的博客存档,现已失效:

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

以防上面的链接也可能失效,我在这里重新发布他的博客:

如何序列化邮件消息

.NET 中有两个 MailMessage 类。第一个在 System.Web.Mail 命名空间中,在 .NET 2.0 及更高版本中已过时,第二个在 System.Net.Mail 中可用。我不关心过时的,所以我只展示如何序列化 System.Net.Mail.MailMessage 类的实例。

要序列化 ​​MailMessage 对象的属性,您可以创建一个新类并为其创建一个 MailMessage 类型的属性,将您的 MailMessage 嵌入到该类中。在这个新类中,您可以实现 IXmlSerializable 接口来手动序列化其 MailMessage。

序列化

序列化方面的工作就像实现 WriteXml 方法一样简单。下面的代码是我为此编写的。

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();
    

按照相同的方法,您可以序列化其他属性,如附件。下周我将发布新版本的 Gopi,其中包含序列化所有内容的更新代码,因此您可以稍等片刻获得代码。

反序列化

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;

以上代码使用辅助方法来获取不同部分的 XmlNode。

public XmlNode GetConfigSection(XmlDocument xml, string nodePath)

    return xml.SelectSingleNode(nodePath);

此代码是不言自明的,不需要任何注释,但请注意,您需要为类名更新 XPath 表达式。当然,我可以使用反射来使这段代码更通用,但有时我是个坏人!

【讨论】:

【参考方案3】:

遗憾的是,System.Net.Mail.MailMessage 类未标记为可序列化。所以,是的,你需要自己做。以下博客文章中描述了一种技术,可以让您了解如何进行操作:How to Serialize a MailMessage ...基本上,您需要单独提取每个属性。引用:

要序列化 ​​MailMessage 对象的属性,您可以创建一个 新类并为其创建一个 MailMessage 类型的属性 你在课堂上的 MailMessage。在这个新类中,您可以实现 IXmlSerializable 接口手动序列化其MailMessage。这里 我创建了这个类并将其命名为 SerializableMailMessage [...]

[WriteXml() 和 ReadXml() 方法的代码实现如下;查看源链接]

【讨论】:

链接重定向到博客主页。 @GunnarSteinn 谢谢 - 已修复。 链接仍然断开。 @Campinho 该博客已不存在。 @ChrisW.Rea 哦,真可惜,有什么新的参考吗?

以上是关于如何序列化邮件消息?的主要内容,如果未能解决你的问题,请参考以下文章

如何设置 WCF 自定义反序列化错误消息

如何使用 DataContractSerializer 从文件中反序列化 WCF 肥皂响应消息?

如何通过 Debezium Connect 反序列化来自 Kafka 消息流的几何字段?

如何修改 Spring Cloud AWS 用来反序列化 SQS 消息的对象映射器?

Spring MVC for Rest 服务如何在 Jackson 反序列化错误时自定义错误“消息”?

SpringBoot整合RabbitMQ--重试/消息序列化--方法/实例