Email Plugin
The Email Plugin is a tool designed to automate the process of sending email notifications to users who subscribe to specific events. This guide will walk you through the steps to configure the Email Plugin for your Notification Service.
Note: [5.3_25.12] Email Plugin support sending html content. In case the receiver does not support html format, plain text message is generated from the content.
How to use
Configuring the Notification Plugin
For the configuration, there will be seven available parameters which will be configured in theNotification Plugin table in the ConfigurationString section. Each parameter will be separated by a semi-colon ( ; ). Keywords are not case sensitive, values are.
Keyword | Short | Description |
|---|---|---|
ServerAddress | server | The TCP/IP address of the SMTP server |
ServerPort (Optional) | port, p | Port for the SMTP server. Default: 587 |
EmailAddress | email, e | Email address used for sending the notification |
Credential | cred | Windows Credential name containing the username/password for the SMTP server. The credential's type must be generic and not windows. Notes: Make sure the credential is on the same account that the service is running. To add credential by command line: cmdkey /generic:[Credential] /user:[Username] /pass:[Password]. To add user credential into vault entry: %app_root%\Config\FeatureInstall\APP_TransferVaultEntries.bat /name "[Credential]" |
SenderName | name, n | The name to be set up as the sender of the mail |
IgnoreCertError | i | Turn 'True' to ignore certificate errors and log certificate information. |
DisableAuth | da | Turn 'True' to disable authentication |
TraceLevel (Optional) [from version 5.3_25.01][from version 5.3_25.01] | tracelevel, tl | Define trace level for logging. Default value is 3. (Off = 0, Error = 1, Warning = 2, Info =3, Verbose =4, Very Verbose = 5) |
Server Port 587 is recommended as the modern and secure standard for email submission. It supports authentication and encryption through STARTTLS, ensuring that email transmissions are protected.
Below is an example of how the configuration string might look:

An example of the configuration string for Notification Plugin.
ServerAddress=smtp-mail.outlook.com;ServerPort=587;Credential=NotificationService-Test;SenderName=Tester;
Configuring the Notification Subscription
In the Notification Subscription section, the ConfigurationString will contain a list of email addresses that should receive notifications. Each email address should be separated by a semi-colon.

