Disclaimer Fun


Introduction


First of all, let me warn you that I’m not a developer guy, I don’t have a rich development background, so please excuse me if I say things that are not absolutely true (regarding programming, of course) or less technically accurate for all of you programming gurus.


Some organizations choose to add a disclaimer to the end of every message that leaves the internal messaging system to the internet (and sometimes also to every internal message). These disclaimers can have different formats, but generally they have some legal content, stating that the person or group who sends the message holds no responsibility for misusing the contents of the message, and warning any potential recipient to destroy the message if he/she receives it by mistake. Technically speaking you can write whatever you want on the disclaimer and use it for any imaginable means that you can think of.


As disclaimer use grew in popularity, Microsoft decided to provide a way of adding this kind of functionality to Exchange Server. Back in the Exchange 5.5 days, Microsoft developed a specific DLL for this purpose – IMSEXT.DLL – and made it available to the public in general. The use of this DLL was not supported, but at least people had a way of adding disclaimers without buying third-party software.


The use of this DLL involved adding the text in Rich Text Format (RTF) to a specific value in the Windows Registry, so it was not very user friendly.


When Microsoft Exchange 2000 was released it broke that DLL functionality, so Microsoft came up with a new method for adding disclaimers: through the use of SMTP event sinks.


SMTP Event Sinks


At first there was the Exchange 5.5 Event Service. This service was soon replaced with the advent of the new Windows 2000 SMTP service (on which Exchange 200x relies on), which introduced event sinks


Event sinks are used to extend and modify the behavior of the Windows 200x SMTP service.


An SMTP service event is the occurrence of some activity within the SMTP service, such as the transmission or arrival of an SMTP command or the submission of a message into the SMTP service transport component. When a particular event occurs, the SMTP service uses an event dispatcher to notify registered event sinks of the event.


Exchange 200x supports three general category service events:



  • Protocol Events: protocol events occur at the SMTP command verb level between the client and the server when commands are either received or transmitted over the network, such as the delivery of a message locally or externally.
  • Transport Events: transport events occur when the SMTP service receives a message, and that message passes through the SMTP stack.
  • Store Events: store events are used to build procedures that react to events in the Exchange store.

The first two are independent from Exchange, as they rely on the Windows 200x SMTP service.


Disclaimer wizardry


If you want to add a disclaimer to all your outgoing messages there are two Knowledge Base (KB) articles (Q317680 and Q317327) with detailed instructions on how to do that, using either VBScript or building a specific DLL with Visual Basic. They are not difficult to follow, but if you don’t have a programming background (like me) I would recommend that you start with the VBScript one.


What I’m going to explain next is how you can extend the provided samples to add extra functionality. In order not to make this article very long I’ll just provide an example of how to add different disclaimers, based on the sender’s domain.


Let’s imagine the Oil&Vinegar Corporation which has 2 major divisions: Oil and Vinegar. Each division has its own SMTP Domain: oil.pt and vinegar.pt (I’ll use my home country top level domain, PT, for demonstrating purposes, because those domains don’t actually exist at the time I’m writing this). Since those divisions are quite independent, they need different disclaimers for legal reasons.


The challenge here is that the company has a centralized Exchange infrastructure, so the messaging administrator will have to figure out a way of doing this through the use of event sinks.


If we carefully examine the code provided by Microsoft in the two KB articles mentioned above, we notice that the IMessage interface is used to make some decisions. So after doing some research we discover that the IMessage interface implements several methods and properties that can be very useful in this case. The From Property (the e-mail addresses of the principal author or authors of this message) is an excellent candidate to use.


Using the provided code from Microsoft, we can now do some modifications to reach the proposed objective. Let’s see how the modified VBScript and Visual Basic codes look like:



VBSCRIPT



