65.9K
CodeProject 正在变化。 阅读更多。
Home

如何创建 SMTP 跟踪侦听器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (6投票s)

2003年1月29日

4分钟阅读

viewsIcon

103177

downloadIcon

948

本文介绍如何创建 SMTP 跟踪侦听器以与 .NET 诊断工具一起使用。

引言

本文介绍了如何扩展 .NET 的原生 TraceListener 功能,使您的应用程序能够发送 SMTP 邮件。  本文假设您熟悉 .NET 跟踪功能(System.Diagnostics 的一部分)。  本文还假定您知道什么是 TraceListener。  如果您不知道,请阅读文章 - **编写自定义 .NET 跟踪侦听器**,作者:**Vagif Abilov**。  Vagif 很好地解释了 TraceListeners 是什么以及如何使用它们。

背景

您有多少次开发了一个应用程序,该应用程序需要发送一封电子邮件来通知您或支持团队发生了某个错误或其他特殊情况?在大多数情况下,该应用程序还必须将相同或类似的信息记录到数据库或某种类型的平面文件中以供以后使用。我最近在 TheCodeProject.com 上发现了一篇题为“**编写自定义 .NET 跟踪侦听器**”的文章,作者是 Vagif Abilov。这篇文章很好地描述了构建自己的跟踪侦听器的方法。  我决定将这篇文章付诸实践,并实现一些人们可以在他们的应用程序中使用的功能。

为什么需要 SMTP 跟踪侦听器?

在构建我的应用程序时,在某些情况下需要将一些相同的跟踪信息发送给电子邮件收件人,例如,抛出异常、用户帐户被锁定等。当开发托管在远程的 Web 应用程序时,这尤其有用。如果您不知道您的 Web 应用程序正在发生什么,并且收到了支持电话,您可能会陷入困境。此代码可以(也应该)扩展以支持附加文件(但我尚未实现,因为我现在不需要)。这样,您就可以将日志文件或其他诊断信息与电子邮件中的错误消息一起发送,这样就不必登录到远程服务器来获取它。

使用代码

SMTPTraceListener

SMTPTraceListener 类派生自 System.Diagnostics 库中的 TraceListener 类。您**必须**覆盖的方法是:

  • public override void Write(string Message)
  • public override void WriteLine(string Message)

您也可以覆盖以下方法(此实现不覆盖,因为它们对于基本功能不是必需的):

  • public virtual void Fail(string);
  • public virtual void Fail(string, string);
  • public virtual void Close();
  • public virtual void Flush();

为了让此类在您的应用程序中工作,您必须在项目引用中创建对 *System.Web.dll* 的引用。  *SMTPTraceListener.cs* 的代码如下所示:

using System;
using System.Diagnostics;
using System.Web.Mail;



namespace RK.TraceListeners
{
    /// <summary>
    /// Summary description for SMTPTraceListener.
    /// </summary>
    public class SMTPTraceListener : TraceListener
    {
        string m_sSMTPServer;
        string m_sFrom;
        string m_sTo;
        string m_sMessage;
        string m_sSubject;
        //Normal mail priority by default
        MailPriority m_oPriority = MailPriority.Normal;

        public MailPriority Priority
        {
            get{return m_oPriority;}
            set{m_oPriority = value;}
        }

        public string Server
        {
            get{return m_sSMTPServer;}
            set{m_sSMTPServer = value;}
        }

        public string From
        {
            get{return m_sFrom;}
            set{m_sFrom = value;}
        }

        public string To
        {
            get{return m_sTo;}
            set{m_sTo = value;}
        }

        public string Message
        {
            get{return m_sMessage;}
            set{m_sMessage = value;}
        }

        public string Subject
        {
            get{return m_sSubject;}
            set{m_sSubject = value;}
        }

        public SMTPTraceListener() 
        {
            
        }

        public SMTPTraceListener(string ListenerName) 
            //: base(ListenerName)
        {
            
        }

