The Core Technologies Blog

Our Software // Windows Services // 24×7 Operation


3 Proven Ways to Send Email from a Windows Service (Without Outlook)

Sending Email from a Windows Service

Not all Outlook functions work from a Windows Service

Calling Outlook from a Windows Service can be problematic. Even though many operations work fine, Microsoft has issued some pointed advice for customers looking to run any Office application in the background in Session 0:

All current versions of Microsoft Office were designed, tested, and configured to run as end-user products on a client workstation. They assume an interactive desktop and user profile. They do not provide the level of reentrancy or security that is necessary to meet the needs of server-side components that are designed to run unattended.

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.

Very disappointing!

So instead of calling Outlook, which may be unreliable when run in the context of a service, look to one of these alternative solutions instead:

Solution #1: Have your Windows Service call PowerShell to send basic email

If you don’t want to install any third-party utilities, you can leverage Microsoft’s ubiquitous PowerShell utility to deliver your messages. And to help, we’ve created a simple script that, given eight required parameters, will send an email to any address:

<#
   send-email.ps1
   
   Summary: Sends email.

   Usage: 
      send-email.ps1 <FROM-EMAIL> <TO-EMAIL> <SUBJECT> <BODY> <SMTP-SERVER> <USERNAME> <PASSWORD>

      Example:
         send-email.ps1 "admin@coretechnologies.com" "alerts@coretechnologies.com" "Server down" 
           "Server 'FileServer1' is down!" "smtp.gmail.com" 587 "admin@coretechnologies.com" "pwd74YKYRO"

   2020, Core Technologies Consulting, LLC (https://coretechnologies.com)
#>

if ($args.Count -ne 8) {
   Write-Host "Passed" $args.Count "parameters; expected 8."
   Write-Host "Usage:"
   Write-Host "send-email.ps1 <FROM-EMAIL> <TO-EMAIL> <SUBJECT> <BODY> <SMTP-SERVER> <SMTP-PORT> <USERNAME> <PASSWORD>"
   exit 1
}

$fromEmail = $args[0]
$toEmail = $args[1]
$subject = $args[2]
$body = $args[3]
$smtpServer = $args[4]
$smtpPort = $args[5]
$userName = $args[6]
$password = $args[7]

$smtpClient = New-Object Net.Mail.SmtpClient($smtpServer, $smtpPort)
$smtpClient.EnableSsl = $true
$smtpClient.Credentials = New-Object System.Net.NetworkCredential($userName, $password)

$smtpClient.Send($fromEmail, $toEmail, $subject, $body)

You can download the PowerShell script here. Please feel free to adapt it for your needs.

Your email provider will determine the SMTP server and port number you should use. For example, if your provider is Gmail, the SMTP server is “smtp.gmail.com” and the port is 587.

To invoke the script from an application, run the PowerShell executable with the -File option. Specify the full path to the script along with the eight required parameters.

For example, if you’ve saved the script in C:\Utilities and you’re sending via Gmail, your command line will look like this:

powershell.exe -File "C:\Utilities\send-email.ps1" from@coretechnologies.com to@coretechnologies.com "Server Down Alert" "Server 'FileServer1' is down!" smtp.gmail.com 587 from@coretechnologies.com "PWD8581JG$"

Watch out for quotes in the subject and body and escape accordingly!

Solution #2: Use SwithMail to deliver complex messages from your Windows Service

SwithMail is a free, no-nonsense utility that can send very detailed email messages. It supports all the important messaging options, including:

  • HTML formatting
  • Multiple attachment files
  • CC and BCC recipients
  • “ReplyTo” configuration

After downloading the SwithMail zip file and extracting its contents to a suitable location, double-click SwithMail.exe to reveal the comprehensive command line:

SwithMail command line usage

Simply specify the options you need. For example, here is a sample command line that sends the same message as the PowerShell script above:

SwithMail.exe /Silent /FromAddress from@CoreTechnologies.com /ToAddress to@coretechnologies.com /Subject "Server down" /HTML /Body "Server <b>FileServer1</b> is down!" /Server smtp.gmail.com /Port 587 /SSL /Username from@coretechnologies.com /Password "PWD8581JG$"

If you prefer, you can compose an XML file with all the details and pass to SwithMail instead, like this:

SwithMail.exe /XML "C:\Your-SwithMail-Settings.xml"

If you’re having trouble configuring SwithMail, add the /Log parameter and a path to a log file. Check the file for error messages after a failed run.

Solution #3: Update your Windows Service code to send email directly

If you have access to the service’s source code, your best option may be to include code to send email using the SMTP classes built into your programming language.

For example, if you are using C#, we recommend incorporating the System.Net.Mail.MailMessage and System.Net.Mail.SmtpClient classes. They are very easy to use.

Here is some sample C# code (error handling omitted for clarity):

// Compose the message.
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("from@coretechnologies.com");
mailMessage.To.Add(new MailAddress("to@coretechnologies.com"));
mailMessage.Subject = "Server down";
mailMessage.Body = "Server <b>FileServer1</b> is down!";
mailMessage.BodyFormat = MailFormat.Html;
// Construct the SMTP object that will send the message.
smtpClient = new SmtpClient("smtp.gmail.com", 587);
smtpClient.EnableSsl = true;
smtpClient.Credentials = new System.Net.NetworkCredential("from@coretechnologies.com", "PWD8581JG$");
// Send the message!
smtpClient.Send(mailMessage);

Get in touch if you need help sending email from your Windows Service

Hopefully one of these three solutions, which don’t involve Outlook, will work from your service. If not — or if you have questions about the methods outlined above — please don’t hesitate to reach out to our support team. We’re here to help!

Posted in Windows Services | Tagged , , , , , | Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *