Broadcast By E-mail

For developer

Introduction

Ozeki Broadcast By E-mail is an excellent software product that enables you to send automated e-mail messages. This powerful technology operates 24/7 so it is the best solution for a stable automated system. Ozeki Broadcast By E-mail is the ideal platform for sending reminders, event notifications, direct mails, etc.

Software requirements

  • Microsoft Windows
  • Microsoft Visual Studio
  • Ozeki Phone System

Installation and Configuration of Ozeki Phone System

In order to connect to the server, Ozeki Phone System has to be installed. A Setup Guide can be found here: How to install and configurate your Ozeki Phone System, the installation package can be downloaded from the following page: Download. After the installation, the main page of the PBX can be accessed on the http://localhost:7777/Home address (Figure 1).

ozeki phone system login screen
Figure 1 - Ozeki Phone System login screen

For the first login attempt, use the username and password, which was provided during the installation process.

New user can be added to the system with the Add user button. It can be found under the Office users menu item in the Connections menu (Figure 2).

add new user
Figure 2 - Add new user

The username and password specified here can be used to connect to the system, in the OPSClient LoginAsync method (Figure 3).

new user configuration panel
Figure 3 - New user configuration panel

Project development

  1. Let us create a new WPF Application project with the help of File/New/Project menu item.
  2. Let us add the OPSSDK.dll file to the project references in the Solution Explorer by clicking on Add Reference… menu item. This will ensure the connection interface to Ozeki Phone System.

1 Ozeki Phone System E-mail Sender

The Ozeki Phone System E-mail Sender allows e-mail sending by connecting to Ozeki Phone System. The e-mails are sent according to a provided a list. The e-mail Sender forwards the mail, which you want to send to Ozeki Phone System. If there is an appropriately set E-mail provider Outside line and Dial plan rule then it sends the message to that provider. The E-mail provider sends the message to the recipient and sends a delivery report about the status of this message as well. Simultaneous e-mail sending is allowed depending on the set simultaneous message sending number. This results an automated and clear message sending. Different groups can be stored in various lists and according to those lists, previously written message templates can be sent to them.

1.1 Settings

After the successful installation of Ozeki Phone System, the only thing that left is to add and configure the e-mail provider. Once the Home screen of Ozeki Phone System is displayed, you will see that the Outside lines section is located on the left-hand side (Figure 4).

outside lines section
Figure 4 - Outside lines section

Select the e-mail Provider Outside line from here with the help of the Install new button. (Figure 5).

email provider outside line
Figure 5 - E-mail Provider Outside line

Then the configuration window of the E-mail provider appears (you can return to this window anytime it is necessary). The ’Connection Name’ displayed on the form will be the identifier name of this Outside line. It will be required later. You may leave it with the original name (EmailService1). (Figure 6).

configuration window of email provider
Figure 6 - Configuration window of the E-mail provider

Firstly, specify the name of the SMTP server. This can be either an internal company server or an SMTP server provided by other providers. By adding the SSL, the port number, which is most commonly used by that type will be set as well. It can also be set to another one, which is more appropriate for us. In case some kind of an authentication is needed regarding the SMTP server then it can be set in the appropriate ComboBox. By selecting No authentication, no password or username have to be provided. This data is specified at Plain Password but it is not sent encryptedly towards the server. On the other hand at Encrypted, the previously mentioned data will be passed in an encrypted way. The username and password will symbolize the data, which is expected from the server. Setting the Default sender address results that the messages where no sender was specified will also have a default address. In case of not setting the Default sender address, the message would not be sent since a message without a sender cannot be sent. Of course if a sender is specified during the message is composed then it will be the sender address.

In case the data is provided, it is necessary to test if it is appropriate or not. This can be done by clicking on the ’Test SMTP Settings’ button. The Popup window will give a feedback about which settings might be inappropriate. In a successful case the settings can be saved by clicking on the ’OK’ button. From now on the E-mail provider is working.

Next, specify the Extension, which will accept the requests that will arrive from the clients. Select the Install new button from the Extensions section, which is located on the right-hand side of the Home screen. (Figure 7).

install new button at extensions section
Figure 7 - Install new button at the Extensions section

The API Extension will be required from the appearing list (Figure 8).

api extension
Figure 8 - API Extension