An example of the configuration string for the Notification Subscription.
Source Codes:
namespace ABB.Vtrin.NotificationService
{
public class NotificationServicePlugin_Email : INotificationServicePlugin
{
private static readonly int mDefaultTraceLevel=(int)System.Diagnostics.TraceLevel.Info;
private static readonly Diagnostics.cTraceSwitch mLog = new("EmailPlugin", string.Empty, "Info");
private const int mDefaultPort =587;
private readonly cEmailConfig mConfiguration;
private class cEmailAccount
{
public readonly string? Username;
public readonly System.Security.SecureString? Password;
public cEmailAccount(string? username, System.Security.SecureString? password)
{
Username = username;
Password = password;
}
}
private class cEmailConfig
{
public readonly string ServerAddress;
public readonly string SendingEmailAddress;
public readonly string ServerPort;
public readonly string Credential;
public readonly string SenderName;
public readonly bool IgnoreCertError;
public readonly bool DisableAuth;
public readonly int TraceLevel;
public cEmailConfig(string serveraddress, string sendingemailaddress, string serverport, string credential, string sendername, bool ignorecerterror, bool disableauth, int tracelevel)
{
ServerAddress = serveraddress;
SendingEmailAddress = sendingemailaddress;
ServerPort = serverport;
Credential = credential;
SenderName = sendername;
IgnoreCertError = ignorecerterror;
DisableAuth = disableauth;
}
public static cEmailConfig GetConfiguration(string configurationstring)
{
string serveraddress = string.Empty;
string sendingemailaddress = string.Empty;
string serverport = string.Empty;
string credential = string.Empty;
string sendername = string.Empty;
bool ignorecerterror = false; //Defaut value "false"
bool disableauth = false; //Default value "false"
int tracelevel = NotificationServicePlugin_Email.mDefaultTraceLevel;
var parts = configurationstring.Split(';', System.StringSplitOptions.RemoveEmptyEntries);
foreach(string part in parts)
{
var keyvalue = part.Split('=');
if(keyvalue.Length == 2)
{
var key=keyvalue[0].Trim().ToLower();
var value=keyvalue[1].Trim();
if(string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value))
{
mLog.LogError($"Cannot read configuration string '{part}'. Key or Value is missing.");
continue;
}
switch (key)
{
case "serveraddress":
case "server":
serveraddress=value;
break;
case "emailaddress":
case "email":
case "e":
sendingemailaddress=value;
break;
case "serverport":
case "port":
case "p":
serverport=value;
break;
case "credential":
case "cred":
credential=value;
break;
case "sendername":
case "name":
case "n":
sendername=value;
break;
case "ignorecerterror":
case "i":
ignorecerterror=Utils.ParseBool(value);
break;
case "disableauth":
case "da":
disableauth=Utils.ParseBool(value);
break;
case "tracelevel":
case "tl":
tracelevel=Utils.ParseInt(value, tracelevel);
break;
default:
mLog.LogError($"Unrecognized keyword '{key}'");
break;
}
} else
{
mLog.LogError($"Check configuration string: '{part}'");
}
}
mLog.LogInfo(
$"""
Email Plugin Configuration:
- Server Address : {serveraddress}
- Email Address : {sendingemailaddress}
- Server Port : {serverport}
- Credential : {credential}
- Sender Name : {sendername}
- Ignore Cert Error : {ignorecerterror}
- Disable Auth : {disableauth}
- Trace Level : {tracelevel}
""");
return new cEmailConfig(serveraddress, sendingemailaddress,serverport, credential, sendername, ignorecerterror, disableauth, tracelevel);
}
}
public NotificationServicePlugin_Email(string configuration)
{
mConfiguration = cEmailConfig.GetConfiguration(configuration);
mLog.IntLevel=mConfiguration.TraceLevel;
}
public void HandleMessage(string title, string message, string configurationstring)
{
using(var client = new MailKit.Net.Smtp.SmtpClient())
{
mLog.LogVerbose("Handling message...");
try
{
if(mConfiguration.IgnoreCertError)
{
client.ServerCertificateValidationCallback = (sender, cert, chain, errors) => mCheckingCertificate(sender, cert, errors);
}
var credential = mFetchCredential(mConfiguration.Credential);
if(credential is null)
{
mLog.LogError($"Failed to fetch credential: '{mConfiguration.Credential}'");
return;
}
if(credential.Username is null)
{
mLog.LogError($"UserName in credential '{mConfiguration.Credential}' is null");
return;
}
System.Security.SecureString? password = credential.Password;
var networkcredential = new System.Net.NetworkCredential(credential.Username, password);
string[] addresseslist = mGetEmailAddress(configurationstring);
var connection = mConnect(client, mConfiguration.ServerAddress, mConfiguration.ServerPort, networkcredential, mConfiguration.DisableAuth);
if(connection)
{
foreach(string address in addresseslist)
{
try
{
mSendMessage(client, title, message, mConfiguration.SendingEmailAddress, mConfiguration.SenderName, address);
} catch(System.Exception ex)
{
mLog.LogError("Couldn't send the message: " + ex);
}
}
}
} catch(System.Exception e)
{
mLog.LogError("Couldn't complete, an exception occured: " + e);
}
}
}
private static bool mCheckingCertificate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate? cert, System.Net.Security.SslPolicyErrors errors)
{
if (cert is not null)
{
mLog.LogInfo("Server Certificate \nSender: " + sender + "\nCertificate Subject: " + cert.Subject + "\nCertificate Issuer: " + cert.Issuer + "\nError: " + errors);
}
return true;
}
protected static int mParsePort(string p)
{
if(string.IsNullOrEmpty(p))
{
return mDefaultPort;
}
if(!int.TryParse(p, out var port))
{
mLog.LogError($"Couldn't parse port option: '{p}' to an integer. Returning default port: {mDefaultPort}.");
return mDefaultPort;
}
else
return port;
}
private static bool mConnect(MailKit.Net.Smtp.SmtpClient client, string serveraddress, string serverport, System.Net.NetworkCredential networkcredential, bool disableauth)
{
try
{
int port = mParsePort(serverport);
client.Connect(serveraddress, port);
if(!disableauth)
{
client.Authenticate(networkcredential);
}
if(client.IsConnected)
{
mLog.LogInfo("Connected.");
}
else
{
mLog.LogInfo("Not connected, giving up...");
return false;
}
return true;
} catch(System.Exception ex)
{
mLog.LogError("Couldn't connect, an exception occured: " + ex);
return false;
}
}
private static void mSendMessage(MailKit.Net.Smtp.SmtpClient client, string title, string message, string sendingemailaddress, string username, string receivingemailaddress)
{
var sentmsg = new MimeKit.MimeMessage();
sentmsg.From.Add(new MimeKit.MailboxAddress(username, sendingemailaddress));
sentmsg.To.Add(MimeKit.MailboxAddress.Parse(receivingemailaddress));
sentmsg.Subject = title;
sentmsg.Body = new MimeKit.TextPart("plain") {
Text = message,
};
mLog.LogInfo("Sending FROM: '" + sendingemailaddress.ToString() +
"', TO: '" + receivingemailaddress.ToString() +
"', SUBJECT: '" + title +
"', BODY: '" + message + "'.");
string serverresponse = client.Send(sentmsg);
mLog.LogInfo("Server's response: " + serverresponse);
}
private static cEmailAccount? mFetchCredential(string credential)
{
mLog.LogVerbose($"Fetching credential: {credential}");
try
{
var cred = ABB.Vtrin.cDataLoader.cCredential.Read(credential);
if(cred is not null)
{
mLog.LogVerbose($"Succesfully fetched credential: '{credential}'.");
return new cEmailAccount(cred.UserName, cred.Password);
} else
{
mLog.LogVerbose($"Fetching credential '{credential}' returned NULL.");
}
} catch(System.Exception ex)
{
mLog.LogError($"Exception raised when fetching credential '{credential}'. Message: {ex.Message}." );
}
return null;
}
private static string[] mGetEmailAddress(string emaillists)
{
string[] mails = emaillists.Split(new char[] { ';' }, System.StringSplitOptions.RemoveEmptyEntries);
return mails;
}
}
}Updated 17 days ago