<SCRIPT LANGUAGE=”VBScript”>
Sub ISMTPOnArrival_OnArrival(ByVal Msg, EventStatus)
   OILTextDisclaimer = vbCrLf & “DISCLAIMER:” & OIL Division Sample Disclaimer.”
   OILHTMLDisclaimer = “<p></p><p>DISCLAIMER:<br>OIL Division Sample Disclaimer.”
   VINEGARTextDisclaimer = vbCrLf & “DISCLAIMER:” & VINEGAR Division Sample Disclaimer.”
   VINEGARHTMLDisclaimer = “<p></p><p>DISCLAIMER:<br>VINEGAR Division Sample Disclaimer.”
   GENTextDisclaimer = vbCrLf & “DISCLAIMER:” & “Generic Sample Disclaimer.”
   GENHTMLDisclaimer = “<p></p><p>DISCLAIMER:<br>Generic Sample Disclaimer.”


   If Msg.HTMLBody <> “” Then
      ‘Search for the “</body>” tag and insert our disclaimer before that tag.
      pos = InStr(1, Msg.HTMLBody, “</body>”, vbTextCompare)
      szPartI = Left(Msg.HTMLBody, pos – 1)
      szPartII = Right(Msg.HTMLBody, Len(Msg.HTMLBody) – (pos – 1))
      If InStr(1, Msg.From, “@oil.pt”, 1) Then
         Msg.HTMLBody = szPartI + OILAMPLER.HTMLBody = szPartI + BICHTMLDisclaimer + szPartII
      ElseIf InStr(1, Msg.From, “@vinegar.pt”, 1) Then
         Msg.HTMLBody = szPartI + VINEGARHTMLDisclaimer + szPartII
      Else
         Msg.HTMLBody = szPartI + GENHTMLDisclaimer + szPartII
      End If
   End If


   If Msg.TextBody <> “” Then
      If InStr(1, Msg.From, “@oil.pt”, 1) Then
         Msg.TextBody = Msg.TextBody & vbCrLf & OILTextDisclaimer & vbCrLf
      ElseIf InStr(1, Msg.From, “@vinegar.pt”, 1) Then
         Msg.TextBody = Msg.TextBody & vbCrLf & VINEGARTextDisclaimer & vbCrLf
      Else
         Msg.TextBody = Msg.TextBody & vbCrLf & GENTextDisclaimer & vbCrLf
      End If
   End If


   ‘Commit the content changes to the transport ADO Stream object.
   Msg.DataSource.Save ‘ Commit the changes into the transport Stream


   pEventStatus = cdoRunNextSink
End Sub


</SCRIPT>


VISUAL BASIC



Dim OILTextDisclaimer As String
Dim OILHTMLDisclaimer As String
Dim VINEGARTextDisclaimer As String
Dim VINEGARHTMLDisclaimer As String
Dim GENTextDisclaimer As String
Dim GENHTMLDisclaimer As String


Implements IEventIsCacheable
Implements CDO.ISMTPOnArrival


Private Sub IEventIsCacheable_IsCacheable()
    ‘Just returns S_OK.
End Sub


Private Sub Class_Initialize()
  ‘TODO: Replace the sample disclaimer text with your own text.
   OILTextDisclaimer = vbCrLf & “DISCLAIMER:” & OIL Division Sample Disclaimer.”
   OILHTMLDisclaimer = “<p></p><p>DISCLAIMER:<br>OIL Division Sample Disclaimer.”
   VINEGARTextDisclaimer = vbCrLf & “DISCLAIMER:” & VINEGAR Division Sample Disclaimer.”
   VINEGARHTMLDisclaimer = “<p></p><p>DISCLAIMER:<br>VINEGAR Division Sample Disclaimer.”
   GENTextDisclaimer = vbCrLf & “DISCLAIMER:” & “Generic Sample Disclaimer.”
   GENHTMLDisclaimer = “<p></p><p>DISCLAIMER:<br>Generic Sample Disclaimer.”
End Sub


