private void SendMessageWaitingNotification(WOSI.CallButler.Data.CallButlerDataset.ExtensionsRow extension)
        {
            PBXPresenceInfo[] presenceInfos = GetPresenceInfoForExtension(extension.ExtensionNumber);

            if (presenceInfos != null)
            {
                foreach (PBXPresenceInfo presenceInfo in presenceInfos)
                {
                    if (presenceInfo.Status == PBXPresenceStatus.Online)
                    {
                        // Create our notify message
                        SipRequest request = new SipRequest(SIPMethodType.NOTIFY);

                        SIPURI requestURI = new SIPURI(presenceInfo.AddressOfRecord);

                        request.BranchID   = "z9hG4bK" + Guid.NewGuid().ToString();
                        request.RequestURI = new SIPURI(presenceInfo.AddressOfRecord);
                        request.HeaderFields["To", "t"].FieldValue   = requestURI.ExtendedURIStringWithParameters;
                        request.HeaderFields["From", "f"].FieldValue = requestURI.ExtendedURIStringWithParameters;
                        request.HeaderFields.Add("Event", "message-summary");
                        request.HeaderFields.Add("Content-Type", "application/simple-message-summary");

                        StringBuilder sb = new StringBuilder();

                        int newVoicemailCount   = dataProvider.GetNewVoicemailCount(extension.ExtensionID);
                        int totalVoicemailCount = dataProvider.GetVoicemails(extension.ExtensionID).Count;

                        string vmStatus = "no";

                        if (newVoicemailCount > 0)
                        {
                            vmStatus = "yes";
                        }

                        sb.AppendFormat("Messages-Waiting: {0}\r\n", vmStatus);
                        sb.AppendFormat("Voice-Message: {0}/{1}", newVoicemailCount, totalVoicemailCount);

                        request.MessageBody = sb.ToString();

                        ipClient.SendSipRequest(request, presenceInfo.RemoteAddress, presenceInfo.RemotePort);
                    }
                }
            }
        }
        protected override void OnExternalCommand(string command, string commandData, string eventToken, TelecomScriptInterface tsInterface, CallButler.Telecom.TelecomProviderBase telecomProvider, WOSI.CallButler.Data.DataProviders.CallButlerDataProviderBase dataProvider)
        {
            // Parse out our external event action
            if (Enum.IsDefined(typeof(VoicemailExternalCommands), command))
            {
                VoicemailExternalCommands externalCommand = WOSI.Utilities.EnumUtils <VoicemailExternalCommands> .Parse(command);

                switch (externalCommand)
                {
                case VoicemailExternalCommands.CALLBUTLERINTERNAL_AuthenticatePasscode:
                {
                    // Check to make sure our passcode matches our extension
                    string enteredPasscodeHash = WOSI.Utilities.CryptoUtils.CreateMD5Hash(commandData);

                    if (enteredPasscodeHash != extension.Password)
                    {
                        tsInterface.IMLInterpreter.SignalExternalEvent(VoicemailExternalEvents.CALLBUTLERINTERNAL_InvalidPasscode.ToString());
                    }
                    else
                    {
                        // Get our new voicemail count
                        int newVoicemailCount = dataProvider.GetNewVoicemailCount(extension.ExtensionID);

                        tsInterface.IMLInterpreter.SetLocalVariable("NewVoicemailCount", newVoicemailCount.ToString());

                        tsInterface.IMLInterpreter.SignalExternalEvent(VoicemailExternalEvents.CALLBUTLERINTERNAL_ValidPasscode.ToString());
                    }

                    break;
                }

                case VoicemailExternalCommands.CALLBUTLERINTERNAL_SaveNewGreeting:
                {
                    WOSI.CallButler.Data.CallButlerDataset.LocalizedGreetingsRow voicemailGreeting = dataProvider.GetLocalizedGreeting(Properties.Settings.Default.CustomerID, extension.ExtensionID, Properties.Settings.Default.DefaultLanguage);
                    string tmpGreetingFilename = commandData;

                    if (File.Exists(tmpGreetingFilename) && voicemailGreeting != null)
                    {
                        // Change our voicemail greeting to a sound file
                        voicemailGreeting.Type = (short)WOSI.CallButler.Data.GreetingType.SoundGreeting;

                        // Move our greeting sound over
                        string greetingDirectory = WOSI.Utilities.FileUtils.GetApplicationRelativePath(Properties.Settings.Default.GreetingSoundRootDirectory) + "\\" + Properties.Settings.Default.DefaultLanguage;
                        string greetingFilename  = greetingDirectory + "\\" + voicemailGreeting.GreetingID.ToString() + ".snd";

                        if (!Directory.Exists(greetingDirectory))
                        {
                            Directory.CreateDirectory(greetingDirectory);
                        }

                        File.Copy(tmpGreetingFilename, greetingFilename, true);
                        File.Delete(tmpGreetingFilename);

                        voicemailGreeting.Data = WOSI.Utilities.CryptoUtils.GetFileChecksum(greetingFilename);

                        dataProvider.PersistLocalizedGreeting(Properties.Settings.Default.CustomerID, voicemailGreeting);
                    }

                    tsInterface.IMLInterpreter.SignalEventCallback(eventToken);

                    break;
                }

                case VoicemailExternalCommands.CALLBUTLERINTERNAL_FetchNextVoicemail:
                {
                    // Get our voicemail rows
                    WOSI.CallButler.Data.CallButlerDataset.VoicemailsRow[] voicemails = (WOSI.CallButler.Data.CallButlerDataset.VoicemailsRow[])dataProvider.GetVoicemails(extension.ExtensionID).Select("", "Timestamp DESC");

                    // Get our voicemail message index
                    int voicemailIndex = Convert.ToInt32(tsInterface.IMLInterpreter.GetLocalVariable("VoicemailIndex"));
                    voicemailIndex++;

                    if (voicemailIndex < voicemails.Length)
                    {
                        WOSI.CallButler.Data.CallButlerDataset.VoicemailsRow voicemail = voicemails[voicemailIndex];

                        // Create our voicemail intro
                        string voicemailIntro = "";

                        if (voicemailIndex == 0)
                        {
                            voicemailIntro = "First ";
                        }
                        else
                        {
                            voicemailIntro = "Next ";
                        }

                        if (voicemail.IsNew)
                        {
                            voicemailIntro += "New ";
                        }

                        voicemailIntro += "Message received on " + voicemail.Timestamp.ToShortDateString() + " " + voicemail.Timestamp.ToShortTimeString();

                        tsInterface.IMLInterpreter.SetLocalVariable("VoicemailIntro", voicemailIntro);

                        string voicemailFilename = WOSI.Utilities.FileUtils.GetApplicationRelativePath(Properties.Settings.Default.VoicemailRootDirectory) + "\\" + voicemail.ExtensionID.ToString() + "\\" + voicemail.VoicemailID + ".snd";
                        tsInterface.IMLInterpreter.SetLocalVariable("VoicemailSound", voicemailFilename);

                        tsInterface.IMLInterpreter.SetLocalVariable("VoicemailIndex", voicemailIndex.ToString());

                        // Mark the voicemail as read
                        dataProvider.MarkVoicemailRead(voicemail.ExtensionID, voicemail.VoicemailID);

                        if (pbxRegistrar != null)
                        {
                            pbxRegistrar.SendMessageWaitingNotification(voicemail.ExtensionID);
                        }

                        tsInterface.IMLInterpreter.SignalEventCallback(eventToken);
                    }
                    else
                    {
                        tsInterface.IMLInterpreter.SignalExternalEvent(VoicemailExternalEvents.CALLBUTLERINTERNAL_EndOfMessages.ToString());
                    }

                    break;
                }

                case VoicemailExternalCommands.CALLBUTLERINTERNAL_DeleteVoicemail:
                {
                    // Get our voicemail rows
                    WOSI.CallButler.Data.CallButlerDataset.VoicemailsRow[] voicemails = (WOSI.CallButler.Data.CallButlerDataset.VoicemailsRow[])dataProvider.GetVoicemails(extension.ExtensionID).Select("", "Timestamp DESC");

                    // Get our voicemail message index
                    int voicemailIndex = Convert.ToInt32(tsInterface.IMLInterpreter.GetLocalVariable("VoicemailIndex"));

                    if (voicemailIndex < voicemails.Length)
                    {
                        WOSI.CallButler.Data.CallButlerDataset.VoicemailsRow voicemail = voicemails[voicemailIndex];

                        // Delete our voicemail
                        dataProvider.DeleteVoicemail(voicemail.ExtensionID, voicemail.VoicemailID);

                        // Delete our voicemail sound
                        string voicemailFilename = WOSI.Utilities.FileUtils.GetApplicationRelativePath(Properties.Settings.Default.VoicemailRootDirectory) + "\\" + voicemail.ExtensionID.ToString() + "\\" + voicemail.VoicemailID + ".snd";
                        if (File.Exists(voicemailFilename))
                        {
                            File.Delete(voicemailFilename);
                        }

                        voicemailIndex--;
                        tsInterface.IMLInterpreter.SetLocalVariable("VoicemailIndex", voicemailIndex.ToString());

                        if (pbxRegistrar != null)
                        {
                            pbxRegistrar.SendMessageWaitingNotification(voicemail.ExtensionID);
                        }
                    }

                    tsInterface.IMLInterpreter.SignalEventCallback(eventToken);

                    break;
                }
                }
            }
        }