402 lines · 16.6 KB · C#
RawDownload
//******************************************************************************************************//  EmailNotifier.cs - Gbtc////  Copyright © 2016, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this//  file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  05/16/2016 - J. Ritchie Carroll//       Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Generic;using System.ComponentModel;using System.Text;using GSF;using GSF.Net.Smtp;using GSF.TimeSeries;using GSF.TimeSeries.Adapters; namespace DynamicCalculator{    /// <summary>    /// The EmailNotifier is an action adapter which takes multiple input measurements and defines    /// a boolean expression such that when the expression is true an e-mail is triggered.    /// </summary>    [Description("E-Mail Notifier: Sends an e-mail based on a custom boolean expression")]    public class EmailNotifier : DynamicCalculator    {        #region [ Members ]                // Constants        private const string DefaultExpressionText = "x > 0";        private const int DefaultFramesPerSecond = 30;        private const double DefaultLagTime = 5.0D;        private const double DefaultLeadTime = 5.0D;         // Fields        private readonly Mail m_mailClient;        private long m_expressionSuccesses;        private long m_expressionFailures;        private long m_totalEmailOperations;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new instance of the <see cref="EmailNotifier"/>.        /// </summary>        public EmailNotifier()        {            m_mailClient = new Mail();        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets the textual representation of the boolean expression.        /// </summary>        [ConnectionStringParameter]        [Description("Define the boolean expression used to determine if an e-mail should be sent.")]        [DefaultValue(DefaultExpressionText)]        public new string ExpressionText // Redeclared to provide a more relevant description and example value for this adapter        {            get => base.ExpressionText;            set => base.ExpressionText = value;        }         /// <summary>        /// Gets or sets the e-mail address of the message sender.        /// </summary>        /// <exception cref="ArgumentNullException">Value being assigned is a null or empty string.</exception>        [ConnectionStringParameter,        Description("Define the e-mail address of the message sender.")]        public string From        {            get => m_mailClient.From;            set => m_mailClient.From = value;        }         /// <summary>        /// Gets or sets the comma-separated or semicolon-separated e-mail address list of the message recipients.        /// </summary>        /// <exception cref="ArgumentNullException">Value being assigned is a null or empty string.</exception>        [ConnectionStringParameter,        Description("Define the comma-separated or semicolon-separated e-mail address list of the e-mail message recipients."),        DefaultValue("")]        public string ToRecipients        {            get => m_mailClient.ToRecipients;            set => m_mailClient.ToRecipients = value;        }         /// <summary>        /// Gets or sets the comma-separated or semicolon-separated e-mail address list of the message carbon copy (CC) recipients.        /// </summary>        [ConnectionStringParameter,        Description("Define the comma-separated or semicolon-separated e-mail address list of the e-mail message carbon copy (CC) recipients."),        DefaultValue("")]        public string CcRecipients        {            get => m_mailClient.CcRecipients;            set => m_mailClient.CcRecipients = value;        }         /// <summary>        /// Gets or sets the comma-separated or semicolon-separated e-mail address list of the message blank carbon copy (BCC) recipients.        /// </summary>        [ConnectionStringParameter,        Description("Define the comma-separated or semicolon-separated e-mail address list of the e-mail message blank carbon copy (BCC) recipients."),        DefaultValue("")]        public string BccRecipients        {            get => m_mailClient.BccRecipients;            set => m_mailClient.BccRecipients = value;        }         /// <summary>        /// Gets or sets the subject of the message.        /// </summary>        [ConnectionStringParameter,        Description("Define the subject of the e-mail message.")]        public string Subject        {            get => m_mailClient.Subject;            set => m_mailClient.Subject = value;        }         /// <summary>        /// Gets or sets the body of the message.        /// </summary>        [ConnectionStringParameter,        Description("Define the body of the e-mail message.")]        public string Body { get; set; }         /// <summary>        /// Gets or sets the name or IP address of the SMTP server to be used for sending the message.        /// </summary>        /// <exception cref="ArgumentNullException">Value being assigned is a null or empty string.</exception>        [ConnectionStringParameter,        Description("Define the name or IP address of the SMTP server to be used for sending the e-mail message.")]        public string SmtpServer        {            get => m_mailClient.SmtpServer;            set => m_mailClient.SmtpServer = value;        }         /// <summary>        /// Gets or sets a boolean value that indicating whether the message body is to be formatted as HTML.        /// </summary>        [ConnectionStringParameter,        Description("Define the boolean value that indicating whether the message body is to be formatted as HTML."),        DefaultValue(false)]        public bool IsBodyHtml        {            get => m_mailClient.IsBodyHtml;            set => m_mailClient.IsBodyHtml = value;        }         /// <summary>        /// Gets or sets the username used to authenticate to the SMTP server.        /// </summary>        [ConnectionStringParameter,        Description("Define the username used to authenticate to the SMTP server."),        DefaultValue("")]        public string Username        {            get => m_mailClient.Username;            set => m_mailClient.Username = value;        }         /// <summary>        /// Gets or sets the password used to authenticate to the SMTP server.        /// </summary>        [ConnectionStringParameter,        Description("Define the password used to authenticate to the SMTP server."),        DefaultValue("")]        public string Password        {            get => m_mailClient.Password;            set => m_mailClient.Password = value;        }         /// <summary>        /// Gets or sets the flag that determines whether to use SSL when communicating with the SMTP server.        /// </summary>        [ConnectionStringParameter,        Description("Define the flag that determines whether to use SSL when communicating with the SMTP server."),        DefaultValue(false)]        public bool EnableSSL        {            get => m_mailClient.EnableSSL;            set => m_mailClient.EnableSSL = value;        }         /// <summary>        /// Gets or sets the number of frames per second.        /// </summary>        /// <remarks>        /// Valid frame rates for a <see cref="ConcentratorBase"/> are greater than 0 frames per second.        /// </remarks>        [ConnectionStringParameter]        [Description("Defines the number of frames per second expected by the adapter.")]        [DefaultValue(DefaultFramesPerSecond)]        public new int FramesPerSecond // Redeclared to provide a default value since property is not commonly used        {            get => base.FramesPerSecond;            set => base.FramesPerSecond = value;        }         /// <summary>        /// Gets or sets the allowed past time deviation tolerance, in seconds (can be sub-second).        /// </summary>        /// <remarks>        /// <para>Defines the time sensitivity to past measurement timestamps.</para>        /// <para>The number of seconds allowed before assuming a measurement timestamp is too old.</para>        /// <para>This becomes the amount of delay introduced by the concentrator to allow time for data to flow into the system.</para>        /// </remarks>        /// <exception cref="ArgumentOutOfRangeException">LagTime must be greater than zero, but it can be less than one.</exception>        [ConnectionStringParameter]        [Description("Defines the allowed past time deviation tolerance, in seconds (can be sub-second).")]        [DefaultValue(DefaultLagTime)]        public new double LagTime // Redeclared to provide a default value since property is not commonly used        {            get => base.LagTime;            set => base.LagTime = value;        }         /// <summary>        /// Gets or sets the allowed future time deviation tolerance, in seconds (can be sub-second).        /// </summary>        /// <remarks>        /// <para>Defines the time sensitivity to future measurement timestamps.</para>        /// <para>The number of seconds allowed before assuming a measurement timestamp is too advanced.</para>        /// <para>This becomes the tolerated +/- accuracy of the local clock to real-time.</para>        /// </remarks>        /// <exception cref="ArgumentOutOfRangeException">LeadTime must be greater than zero, but it can be less than one.</exception>        [ConnectionStringParameter]        [Description("Defines the allowed future time deviation tolerance, in seconds (can be sub-second).")]        [DefaultValue(DefaultLeadTime)]        public new double LeadTime // Redeclared to provide a default value since property is not commonly used        {            get => base.LeadTime;            set => base.LeadTime = value;        }         /// <summary>        /// Gets or sets output measurements that the action adapter will produce, if any.        /// </summary>        [EditorBrowsable(EditorBrowsableState.Never)]        public override IMeasurement[] OutputMeasurements // Redeclared to hide property - not relevant to this adapter        {            get => base.OutputMeasurements;            set => base.OutputMeasurements = value;        }         /// <summary>        /// Gets or sets the source of the timestamps of the calculated values.        /// </summary>        public new TimestampSource TimestampSource // Redeclared to hide property - not relevant to this adapter        {            get => base.TimestampSource;            set => base.TimestampSource = value;        }         /// <summary>        /// Gets flag that determines if the implementation of the <see cref="DynamicCalculator"/> requires an output measurement.        /// </summary>        protected override bool ExpectsOutputMeasurement => false;         /// <summary>        /// Returns the detailed status of the data input source.        /// </summary>        public override string Status        {            get            {                StringBuilder status = new StringBuilder();                 status.Append(base.Status);                status.AppendLine();                status.AppendFormat("      Expression Successes: {0:N0}", m_expressionSuccesses);                status.AppendLine();                status.AppendFormat("       Expression Failures: {0:N0}", m_expressionFailures);                status.AppendLine();                status.AppendFormat("   Total E-mail Operations: {0:N0}", m_totalEmailOperations);                status.AppendLine();                 return status.ToString();            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Initializes <see cref="EmailNotifier"/>.        /// </summary>        public override void Initialize()        {            const string MissingRequiredMailSetting = "Missing required e-mail setting: \"{0}\"";            Dictionary<string, string> settings = Settings;             if (!settings.TryGetValue(nameof(ExpressionText), out _))                settings[nameof(ExpressionText)] = DefaultExpressionText;             if (!settings.TryGetValue(nameof(FramesPerSecond), out _))                settings[nameof(FramesPerSecond)] = DefaultFramesPerSecond.ToString();             if (!settings.TryGetValue(nameof(LagTime), out _))                settings[nameof(LagTime)] = DefaultLagTime.ToString();             if (!settings.TryGetValue(nameof(LeadTime), out _))                settings[nameof(LeadTime)] = DefaultLeadTime.ToString();             base.Initialize();             // Load required mail settings            if (settings.TryGetValue("from", out string setting) && !string.IsNullOrWhiteSpace(setting))                From = setting;            else                throw new ArgumentException(string.Format(MissingRequiredMailSetting, "from"));             if (settings.TryGetValue("subject", out setting) && !string.IsNullOrWhiteSpace(setting))                Subject = setting;            else                throw new ArgumentException(string.Format(MissingRequiredMailSetting, "subject"));             if (settings.TryGetValue("body", out setting) && !string.IsNullOrWhiteSpace(setting))                Body = setting;            else                throw new ArgumentException(string.Format(MissingRequiredMailSetting, "body"));             if (settings.TryGetValue("smtpServer", out setting) && !string.IsNullOrWhiteSpace(setting))                SmtpServer = setting;            else                throw new ArgumentException(string.Format(MissingRequiredMailSetting, "smtpServer"));             // Load optional mail settings            if (settings.TryGetValue("toRecipients", out setting) && !string.IsNullOrWhiteSpace(setting))                ToRecipients = setting;             if (settings.TryGetValue("ccRecipients", out setting) && !string.IsNullOrWhiteSpace(setting))                CcRecipients = setting;             if (settings.TryGetValue("bccRecipients", out setting) && !string.IsNullOrWhiteSpace(setting))                BccRecipients = setting;             if (string.IsNullOrWhiteSpace(ToRecipients) && string.IsNullOrWhiteSpace(CcRecipients) && string.IsNullOrWhiteSpace(BccRecipients))                throw new ArgumentException("At least one destination e-mail address for one of ToRecipients, CcRecipients or BccRecipients must be defined");             if (settings.TryGetValue("isBodyHtml", out setting) && !string.IsNullOrWhiteSpace(setting))                IsBodyHtml = setting.ParseBoolean();             if (settings.TryGetValue("username", out setting) && !string.IsNullOrWhiteSpace(setting))                Username = setting;             if (settings.TryGetValue("password", out setting) && !string.IsNullOrWhiteSpace(setting))                Password = setting;             if (settings.TryGetValue("enableSSL", out setting) && !string.IsNullOrWhiteSpace(setting))                EnableSSL = setting.ParseBoolean();        }         /// <summary>        /// Handler for the values calculated by the <see cref="DynamicCalculator"/>.        /// </summary>        /// <param name="value">The value calculated by the <see cref="DynamicCalculator"/>.</param>        protected override void HandleCalculatedValue(object value)        {                        if (value.ToString().ParseBoolean())            {                m_expressionSuccesses++;                m_mailClient.Body = Body.Interpolate(Variables);                m_mailClient.Send();                m_totalEmailOperations++;            }            else            {                m_expressionFailures++;            }        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t