none
Handling Outlook-events in Powershell RRS feed

  • Question

  • I would like to write a script, that sends an E-Mail via our companys SMTP-Server using CDO.

    First I tried to write an HTA-application for that purpose, but it became rather fiddly to make it cormfortable enough so that other people may handle it well (because of proper recipient resolving).

    So now I try to use the regular Outlook-Mail mask to prepare the mail first and then catch the send-item event via Powershell to give it's content to a CDO script.

    I'm rather new to powershell-scripting so I didn't come very far before running into the first problems... First of all I'm trying to catch the ItemSend-event. But whenever I run the following code and hit the send-button in my E-Mail, powershell simply crashes. What am I missing? I have never worked with events in powershell and all examples I can find are very very specific and sadly don't apply to my problem at all...

    $WSH = new-Object -ComObject "WScript.Shell" $Outlook = new-Object -ComObject "Outlook.Application" $Action = { WSH.PopUp("TestEvent") } Register-ObjectEvent -InputObject $Outlook -EventName ItemSend -Action $Action $MailItem = $Outlook.CreateItem(0)

    $MailItem.Display()

    • Moved by Bill_Stewart Friday, March 15, 2019 5:38 PM Pointless (why not just sent SMTP mail)
    Tuesday, January 15, 2019 10:42 AM