Select the ’Install’ button. The ’Extension number’, which is located here will be used for the client setting. Every setting can be left by default on this interface, it will work properly with the default settings as well. In order to save click on the ’OK’ button.

In addition a Dial plan rule also has to be installed. To add the Dial plan rule return to the Home screen and select the ’Add Rule button’ in the central (Figure 9).

dial plan add rule button
Figure 9 - Dial plan Add Rule button

Anything can be entered in the Description field, which will remind us to the purpose of the rule. It can be modified later as well. On the Source tab, the devices from which the information is received can be specified. Select the previously set API extension from the combobox, which belongs to the ’Specific extension’. On the Condition tab, the E-mail is specified at the Type field. Then by clicking on the Destination tab, the device on which the information should be forwarded needs to be provided. In this case, let it be ’Send to outside line EmailService1 – E-mail provider and call dialled number’ (Figure 10).

destination tab
Figure 10 - Destination tab

The rule can be saved by clicking on ’OK’.

Now, only the final step remains. On the Home interface of Ozeki Phone System select the Connections from the upper menu bar and then select the Office users menu item (Figure 11).

upper menu
Figure 11 - Upper menu

On the appearing interface click on the Add user button, which is located on the right. Fill in the form that appears on the General tab. Next, click on the ’OK’ button. This way a new user is created. Later the login to the Ozeki Phone System E-mail Sender will happen with the data that was provided here.

Now everything is set on the Server side. Continue with the Client side. After installing and starting the Ozeki Phone System E-mail Sender, a login window appears. Provide the Server address in this window. In case the server address is unknown then the easiest way to find it out is to open the Home screen of Ozeki Phone System. Then the part located before the colon of the browser track will be the Server Address. Next, provide the data of the previously created user and click on the Login button. It is practical to have the data remembered by checking the ’Remember me’ checkbox. Please note that the login is successful only when every data is appropriate and Ozeki Phone System is running in the background as well.

After the successful login, click on the Settings menu item.Specify the value of the previously created API Extension ’Extension number’ in the ’Extension ID’ field and then click on the ’Save’ button.After that click on the ’Open’ icon, browse the folder of the application and select the TestEntries.csv document. Thus a line appears in which the e-mail address can be provided where the message has to be sent with the Subject and the Content included in the line. After this is done, click on the ’Start’ icon. Next, the result can be seen in the State column. For more information select the log menu of the E-mail provider, which was set in Ozeki Phone System. Here, it can also be seen that in case a message could not be sent, the E-mail Service tries to forward that message after a couple of minutes.

Select the ’Save’ command and save it to an appropriate place. Then this document can be edited with a spreadsheet or a text editor. New lines can be added to it but be aware of preserving the data structure, the optional commas and line breaks. The best way to edit is by using a spreadsheet.

1.2 Model

1.2.1 About configuration classes

The EmailConfig class is developedwith configuration purposes. It serves to store, save in a standard way and load certain settings given by a user. It is inherited from the class BaseModel and it implements the ICloneable and the IDataErrorInfo interfaces. As a result, the Raise method (inherited from the BaseModel) can be called on every property of this class, making the communication with the GUI simpler. The writing of the Clone() method is important because the settings have to be saved if they are valid and the user saves it. Data display on the user interface can be implemented with data binding. If the interface is modified, it would appear in the Model layer as well, although it is not practical. The data can only be saved to the Model layer after validation. When the data is displayed, the data classes are not specified directly but a cloned copy. If any modification is made, it will be executed on the cloned copy, not the original class. When it is about saving, check the validity of this copy. If it is valid, overwrite the configuration files handled by SettingsRepository.

The data can be validated by the properties of the IDataErrorInfo interface.

1.2.2 EmailConfig

By setting the ConcurrentWorks property, the number of the executable simultaneous tasks can be defined. This is where the ExtensionId property is located. The purpose of this property is that it will determine the extension of Ozeki Phone System, which will be used for communicating with the application. Furthermore, the default SenderEmailAddress is also located here. In case it is set then the e-mails will be sent by that sender address. In case nothing is set then on the server, the default Sender address, which was set in the E-mail service, will be the sender. In case nothing was set there either then the e-mail will not be sent.

