powershellemailoutlookoffice-automationwindows-server-2019

Send email with powershell in windows server 2019


I use a script to send mail from powershell, through outlook:

Try{
$ol = New-Object -comObject Outlook.Application
$mail = $ol.CreateItem(0)
$mail.To = ""
$mail.Subject = "Test from PS"
$mail.Display( $true )
$ol.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ol) | Out-Null
}
Catch{ write-host [ERROR] $Error }

It works correctly in windows 10, but in server 2019 the sent message remains in the outbox, and it is only sent if I enter outlook expressly.

Is there something missing from the script to force outlook to immediately send the generated message?

I have tested it with outlook 2019 and 2021 In outlook options, programmatic access is 'never warn me about suspicious activity'


Solution

  • The code creates a new mail item in Outlook and then display it to a user by calling the Display method:

    $mail.Display( $true )
    

    Which I suppose doesn't make any sense on the server side.

    If you need to send the mail item you need to call the Send method instead of Display one. So, the code may look like that:

    Try{
    $ol = New-Object -comObject Outlook.Application
    $olNamespace = $ol.GetNamespace("MAPI")
    $mail = $ol.CreateItem(0)
    $mail.To = ""
    $mail.Subject = "Test from PS"
    $mail.Send()
    $olNamespace.SendAndReceive(false);
    $ol.Quit()
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ol) | Out-Null
    }
    Catch{ write-host [ERROR] $Error }
    

    Also you may try using the NameSpace.SendAndReceive method which initiates immediate delivery of all undelivered messages submitted in the current session, and immediate receipt of mail for all accounts in the current profile. SendAndReceive provides the programmatic equivalent to the Send/Receive All command that is available when you click Tools and then Send/Receive.

    If you don't need to synchronize all objects, you can use the SyncObjects collection object to select specific objects. For more information, see NameSpace.SyncObjects. It makes sense to wait until the sync process is finished and only then close Outlook by calling the Quit method. The SyncObject.SyncEnd event is fired immediately after Microsoft Outlook finishes synchronizing a user's folders using the specified Send/Receive group.

    Also be aware, Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.

    If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution.

    Read more about that in the Considerations for server-side Automation of Office article.

    As a possible workaround you may consider using the Graph API or EWS, see Send email messages by using EWS in Exchange for more information.