All replies

  • You cannot use a popup in an event sent by Outlook.

    $Outlook = new-Object -ComObject Outlook.Application
    $Action = {Write-Host 'Mail TestEvent' -fore green}
    Register-ObjectEvent -SourceIdentifier SendMail -InputObject $Outlook -EventName ItemSend -Action $Action
    
    $MailItem = $Outlook.CreateItem(0)
    $MailItem.Display()
    


    \_(ツ)_/

    Tuesday, January 15, 2019 3:25 PM
  • Thanks for your answer, but the script still crashed when I send the E-Mail. :-(

    Tuesday, January 15, 2019 3:50 PM
  • What is "crashed"  is that a technical term for your software.  Perhaps you are getting an error message.  We cannot help with limited or vague information.


    \_(ツ)_/

    Tuesday, January 15, 2019 6:09 PM
  • There is no error code or anything. It's just the "it stopped working"-crash which prompts me to close or debug my application.

    I can't add a screenshot because it says I have to verify my account. How do I do that?
    • Edited by Guido_T Wednesday, January 16, 2019 7:46 AM
    Wednesday, January 16, 2019 7:45 AM
  • What application?  This is PowerShell.  Just copy the exception and post it as text.  It sounds like you are trying to run PS in s compiled exe.

    The Outlook COM object cannot correctly raise events to PowerShell.  The PowerShell engine is shutting down due to an unhandled exception.  Outlook cannot do callbacks to code that it does not trust.


    \_(ツ)_/

    Wednesday, January 16, 2019 10:24 AM
  • Please refer to the screenshot stored at this location. I run the script with the -noexit comandline parameter to keep it running.

    https://social.technet.microsoft.com/Forums/getfile/1381636

    Edit:

    The full comandline to run my script:

    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit "H:\Makroversuche\OutlookItemSendEvent.ps1"

    • Edited by Guido_T Wednesday, January 16, 2019 11:17 AM
    Wednesday, January 16, 2019 11:07 AM
  • As I noted,  you cannot do this because it will cause an exception and PS will terminate.

    The issue is that PS creates the incorrect type of interface code for the Outlook callback. 


    \_(ツ)_/

    Wednesday, January 16, 2019 11:19 AM
  • To add.  The Outlook Interop takes a special kind of multi-cast delegate.  PowerShell can only use a script block and converts it into a simple delegate.  When Outlook calls the delegate the mismatch causes PowerShell to throw an exception. There is now way in PowerShell to create the correct type of delegate.

    You can do this from a C# or other compiled CLR program but there is no direct way to do it in PowerShell.

    Here is the definition of the handler:

    PS D:\scripts> $Outlook.add_ItemSend
    
    OverloadDefinitions
    -------------------
    void add_ItemSend(Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler )

    The type is: "Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler "

    We can make one of these from the Interop.

    PS D:\scripts> [Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler]::New
    
    OverloadDefinitions
    -------------------
    Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler new(System.Object , System.UIntPtr )

    But it does not have the correct signature for PowerShell. 


    \_(ツ)_/

    Wednesday, January 16, 2019 11:37 AM
  • Wow, thanks for your very detailed response. Well that's a pitty... Might there be some workaround? I tried to register the send-event for my mail-item directly, but PS says, there is no such event.

    I don't have the possibility to develop C/C#/C++ or whatever applications on my work PC as I don't have any compiler installed.

    Maybe there's an alternative way with VBS? I actually already managed to fire the ItemSend-event there but canceling doesn't work...


    Dim OutlookApplication
    Dim MailItem
    Const olMailItem = 0
    Const olDiscard = 1
    Dim CDO_Done: CDO_Done = False

    Set OutlookApplication = WScript.CreateObject("Outlook.Application", "Outlook_")
    'Alternative way:
    'Set OutlookApplication = CreateObject("Outlook.Application")
    'WScript.ConnectObject OutlookApplication, "Outlook_"

    Set MailItem = OutlookApplication.CreateItem(olMailItem) MailItem.UserProperties.Add "CDOFlag", 20, false, false MailItem.Display '(...) some code to add recipients, subject, text, etc... depending on the given WScript.Arguments While Not CDO_Done 'keep the script alive WScript.Sleep 1 WEnd
    MailItem.Close olDiscard
    Function CDOSendMessage() 'some code to send the data to our smtp server, return true if successfull CDOSendMessage = True End Function Sub Outlook_ItemSend(byVal Item, byRef Cancel) If Not Item.UserProperties.Find("CDOFlag") Is Nothing Then Cancel = True 'does not work. The mail just gets sent out regularly.... If CDOSendMessage() then CDO_Done = True Else Cancel = False MsgBox "Sending message via CDO failed." WScript.Quit End If End If End Sub


    • Edited by Guido_T Wednesday, January 16, 2019 12:04 PM
    Wednesday, January 16, 2019 11:58 AM
  • Post in the Outlook developers forum for more assistance.

    VBS does not use Interop.  It can intercept some COM events. 


    \_(ツ)_/

    Wednesday, January 16, 2019 12:13 PM
  • Here is the exception caused by Outlook:

    Log Name:      Application
    Source:        .NET Runtime
    Date:          1/16/2019 7:25:09 AM
    Event ID:      1023
    Task Category: None
    Level:         Error
    Keywords:      Classic
    User:          N/A
    Computer:      Alpha
    Description:
    Application: powershell.exe
    Framework Version: v4.0.30319
    Description: The process was terminated due to an internal error in the .NET Runtime at IP 00007FFEDF8E3D60 (00007FFEDF8E0000) with exit code 80131506.
    
    Event Xml:
    <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
      <System>
        <Provider Name=".NET Runtime" />
        <EventID Qualifiers="0">1023</EventID>
        <Level>2</Level>
        <Task>0</Task>
        <Keywords>0x80000000000000</Keywords>
        <TimeCreated SystemTime="2019-01-16T12:25:09.820054300Z" />
        <EventRecordID>9437</EventRecordID>
        <Channel>Application</Channel>
        <Computer>Alpha</Computer>
        <Security />
      </System>
      <EventData>
        <Data>Application: powershell.exe
    Framework Version: v4.0.30319
    Description: The process was terminated due to an internal error in the .NET Runtime at IP 00007FFEDF8E3D60 (00007FFEDF8E0000) with exit code 80131506.
    </Data>
      </EventData>
    </Event>


    \_(ツ)_/

    Wednesday, January 16, 2019 12:29 PM