        public SMTPTraceListener(string ListenerName, 
                string Server, string From) 
            //: base(ListenerName)
        {
            m_sSMTPServer = Server;
            m_sFrom = From;            
        }

        public SMTPTraceListener(string Server, string From) 
            : this("SMTPTraceListener", Server, From)
        {
            
        }

        public override void Write(string Message)
        {
            try
            {
                SmtpMail.SmtpServer  = m_sSMTPServer;
                System.Web.Mail.MailMessage oMessage = new MailMessage();
                Message.Priority = m_oPriority;
                Message.From = m_sFrom;
                Message.To = m_sTo;
                Message.Body = Message;
                Message.Subject = m_sSubject;
                SmtpMail.Send(oMessage);
                this.Flush();
            }
            catch(Exception ex)
            {    
                throw ex;
            }
        }

        public void Write(string Server, string From, 
           string To, string Subject, string Message)
        {
            this.m_sSMTPServer = Server;
            this.m_sFrom = From;
            this.m_sTo = To;
            this.m_sSubject = Subject;
            this.m_sMessage = Message;
            try
            {
                this.Write(Message);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        public override void WriteLine(string Message)
        {
            try
            {
                this.Write(Message);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
    }//SMTPTraceListener
}//namespace

在代码中使用 SMTPTraceListener

除了引用 *System.Web.Dll* 之外,您还必须包含这些 using 指令:

using System;
using System.Web.Mail;
using System.Diagnostics;            
有了这些,您应该可以在代码中的任何位置包含以下内容:
RK.TraceListeners.SMTPTraceListener oTrace = new 
RK.TraceListeners.SMTPTraceListener("YourServer.YourDomain.com", "mike");

Trace.To = "Someone@Yourdomain.com";
Trace.Subject = "SMTP Trace Listener Test - Do not reply";                        
            
string obj1 = "Someone,  The SMTP Trace Listener is now working!";            
            
Trace.Listeners.Add(oTrace);
Trace.Write("Message from Trace.Write(message)") ;
Trace.Write(obj1) ;        
请注意,在上面的代码中,直接使用了 System.Diagnostics Trace 组件,而无需声明。这是因为每个 .NET 应用程序都原生有一个 Trace 对象,可以随时使用。

关注点

在开发此组件时,有些事情有些有趣

  • 我没有调用基类构造函数(您会注意到这些在 SMTPTraceListener 中被注释掉了)。   出于某种奇怪的原因,**有时**在调用基构造函数然后尝试使用该类时,会出现以下异常:
    System.Exception: Cannot create CDO.Message object 
  • 我发现 System.Web.Mail 只是 Outlook 98 或更高版本附带的协作数据对象 (CDOSys.dll) 的一个包装器。  这个 *CDOSys.dll* 是一个 COM DLL,因此使得 SMTPMail 组件非常**慢**。   可能是因为涉及到大量的互操作。 
  • 由于互操作相关的性能问题,您应该谨慎使用 write 方法,因为它可能会减慢您的应用程序速度。  一种替代方法是实现一个不带参数的 Write 方法。  然后在您的应用程序代码中,设置侦听器的属性,然后生成一个线程来传递 write 方法。  这是一种解决性能问题的方法。
  • SMTPTraceListener Write 方法中,我调用了 Flush 方法。  这会立即强制电子邮件输出,并使组件更加稳定。  将 Flush 从 Write 方法中移除后,我遇到了一些不稳定的行为——例如,有时会抛出异常,但并不总是如此……这可能是一个奇怪的问题,也许有人知道原因?
  • 消息对象中的 FROM 属性应设置为一个有效回复地址,或者一个不包含任何特殊字符的地址。  (感谢 Guy Swartwout 和 Michael Witczak 解决了这个问题)。  就我个人而言,我认为 SMTPMail.Send 方法应该返回比“无法创建 CDO.Message 对象”更有效的异常。 

历史

  • 2003 年 1 月 24 日 - 文章创建
© . All rights reserved.