Become a Columnist Microsoft Exchange Site Microsoft Support SiteMSDN Exchange Site

   

Subscribe to OutlookExchange
Anderson Patricio
Ann Mc Donough
Bob Spurzem
Brian Veal
Catherine Creary
Cherry Beado
Colin Janssen
Collins Timothy Mutesaria
Drew Nicholson
Fred Volking
Glen Scales
Goran Husman
Guy Thomas
Henrik Walther
Jason Sherry
Jayme Bowers
John Young
Joyce Tang
Justin Braun
Konstantin Zheludev
Kristina Waters
Kuang Zhang
Mahmoud Magdy
Martin Tuip
Michael Dong
Michele Deo
Mitch Tulloch
Nicolas Blank
Pavel Nagaev
Ragnar Harper
Ricardo Silva
Richard Wakeman
Russ Iuliano
Santhosh Hanumanthappa
Steve Bryant
Steve Craig
Todd Walker
Tracey J. Rosenblath
 
 

IM Announcements to all user with a Exchange mailbox using an On_Arrival SMTP event sink

Introduction                      Download script
    If everyone in your office is using Exchange Instant messaging you may want to provide a method to allow some users to send a quick announcement to all online users. One solution for this is to setup a mailbox that your users can send an email to with their announcement as the subject. This email will then trigger the On_Arrival SMTP event sink on the Instant Messaging Server which will spawn a script that queries Active directory for all IM users and then establishes a session with each user and sends them a message based on the subject line of the initiating email.

Comments
    There are many other ways to provide the above functionality I have used the above method because it was an easy way of achieving the desired result. Some other methods would be providing people a web page that executes a script or use a Web Storage System event sink (article coming soon). If your going to be using event sinks with Exchange and your server is heavily trafficked you shouldn't use VBscripts because of the performance bottleneck these can create, instead write them in C or at least VB. For development and simplicity however you can't beat VBS.