In this class, the Item and Error properties can be seen, which is provided by the IDataErrorInfo interface. These are responsible for letting users to save only valid status. Such a status examination is e.g. the condition, which refers to the "ExtensionId". According to this condition, the value of the property can only be a series containing empty characters, otherwise the "Extension ID cannot be empty" text will be passed to the LoginWindow. The ConcurrentWorks property works in a similar way, by looking at its code it can be seen that 1 is the minimum value for this property.

The IsValid property of the class is made up from the above things.

1.2.3 EmailEntry

This class is for storing and handling tasks that are form the BaseModel. This way, the class inherits the methods and events of BaseModel. Later this class will be referred to as task class. This class will be passed as a T generic parameter. Observe how simply the Raise method can be used defined in the BaseModel:

[ReadOnlyProperty]
[ExportIgnoreProperty]
Public WorkState State
{
get { return state; }
set { state = value; Raise(() => State); }
}

[InvisibleProperty]
[ExportIgnoreProperty]
Public bool IsCompleted
{
get { return isCompleted; }
set { isCompleted = value; Raise(() => IsCompleted); }
}
	

As it was mentioned in the parent class, the Raise method is responsible for make the modifications of the properties appear on the GUI.

Here, the RecipientAddress, EmailSubject, EmailContent properties, just like their names say, store information about the address of the recipient and about the subject and content of the e-mail. The State property indicates the status of the task, in the beginning it has an Init value. The value will be Routed in case Ozeki Phone System forwarded it to the appropriate Extension. If it was unsuccessful then the value will be RoutingFailed. If the sending was successful via the Email Service, which was set in Ozeki Phone System then the Success status will appear, otherwise the DeliveringFailed status can be seen. If the e-mail sending is successful then the setting of the IsCompleted property happens as well. The value will be true. From now on, the DataGridRow belonging to the given instance cannot be modified in a way that the actual sending data could be seen. The Properties required for the validation (like Item, Isvalid and Error) can also be found here. It is practical to place the ExportIgnoreProperty and the InvisibleProperty attributes on them.

It is worth observing the usage of the Attributes placed on the properties and also how the class implements the ICompletedWork interface.

1.2.4 EmailWorker

The executable task is getting implemented in this class. It will be generated by the EmailWorkerFactory. As a parameter, it receives a task class and the IAPIExtension, which was set by the user. The setting of the IAPIExtension is only a one time creation of an API Extension. Specify its ID here in the Client, in the SettingsWindow to be exact.

The concrete task, which has to be executed should be provided in the StartWork()method. In case this task was successfully executed previously just skip it. On the other hand if the State status of the task is not Success then continue as follows:

By using the information, which is stored in the task class (EmailEntry) an EmailMessage is created that can be sent with the help of the received apiExtension:

var message = new EmailMessage(emailEntry.RecipientAddress, emailEntry.EmailSubject,
emailEntry.EmailContent, settingsRepository.GetSettings().SenderEmailAddress);
messageId = message.MessageId;

apiExtension.SendMessageAsync(message, result =>
{
switch (result.RoutingState)
{
case RoutingState.DestinationAccepted:
   if (emailEntry.State == WorkState.InProgress)
emailEntry.State = WorkState.Routed;
break;
case RoutingState.DestinationNotFound:
OnWorkCompleted(WorkState.DeliveringFailed);
apiExtension.MessageSubmitted -= apiExtension_MessageSubmitted;
break;
}
});
	

As it can be seen theSendMessageAsyncmethod is waiting for an Action<RoutingResult> parameter. This parameter will be the switch block as you can see it above. After the message forwarding had run on the server side then the Action will run. If it was successful, change the state of the task to Routed and in case it was unsuccessful then change it to DestinationNotFound. Furthermore, in the second case, the OnWorkCompleted eventhandler is invited as well.

In case the message was successfully forwarded then the E-mail Service will receive it for processing. As it can be seen, subscription happened to the apiExtension_MessageSubmitted event. In case of successful or unsuccessful sending, a feedback is received about the execution of the task. After that the WorkCompleted event will be fired and from it the subscribed objects will be notified.

1.2.5 EmailWorkerFactory

This class is responsible for producing the EmailWorker. The actual IAPIExtension will be set in the BroadcastViewModel and then the EmailWorkerFactory is invited by the Scheduler. This is when the EmailWorker –s are generated for completing their tasks.

1.3 View

1.3.1 SettingsUC

The SettingsViewModel is set as the Datacontext of this UserControl so the properties and commands of SettingsViewModel ViewModel can be accessed from here too. The SaveCommand and CancelCommandcommands are bound to Save and Cancel buttons. Their description is available at SettingsViewModel class. The GeneralSettingsUC was referred to this UserControl on a tab. This UserControl will be added later to ContentControl of SettingsWindow window.

1.3.2 GeneralSettingsUC

This UserControl is responsible for displaying and managing the own data, which is possessed by the EmailConfig class. The elements have been bounded to the EmailConfig property, which is located in the SettingsViewModel. More information can be read about their tasks at the class descriptions.

1.4 ViewModel

1.4.1 EmailViewModel

The main window gets this ViewModel indirectly as a DataContext. In the signature you can see that the concrete EmailEntry task class is given here:

public class EmailViewModel : BroadcastMainViewModel < EmailEntry >

The BroadcastMainWindow and BroadcastMainViewModel will work with this EmailEntry task class further on as a generic T type. In its constructor it gets its own settingsRepository. In this way the maximum number of tasks can be passed to the BroadcastMainViewModel that can be performed simultaneously. In this class the body of the GetSettingsViewModel() and GetMaxConcurrentWorkers() abstract method is defined as well that derive from BroadcastMainViewModel.

1.4.2 SettingsViewModel

This ViewModel will be passed in the GetSettingsViewModel() of BroadcastMainViewModel method.

This way the BroadcastMainViewModel can access and use this class and the user’s settings. The settingsRepository requested and the GetSettings()method is called. In this method our EmailConfig property is instantiated. If settingsRepository. GetSettings() method will not be null value, then we set the clone copy of the received settings of the EmailConfig property.

var config = settingsRepository.GetSettings();
if (config != null)
EmailConfig = config.Clone() as EmailConfig;
	

In the description of the configuration classes you can read why cloning is needed. Two RelayCommand can also be found in our class which is used for saving or reject saving. The SaveCommand can be executed only if the configured settings that were made are still valid.

1.5 App.xaml

This class is a bit outside of the three layers defined by the MVVM but it is important to tell a few words about it. Since this is the entry point of the application, the general settings concerning the whole application should be given here. Firstly a SingletonApp with "OPSEmailSender" parameter is created. The importance of the class can be read in the description about that class. Thereafter the necessary classes and interfaces will be registered in the InitDependencies() method. These classes and interfaces can be reached from any point of the program and it is guaranteed that they work as singleton. It is important that all classes, which need resources, are covered with the help of an interface. Pass these interfaces and classes in InitDependencies() method but they can be changed Mock classes anytime if needed. For example simulate a connection with a database or with a server during the tests.

Notice that concrete EmailEntry task class is passed as generic parameter in many cases.

SimpleIoc.Default.Register>(()
=> new CsvImporter());

SimpleIoc.Default.Register>(() 
=> new GenericSettingsRepository());	
	

After the registration is completed in the Inversion of Control (IoC) container, let’s look over the OnStartup (StartupEventArgs e) method. Here call asingletonApp.OnStartup(e) method, with which it can be achieve that the application can run in one instance only. If you try to do further application starts, the started application will be closed. Read more about it in the SingletonApp section.

The application can start after the LoginViewModel class has completed the login in Ozeki Phone System and it has given the following command to the message handling system:

Messenger.Default.Send(new NotificationMessage (Messages.NavigateToMainWindow));  
	

Instantiate a BroadcastMainWindow in MessageReceived method and start it. You should not forget that DialerEntry will be the generic parameter of BroadcastMainWindow class that is passed in the signature of AutoDialerViewModel.

Read the following code in app.xaml class:

<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModel:SettingsViewModel}">
<views:SettingsUC/>
</DataTemplate>
<Style x:Key="WindowIconStyle" TargetType="Window">
<Setter Property="Icon" 
Value="View\Resources\Broadcast_autodialer.ico"/>"/>
</Style>
...
</ResourceDictionary>
</Application.Resources>
	

Here provide the DataTemplate which will be used by SettingsWindow to display the SettingsUC UserControl. Wherever we use SettingsViewModel class is used, its DataTemplate will always be the configured SettingsUC since the Application.Resources defined in app.xaml class can be reached from any xaml class. That it why the icons used by the application and some resources are given here.



Download Installer    Download Source Code



More information