Does anyone know is there a way to make Exchange server 2010 execute some program upon mail receive for some mailbox ?
For example:
I have mails test1#example.com and test2#example.com
I want to execute program1.exe when mail arrives to test1#example.com
and execute program2.exe when mail arrives to test2#example.com
I have looked all options in Exchange management console, and didn't find anything similar.
I made something similar using EWS and powershell. You can download EWS
here
Then you can create an script in powershell that use the Exchange web service
This is the example of my script:
$MailboxName = "mail#domain.com"
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
[void][Reflection.Assembly]::LoadFile($dllpath)
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)
$service.TraceEnabled = $false
$service.Credentials = New-Object System.Net.NetworkCredential("name","password", "domain")
$service.Url="https://mail.yourdomain.com.au/ews/exchange.asmx"
try{
$fldArray = new-object Microsoft.Exchange.WebServices.Data.FolderId[] 1
$Inboxid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$fldArray[0] = $Inboxid
$stmsubscription = $service.SubscribeToStreamingNotifications($fldArray, [Microsoft.Exchange.WebServices.Data.EventType]::NewMail)
$stmConnection = new-object Microsoft.Exchange.WebServices.Data.StreamingSubscriptionConnection($service, 30);
$stmConnection.AddSubscription($stmsubscription)
Register-ObjectEvent -inputObject $stmConnection -eventName "OnNotificationEvent" -Action {
foreach($notEvent in $event.SourceEventArgs.Events){
[String]$itmId = $notEvent.ItemId.UniqueId.ToString()
$message = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($event.MessageData,$itmId)
IF ($message.Subject -eq "execprocess"){
Start-Process "mybat.bat"
}
}
} -MessageData $service
}catch [Exception] {
Get-Date | Out-File C:\logs\logError.txt -Append
"Error : "+ $_.Exception.Message
}
Register-ObjectEvent -inputObject $stmConnection -eventName "OnDisconnect" -Action {$event.MessageData.Open()} -MessageData $stmConnection
$stmConnection.Open()
Then, run the 2 scripts one for every account you need to monitoring.
See the original example here--> Source
Exchange has no out-of-box way to do this. You might want to look at using Exchange Web Services (EWS) subscriptions in an external service to do this.
One way I accomplished this is by writing a powershell script using outlook com objects to scan the inbox for certain criteria and execute a process based on what it finds.
Related
I am new to PowerShell and I am trying to use the System.IO.FileSystemWatcher to monitor the presence of a file in a specified folder. However, as soon as the file is detected I want to stop monitoring this folder immediately and stop the FileSystemWatcher. The plan is to incorporate the PowerShell script into a SQL Agent to enable users to restore their own databases. Basically I need to know the command to stop FileSystemWatcher from monitoring as soon as one file is found. Here is the script so far.
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "C:\TriggerBatch"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
### DEFINE ACTIONS AFTER A EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content "C:\log2.txt" -value $logline
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY
$created = Register-ObjectEvent $watcher Created -Action $action
while ($true) {sleep 1}
## Unregister-Event Created ??
##Stop-ScheduledTask ??
Unregister-Event $created.Id
This will unregister the event. You will probably want to add this to the $action.
Do note that if there are events in the queue they will still be fired.
This might help too.
Scriptblocks that are run as an action on a subscribed event have access to the $Args, $Event, $EventArgs and $EventSubscriber automatic variables.
Just add the Unregister-Event command to the end of your scriptblock, like so:
### DEFINE ACTIONS AFTER A EVENT IS DETECTED
$action = { $path = $Event.SourceEventArgs.FullPath
$changeType = $Event.SourceEventArgs.ChangeType
$logline = "$(Get-Date), $changeType, $path"
Add-content "C:\log2.txt" -value $logline
Unregister-Event -SubscriptionId $EventSubscriber.SubscriptionId
}
This is the pattern for an event that only performs an action once and then cleans itself up.
It's difficult to effectively explore these automatic variables since they are within the scope of a Job, but you can futz with them by assigning them to global variables while you are sketching out your code. You may also get some joy with Wait-Debugger and Debug-Runspace. In the case of the $EventSubscriber variable, it returns the exact object you get if you run Get-EventSubscriber (having created a single subscription already). That's how I found the SubscriptionId property.
If you want to stop/unregister all registered events you can call
Get-EventSubscriber|Unregister-Event
so I want to trigger an action every time a new event occurs in the ForwardedEvents Log in windows with my powershell script.
I found the following code to subscribe to Application Log, but this does not work for the ForwardedEvent log
$Name = 'Application'
# get an instance
$Log = [System.Diagnostics.EventLog]$Name
# determine what to do when an event occurs
$Action = {
# do something when a new ecent occurs
}
# subscribe to its "EntryWritten" event
$job = Register-ObjectEvent -InputObject $log -EventName EntryWritten -SourceIdentifier 'NewEventHandler' -Action $Action
The error I get when trying this code with "ForwardedEvents" as name is:
Register-ObjectEvent : The event log 'ForwardedEvents' on computer '.' does not exist.
Thank you for any help!
EDIT:
My ForwardedEvent Log is active and filled with events. I use Windows 10 for this.
I want to know how can I get notification to my phone when my PC goes online (Turns On).
TeamViewer can help you: https://www.teamviewer.com.
If you install this app on your pc and you sync your user on your iPhone, I guess that whenever your pc starts you will get a notification
If your pc have login in, you can create an powershell script for any time when some one login in your pc you receive an email. Or, this is hard, you can creat an powershell script for when an service start on your pc, send you an email too, you set the service on the start.
$filter="*[System[EventID=7036] and EventData[Data='SIOS DataKeeper']]"
$A = Get-WinEvent -LogName System -MaxEvents 1 -FilterXPath $filter
$Message = $A.Message
$EventID = $A.Id
$MachineName = $A.MachineName
$Source = $A.ProviderName
$EmailFrom = "sios#medfordband.com"
$EmailTo = "sios#medfordband.com"
$Subject ="Alert From $MachineName"
$Body = "EventID: $EventID`nSource: $Source`nMachineName: $MachineName `n$Message"
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("sios#medfordband.com", "MySMTPP#55w0rd");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
Like this, the event is the SIOS DataKeeper, when someone start the service you will receive an email. You can set the service for windows start, when the windows start you will receive an email.
I'm setting a handler for the InstantMessageReceived event, but it only seems to fire on outgoing text messages, not incoming. Here is the code I'm running:
# Register the app with Growl
$icon = "https://docs.google.com/uc?export=download&id=0B1Weg9ZlwneOZmY2b1NSVXJ0Q2s"
$types = '"new-im","new-call","invitation","share"'
& 'C:\Program Files (x86)\Growl for Windows\growlnotify.exe' /a:Lync /ai:$icon /r:$types "Registration."
#We just need the Model API for this example
import-module "C:\Program Files (x86)\Microsoft Lync\SDK\Assemblies\Desktop\Microsoft.Lync.Model.Dll"
#Get a reference to the Client object
$client = [Microsoft.Lync.Model.LyncClient]::GetClient()
#Set the client to reference to the local client
$self = $client.Self
# What do we do here?
$conversationMgr = $client.ConversationManager
# Register events for existing conversations.
$i = 0
for ($i=0; $i -lt $conversationMgr.Conversations.Count; $i++) {
Register-ObjectEvent -InputObject $conversationMgr.Conversations[$i].Modalities[1] -EventName "InstantMessageReceived" `
-SourceIdentifier "new im $i" `
-action {
$message = $EventArgs.Text
Write-Host "DEBUG: New incoming IM - $message"
# Try to get the name of the person...
$contactInfo = $Event.Sender.Conversation.Participants[1].Contact.GetContactInformation([Microsoft.Lync.Model.ContactInformationType[]] #("FirstName", "LastName", "DisplayName", "PrimaryEmailAddress", "Photo", "IconUrl", "IconStream"))
$name = " "
if ($contactInfo.Get_Item("FirstName")) { $name = $contactInfo.Get_Item("FirstName") + " " + $contactInfo.Get_Item("LastName") + ":" }
elseif ($contactInfo.Get_Item("DisplayName")) { $name = $contactInfo.Get_Item("DisplayName") + ":"}
else { $name = $contactInfo.Get_Item("PrimaryEmailAddress") + ":" }
# We need to check if the Lync window (conversation?) has focus or not.
if (1) {
# We need to send our growl notification.
& 'C:\Program Files (x86)\Growl for Windows\growlnotify.exe' /a:Lync /n:new-im /t:"New Instant Message" "$name $message"
}
}
}
# If this exits, no more events.
while (1) { }
Every time I type out an IM message to someone else, it does what I'm trying to do for incoming messages. But nothing ever fires for those, just outgoing. I've been through all the documentation, and there aren't any other candidate events, I'm sure it's this one. But the Modality object just stores some stuff about whether it's an IM or screensharing and the like, nothing useful.
http://msdn.microsoft.com/en-us/library/lync/microsoft.lync.model.conversation.instantmessagemodality_di_3_uc_ocs14mreflyncclnt_members(v=office.14).aspx
Where am I screwing up on this? I prefer answers in Powershell, but I don't think this is a problem specific to Powershell, so if you know how to do it in C# or Visual Basic or something like that, I'd appreciate that too.
I don't have Lync so I can test this myself, but take a look at this link where it shows how to use the API.
The problem is(from what I understand) that there is a modality per participant per media. So for a conversation with two members using only text, there will be 2 modalities, one for incoming messages(from the remote participant) and one for outgoing. This is specified here in
Occurs when an instant message is received, or sent if the InstantMessageModality belongs to the local participant.
Source: MSDN
When you register your object-event, you register it to "your modality", and not the remote modality. To fix it it seems to you need to take each conversation from the manager, look at each participant except the one representing you (check the IsSelf property). Then take the modality from the participants(except yourself) and register for the InstantMessageReceived event.
At least that's what I got out of it, but as said I have no experience with Lync so I could easily be wrong.
My guess at how it could be done(VERY untested):
# What do we do here? You get the manager the keeps track of every conversation
$conversationMgr = $client.ConversationManager
# Register events for existing conversations.
#You may need to use '$conversation in $conversationMgr.GetEnumerator()'
foreach ($conversation in $conversationMgr) {
#Get remote participants
$conversation.Participants | where { !$_.IsSelf } | foreach {
#Get IM modality
$textmod = [InstantMessageModality]($_.Modalities[ModalityTypes.InstantMessage])
Register-ObjectEvent -InputObject $textmod -EventName "InstantMessageReceived" `
-SourceIdentifier "new im $i" `
-action {
#...
}
}
}
We had our server guys set up something on Exchange so that for a particular email address, any attachments sent to it will be dumped to a location on the file server.
The Exchange Event Service controls this behaviour, but it seems that this particular service fails fairly often. I dont know why - I dont have access to the Exchange server and it is run by a team in a different country.
Is it possible to monitor this exchange service programatically so I can warn the users if it goes down? I know that the 'right' solution is to have this handled by the Exchange team, but because of the timezone differences (and their massive workload) I really need to handle it from my end.
Could you do something like this with WebDav?
You could use the following powerShell script:
# Getting status of Exchange Services and look for anything that's "stopped"
$ServiceStatus = get-service MSExch* | where-object {$_.Status -eq "stopped"}
# Convert Result to String
$ServiceStatusText = $ServiceStatus | fl | Out-String
# If $ServiceStatus <> $null then send notification
If ($ServiceStatus -ne $null)
{
###Exchange Server Values
$FromAddress = "Exchange-Alert#YOUR_DOMAIN.local"
$ToAddress = "your_address#YOUR_DOMAIN.com"
$MessageSubject = "CRITICAL: An exchange service is has stopped"
$MessageBody = "One or more Exchange services has stopped running or crashed. Please check the server ASAP for possible issues`n"
$MessageBody = $MessageBody + $ServiceStatusText
$SendingServer = "msexch02.pnlab.local"
###Create the mail message and add the statistics text file as an attachment
$SMTPMessage = New-Object System.Net.Mail.MailMessage $FromAddress, $ToAddress, $MessageSubject, $MessageBody
###Send the message
$SMTPClient = New-Object System.Net.Mail.SMTPClient $SendingServer
$SMTPClient.Send($SMTPMessage)
}
# Else don't do anything and exit
Else
{
$null
}