Caveats
  There is one main caveat with this code in that the SMTP OnArrival event only fires when messages are sent from one server to another (It doesn't fire on local delivery). If you have only one Exchange server in your company then you will need to consider using a WSS event sink. To use the code in this article you should have a dedicated  IM server, create your announcement mailbox on this server and then setup the event sink to fire on the SMTP connector for this server.  As a precursor I recommend you read Q273233 and this article which you can get from DEVX which gives a good background on using the SMTP On Arrival sink.

SMTP OnArrival Event
    The SMTP OnArrival event is a synchronous event  meaning that when it is fired it will block any new messages from arriving at the specified SMTP connector until the event sink has successfully completed. With this in mind its preferable to have the event script code execute as quickly as possible deal with any errors then get back to allowing mail to flow through the SMTP connector (this is where poor code could cause a bottleneck). For this reason  I have designed the script in two parts the first script spawns a process to start the second script and sends the subject of the message as script arguments.

Installation
    To install and use an SMTP event sink you will first require the SMTPREG.vbs script that is included in the Exchange SDK. Create a directory on your servers c: drive called c:\smtpevt and copy the smtpreg.vbs ,smtpevt.vbs and sndmsg.vbs scripts into this directory. To create an event sink for the smtpevt.vbs script that will fire when mail is received addressed to IMannouce. From a command line in the c:\smtpevt directory type

cscript smtpreg.vbs /add 1 onarrival IMannouce  CDO.SS_SMTPOnArrivalSink "mail to=imannouce@yourdomain.com"

You then need to associate the smtpevt.vbs script to this event sink you have created using

cscript smtpreg.vbs /setprop 1 onarrival  IMannouce  Sink ScriptName c:\smtpevt\smtpevt.vbs

Once this has been done you need to stop and start the SMTP service and your event sink will now be active.

If you wish to delete this event sink latter type

cscript smtpreg.vbs /remove 1 onarrival IMannouce  


The Code
  
 Okay here we go, As I mentioned before there are two separate scripts for this function one script which is the event sink script simply spawns a process to send a Instant message and passes the subject line of the received mail to the other script. Let start here

Script Smtpevt.VBS (Event Sink Script)

<SCRIPT LANGUAGE="VBScript">
Sub ISMTPOnArrival_OnArrival(ByVal Msg, EventStatus )
Dim Stm
Dim WshShell
Stm = Msg.Subject
set WshShell = CreateObject("WScript.Shell")
strrun = WshShell.run ("c:\smtpevt\sndmsg.vbs " & stm)
set WshShell = nothing
End Sub

</SCRIPT>

    As you can see this code is dead easy it starts the other script and then goes back to what it was doing (it doesn't wait around to see if the other script was successfully or not). Note when you are writing any event sink scripts you must enclose you scripts in the <SCRIPT LANGUAGE="VBScript"></script> tags or your scripts wont work.

Script Sndmsg.vbs

    The next piece of code is slightly more complicated it uses as the base  the code I described in the "Sending and Instant Message's Programmatically article" for more information on customising the IM part of this script see this article. Lets have a look at this script

Set objArgs = WScript.Arguments
For I = 0 to objArgs.Count - 1
message = message & objArgs(I) & " "
Next
set OU = GetObject("LDAP://CN=Users,DC=AD1")
dim strtest, loopexit
loopexit = 1
call sendmsg()

    The front-end of this code accepts the subject line passed from the smtpevt.vbs script as a bunch of script arguments and loads them into one string for the message. The next bit of code sets up the Active directory connection (Hint you need to customise this bit here with your own AD and OU names).

sub sendmsg()
	strMsgHeader = "Mime-Version: 1.0" & vbCrLf & "Content-Type: text/plain; charset=UTF-8" & vbCrLf & vbCrLf
	msgType = IM_MSG_TYPE_NO_RESULT
	Set oIMApp = CreateObject("MSExchangeIM.MSIMHost")
	Set oIMServ = oIMApp.CreateContext("Default", 0)
	strtest = Array("newb1@exbend","newb1","pass","ad1")
	oIMServ.logon strtest
	do until iState = 2
		oIMServ.GetLocalState iState, strState, strDescr
		if loopexit = 1000 then
			exit sub
		end if
		loopexit = loopexit + 1
	loop
	For Each oUser in OU
		if oUser.Class = "user" then
			if oUser.msExchIMAddress <> "" then
    				set oIMsession = oIMServ.CreateIMSession(oUser.msExchIMAddress)
				oIMsession.Sendtext strMsgHeader, message, msgtype
				On Error resume Next
			End If
		End If
	Next
	Set OU = Nothing	
	OIMServ.logoff()
	set oIMApp = nothing
end sub

    The body of the code opens up a connection to Active directory and searches each user object in the nominated OU for an Instant messaging user address. If one is found it tries to establish a session with this user and send them the message. If the user is not online an error will be generated and be caught by the "On error resume next" line and processing will continue.

Security
   
You properly don't want to allow everybody to use this announcement script so you might need to put some security measures in place. There are many ways to achieve this some examples are if you only want one person to be able to use this script when your registering the event you can place a condition so the script will only fire when mail arrives from a specific user using something such as "mail from=bob@hotmail.com". Or use two mailboxes the first mailbox acts as the user interface and verifies the sender of the email via normal outlook rules and then forwards it to a hidden mailbox on the IM server.

Improvements
    
There are many areas of improvement for this script with the ability to query active directory opening up lots of possibilities. There are some limitations that you can't get around with just using an SMTP event sink so in these cases its better to invest in the effort of a WSS event sink (Article coming soon).

Download script


Disclaimer: Your use of the information contained in these pages is at your sole risk. All information on these pages is provided "as is", without any warranty, whether express or implied, of its accuracy, completeness, fitness for a particular purpose, title or non-infringement, and none of the third-party products or information mentioned in the work are authored, recommended, supported or guaranteed by Stephen Bryant or Pro Exchange. OutlookExchange.Com, Stephen Bryant and Pro Exchange shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages.

Copyright Stephen Bryant 2008