Private Sub ISMTPOnArrival_OnArrival(ByVal Msg As CDO.IMessage, EventStatus As CDO.CdoEventStatus)
    If Msg.HTMLBody <> “” Then
        Dim szPartI As String
        Dim szPartII As String
        Dim pos As Integer


        ‘Search for the “</body>” tag and insert the disclaimer before that tag.
        pos = InStr(1, Msg.HTMLBody, “</body>”, vbTextCompare)
        szPartI = Left(Msg.HTMLBody, pos – 1)
        szPartII = Right(Msg.HTMLBody, Len(Msg.HTMLBody) – (pos – 1))


        If InStr(1, Msg.From, “@oil.pt”, vbTextCompare) Then
           Msg.HTMLBody = szPartI + OILAMPLER InStr(1, Msg.From, “@bicHTMLDisclaimer + szPartII
        ElseIf InStr(1, Msg.From, “@vinegar.pt”, vbTextCompare) Then
           Msg.HTMLBody = szPartI + VINEGARHTMLDisclaimer + szPartII
        Else
           Msg.HTMLBody = szPartI + GENHTMLDisclaimer + szPartII
        End If
    End If


    If Msg.TextBody <> “” Then
        If InStr(1, Msg.From, “@oil.pt”, vbTextCompare) Then
           Msg.TextBody = Msg.TextBody & vbCrLf & OILTextDisclaimer & vbCrLf
        ElseIf InStr(1, Msg.From, “@vinegar.pt”, vbTextCompare) Then
           Msg.TextBody = Msg.TextBody & vbCrLf & VINEGARTextDisclaimer & vbCrLf
        Else
           Msg.TextBody = Msg.TextBody & vbCrLf & GENTextDisclaimer & vbCrLf
        End If
    End If


    ‘Commit the content changes to the transport ADO Stream object.
    Msg.DataSource.Save
    EventStatus = cdoRunNextSink
End Sub


The final step is registering the event sink. In order to do this you’ll have to use the smtpreg.vbs script provided by Microsoft. From a command prompt run the following commands:



cscript smtpreg.vbs /add 1 onarrival SMTPScriptingHost CDO.SS_SMTPOnArrivalSink “mail from=*”


cscript smtpreg.vbs /setprop 1 onarrival SMTPScriptingHost Sink ScriptName “C:\EventSinkScript.vbs”


(You can omit the “mail from=*” if you want, it will still work).


Please read Q317680 and Q317327 for further details.


Performance issues


Before putting this stuff on a production server (by the way, you should use your external bridge-head server, since all external mail flows through it), you may wonder which of the provided solutions – VBScript or Visual Basic – has more performance.


In order to answer that question I ran a script (see bellow) that sends a total of 5,000 messages, 2,500 from each of the SMTP domains – oil.pt and vinegar.pt.



For i = 0 To 2500
    Set objEmail = CreateObject(“CDO.Message”)
    objEmail.From = “[email protected]
    objEmail.To = “[email protected]
    objEmail.Subject = “OIL disclaimer test”
    ‘objEmail.Textbody = “Just a regular message body text…”
    objEmail.CreateMHTMLBody (“http://localhost/body.htm”)
    objEmail.AddAttachment “file://C:\Disclaimers\attach.dummy”
    objEmail.Send


    objEmail.From = “[email protected]
    objEmail.To = “[email protected]
    objEmail.Subject = “VINEGAR disclaimer test”
    ‘objEmail.Textbody = ” Just a regular message body text…”
    objEmail.CreateMHTMLBody (“http://localhost/body.htm”)
    objEmail.AddAttachment “file://C:\Disclaimers\attach.dummy”
    objEmail.Send
    wscript.echo i
Next


I ran this script twice, once using VBScript and the second time using the DLL built from Visual Basic. While performing the tests I took some measures using Performance Monitor. I must say that I expected much different results from the ones I got. In my mind the VBScript should be much slower than the DLL.


Let’s take a look at the results:




Figure 1: DLL (Visual Basic)




Figure 2: VBScript


Notice the total time taken: VBScript took 9 minutes to send the 5,000 messages, while Visual Basic DLL spent almost 15 minutes. Besides that we can conclude that both methods are very disk intensive and that VBScript will burn more CPU (but it will do it in less time).


I strongly advise you to make your own measures and do some research if you can improve the DLL compilation process.


Third party products


If you don’t want to bother with developing your own solution, you can always use third party products. I’ll mention just a few: ExClaimer, GFI MailEssentials, MailDisclaimer and mxClaim. I’m sure that you can found some more if you search on the internet. Most of these products will add extra functionality that you may or may not use. GFI MailEssentials will provide you disclaimer functionality for free, after the trial period ends.


Conclusion


From my community experience, the process of adding a disclaimer to Exchange is one of the most asked questions. So I’m hopping that now more people will know how to use it. In this article I also showed you how to extend the code provided as an example by Microsoft. I’m sure that much more functionality can be added, just by using the IMessage methods and properties, so why don’t you give it a try?


NOTE: For single server configurations there is an issue that may prevent the described method from working as expected. Microsoft had a KB article – Q288756: SMTP Transport Event Does Not Fire For MAPI Messages – which was retired because the provided workaround (creating a second SMTP Virtual Server) did not always worked in a reliable way. The problem occurs for mail that is sent by using a MAPI client, such as Outlook, which is not in SMTP format, therefore changes that are made by the event’s code are not persisted.


If you are in this situation, my advice is for you to use a third party product.


Useful Links


How to add a disclaimer to outgoing SMTP messages in Visual Basic script
http://support.microsoft.com/?kbid=317680


How to add a disclaimer to outgoing SMTP messages in Visual Basic
http://support.microsoft.com/?kbid=317327


IMessage Interface
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_cdo_imessage_interface.asp


Microsoft Windows 2000 SMTP Service Events
http://go.microsoft.com/fwlink/?LinkId=12279


XFOR: Installing Internet Mail Service Extension Imsext.dll
http://support.microsoft.com/?kbid=258206


XIMS: Internet Mail Service Extension Message Text Append and Prepend
http://support.microsoft.com/?kbid=262097

Leave a Comment

Your email address will not be published.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top