How to write an OnArrival-type SMTP event sink in managed code by using Visual Studio .NET 2003 (894286)



The information in this article applies to:

  • Microsoft Exchange Server 2003 Standard Edition
  • Microsoft Windows Server 2003, Standard Edition
  • Microsoft Visual Studio .NET (2003), Professional Edition

Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements.

INTRODUCTION

This article contains an overview of how to write event sinks for SMTP events in managed code by using wrappers that obscure some of the details of communicating with the unmanaged server.

MORE INFORMATION

The following example illustrates how to write a managed OnArrival-type SMTP event sink that handles incoming commands in Microsoft Visual C# .NET and Microsoft Visual Basic .NET. Use this kind of event sink to handle incoming SMTP commands and messages and to process them as needed.

Generate unmanaged code to tie into the Event sink architecure in Microsoft Exchange

  1. Download and then extract the sample code from the following Microsoft Developer Network (MSDN) article:Note This MSDN article contains sample code for two libraries that you must have to connect to the unmanaged events that Exchange makes available.
  2. At a command prompt, run the following command:

    Drive:\\Program Files\Microsoft Visual Studio .NET\Common7\Tools\vsvars32.bat

  3. From the folder of the interop, run Nmake.exe. Typically, this folder is \ManagedSinksWP\Interop.
  4. The interop DLL is Microsoft.Exchange.Transport.EventInterop.dll. Copy this file to the \ManagedSinksWP\Wrappers folder.
  5. Generate a new strong-named pair by using the following command:

    SN.exe -k c:\key_wrapper.snk

  6. Create a new AssemblyInfo file (AssemblyInfo.cs) in the wrappers folder by using the following code.
    using System.Reflection;
    using System.Runtime.CompilerServices;
    
    [assembly: AssemblyTitle("")]
    [assembly: AssemblyDescription("")]
    [assembly: AssemblyConfiguration("")]
    [assembly: AssemblyCompany("")]
    [assembly: AssemblyProduct("")]
    [assembly: AssemblyCopyright("")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    [assembly: AssemblyVersion("1.0.*")]
    [assembly: AssemblyDelaySign(false)]
    [assembly: AssemblyKeyFile("c:\\key_wrapper.snk")]
    [assembly: AssemblyKeyName("")]
    
  7. In the same environment as the interop, run the following command from the wrappers folder:

    csc /t:library /out:Microsoft.Exchange.Transport.EventWrappers.dll /r:Microsoft.Exchange.Transport.EventInterop.dll *.cs /unsafe

Generate and then compile the managed class to handle the event sink

  1. Start Microsoft Visual Studio .NET 2003.
  2. On the File menu, point to New, and then click Project.
  3. Under Project Types, click Visual C# Projects. Under Templates, click Class Library. Name the project "ManSMTPLib".
  4. In Solution Explorer, right-click the project, and then click Properties.
  5. In Project Property Pages dialog box, click the Configuration Properties folder.
  6. Click Build, and then set the Register for COM interop setting to True. Click OK to close the Project Property Pages dialog box.
  7. In Solution Explorer, right-click References, and then click Add Reference. Add references to the following two assemblies to your project:
    • Microsoft.Exchange.Transport.EventInterop.dll
    • Microsoft.Exchange.Transport.EventWrappers.dll
  8. In Solution Explorer, right-click Class1.cs, click View Code, and then replace the generated code for the class by using the following code example.

    Visual C# .NET code
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using Microsoft.Exchange.Transport.EventInterop;
    using Microsoft.Exchange.Transport.EventWrappers;
     
     
    namespace SampleManagedSink
    {
          [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]  //For more information, see step 10.
          public class ExchSinkClass : IMailTransportSubmission, IEventIsCacheable
          {
                void IEventIsCacheable.IsCacheable()
                {
                }
     
                void IMailTransportSubmission.OnMessageSubmission( Microsoft.Exchange.Transport.EventInterop.MailMsg pIMailMsg , Microsoft.Exchange.Transport.EventInterop.IMailTransportNotify pINotify , System.IntPtr pvNotifyContext )
                {
                      try
                      {
                            string sSource = "dotNET Sample App";
                            string sLog = "Application";
                            string sEvent = "Sample Event";
                            if (!EventLog.SourceExists(sSource))
                                                    EventLog.CreateEventSource(sSource,sLog);                         
                            EventLog.WriteEntry(sSource,sEvent);
                      }
                      finally
                      {
                      }
                }
          }
    }
    
    Visual Basic .NET code
    Imports System
    Imports System.Diagnostics
    Imports System.Runtime.InteropServices
    Imports Microsoft.Exchange.Transport.EventInterop
    Imports Microsoft.Exchange.Transport.EventWrappers 
    Namespace SampleManagedSink
    
    ' For more information about the GUID, see step 10.
        <Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")>Public Class ExchSinkClass
            Implements IMailTransportSubmission, IEventIsCacheable
             Public Sub IsCacheable() _
               Implements IEventIsCacheable.IsCacheable
             End Sub
            Public Sub OnMessageSubmission(ByVal pIMailMsg As Microsoft.Exchange.Transport.EventInterop.MailMsg, ByVal pINotify As Microsoft.Exchange.Transport.EventInterop.IMailTransportNotify, ByVal pvNotifyContext As System.IntPtr) _
                Implements IMailTransportSubmission.OnMessageSubmission
                Try
                    Dim sSource As String = "Sample dotNET Exchange Sink Library"
                    Dim sLog As String = "Application"
                    Dim sEvent As String = "Sample dotNET Exchange Sink was triggered."
                    If (Not EventLog.SourceExists(sSource)) Then EventLog.CreateEventSource(sSource, sLog)
                    EventLog.WriteEntry(sSource, sEvent)
                Catch
                    ' Put some code here to handle errors.
                    ' Currently, any error will just be ignored.
                Finally
     
                End Try
            End Sub
        End Class
    End Namespace 
  9. Generate a new GUID. To generate a new GUID, click Create GUID on the Tools menu.
  10. Click Registry Format, click New GUID, and then click Copy to copy the new GUID to the Clipboard. You will paste this new GUID into your code that you pasted in step 8. Make sure that you exclude the enclosing braces ({ }).
  11. Generate another strong-named key pair by using the following command:

    SN.exe -k c:\key_sink.snk

  12. In Solution Explorer, click AssemblyInfo.cs, right-click View Code, and then set the AssemblyKeyFile attribute with the following code:

    Visual C# .NET code
    [assembly: AssemblyKeyFile("c:\\key_sink.snk")]
    
    Visual Basic .NET code
    <Assembly: AssemblyKeyFile("c:\key_sink.snk")>
    
  13. On the Build menu, click Build Solution. If the object is built on a non-production server, copy the event sink object to the production server, and then use the RegAsm.exe tool to register the event sink object on the server.

Implement the event sink and then register it into Exchange

  1. On the production server, open a Command Prompt window, and then type the following commands:

    RegAsm.exe ManSMTPLib.dll /tlb: ManSMTPLib.tlb /codebase

    RegAsm.exe Microsoft.Exchange.Transport.EventWrappers.dll /codebase

    RegAsmexe Microsoft.Exchange.Transport.EventInterop.dll /codebase

  2. Register the object on your production server as an event sink by using the Smtpreg.vbs script. To do this, use the following code example.

    Visual C# .NET code
    cscript smtpreg.vbs /add 1 OnTransportSubmission "Sample managed sink" SampleManagedSink.ExchSinkClass "MAIL FROM=*" 28001 
    Visual Basic .NET code
    cscript smtpreg.vbs /add 1 OnTransportSubmission "Sample managed sink" ManSMTPLib.SampleManagedSink.ExchSinkClass "MAIL FROM=*" 28001
    
    To obtain the Smtpreg.vbs script, visit the following MSDN Web site:

REFERENCES

For more information, visit the following MSDN Web site:

Modification Type:MinorLast Reviewed:4/28/2006
Keywords:kbHOWTOmaster kbhowto kbinfo KB894286 kbAudDeveloper