SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(Secure iNetSuite)

Secure iNetSuite for .NET 4.0Jを最新環境で使ってみる

Windows 8.1+Visual Studio 2013+Secure Mail for.NET 4.0Jの組み合わせを確認

  • このエントリーをはてなブックマークに追加

 私が好きなグレープシティ社のコンポーネントはいくつかありますが、その中の一つがSecure iNetSuiteのSecure Mailです。Secure Mailの特徴は、なんといっても日本のメール事情に精通したグレープシティ社がきちんと検証を行ってくれているため、メールの文字化けとは無縁の世界でアプリ構築ができるという点でしょう。

  • このエントリーをはてなブックマークに追加

 VB5/6用のiNetMail 1.0J、そして.NET対応初版のSecure Mail 2.0J、どちらもその当時に担当していたコンシューマーからのメールを受信してシステムに取り込むという要件がある開発プロジェクトで採用しました。やはり、肌感覚として文字化けなどの問題が生じない安心感は、自信をもってリリース日を迎えることができた根拠の一つになっていました。

 最新版のSecure iNetSuite 4.0JはWindows 8やVisual Studio 2012に対応していますが、2013/10/17から提供が開始されたVisual Studio 2013や発売が開始されたWindows 8.1については現時点ではまだ対応予定の状態です(注1)。そこで、あえて最新のWindows 8.1とVisual Studio 2013でSecure iNetSuite 4.0Jを構成するコンポーネントの一つであるSecure Mail 4.0Jを使ってみて、実際のところどうなのかを確認してみたいと思います。また、今回はデスクトップアプリとしてサンプルを作成しましたが、MVCデザインパターンでの適用がしやすい非同期モード実装に変わったとのことなので、このあたりも意識してサンプルを作成しています。

注1

 2013/11/7にリリースされたService Pack 1で対応されました。

Windowsフォームアプリへの適用例

(※サンプルファイルの「CZ1310Win」に対応)

 まずは一番オーソドックスなWindowsフォームアプリにSecure iNetSuite 4.0Jを適用してみましょう。とはいっても、Windowsフォーム画面にSecure Mail 4.0Jのsmtpコンポーネントやpopコンポーネントをドラッグ&ドロップで配置してプロパティを設定し、イベントプロシージャの中でメソッドを呼び出すのでは、少々オーソドックスすぎます。

 そこで、popコンポーネントを使ってメール一覧を作成するModel部と、WindowsフォームのView部を別クラスになるような構成をとってみましょう。

プロジェクトの構成

 Visual Studio 2013を起動して[ファイル]-[新しいプロジェクト]から[Visual Basic]-[Windows]-[Windowsフォームアプリケーション]を選択してWindowsフォームアプリの新規プロジェクトを作成します。

 新規プロジェクトが作成できたら、以下の操作を行い、プロジェクトの初期状態を定義します。

  1. 「Views」「ViewModels」「Models」の3つのフォルダを作成
  2. Form1.vbファイルをMainForm.vbファイルにリネームしてからViewsフォルダに移動
  3. ViewModelsフォルダにMainViewModelクラスを作成
  4. ModelsフォルダにMailModelクラスを作成

 なお、今回のサンプルは、MailModelクラスにpopコンポーネントを使ったメール受信のコードを作成し、MainForm.vbファイルには画面定義を記述します。そしてこの2つの橋渡し用のコードを、MainViewModelに記述するという構成になっています。

Secure Mailの参照追加

 Secure Mailコンポーネントを利用するためには、参照設定が必要です。

 ソリューションエクスプローラーでプロジェクト名を右クリックして[追加]-[参照]メニューから[参照マネージャー]ダイアログを表示します。次に、[アセンブリ]-[拡張]から「PowerTCP Mail for.NET」を選択して、参照の追加を行います。

図1 参照の追加
図1 参照の追加

ライセンスファイルの追加

 グレープシティ社のコンポーネント製品に共通しているのは、開発環境でコンポーネントを使う場合、コンポーネント製品をインストールしてあることに加えて、プロジェクトにライセンスファイルを記述しておく必要がある点です。

 ソリューションエクスプローラーでプロジェクト名を右クリックして[追加]-[新しい項目]メニューから[新しい項目の追加]ダイアログを表示します。続いて、[全般]から「テキストファイル」を選択して「licenses.licx」という名前でライセンスファイルをプロジェクトに追加してください。

図2 ライセンスファイルの追加
図2 ライセンスファイルの追加

 ライセンスファイルには試用するコンポーネント名を記載しますので、今回は次のような内容になります。

リスト1 licenses.licx
Dart.Mail.Pop, Dart.Mail
Dart.Mail.MailMessage, Dart.Mail

 余談ですが、参照設定やライセンスファイルの追加は、popコンポーネントをツールボックスからWindowsフォームエディタ上にドラッグ&ドロップして配置すると自動的に行われるため、今回のような手間はありません。ドラッグ&ドロップ方式の方が圧倒的に手軽ではありますが、今回はWindowsフォーム上には見た目の定義以外は極力排除するためにこのような手順をとっています。

画面に表示する情報の定義

 コンポーネントを使う準備ができたならば、画面に表示したい情報や画面での操作に関する処理をMainViewModelクラスに記述します。

 MainViewModelクラスに記述するコードは実際にはもう少し必要ですが、重要な部分だけを抜き出すと次のようになります。

リスト2 MainViewModel
Imports System.Collections.ObjectModel
Imports System.Runtime.CompilerServices
Imports System.ComponentModel

Public Class MainViewModel
    Implements INotifyPropertyChanged
    Private WithEvents Model As New MailModel

    Public Property Items As ObservableCollection(Of MailModel.TMail)
        Get
            Return Me.Model.Items
        End Get
        Set(value As ObservableCollection(Of MailModel.TMail))
            Me.Model.Items = value
        End Set
    End Property

    Public Async Function GetMail() As Task
        Await Me.Model.GetMail()
    End Function

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
        Implements INotifyPropertyChanged.PropertyChanged
End Class

 受信メール一覧はItemsプロパティに設定され、一覧を作るためのメソッドがGetMailメソッドとして定義されています。この時点では、まだMailModelクラスの中身は記述していないため、例えば「Me.Model.GetMail()」などと入力するとIDEの即時チェックでコンパイルエラーです。しかし、エラー修正のオプションで「MailModelにGetMailのメソッドスタブを生成」を選択すると、MailModelクラスにPublicメソッドの入り口だけ定義され、コンパイルエラーが解消できます。

画面の定義

 今回のサンプルでは、非常にシンプルな画面構成を採用しています。

図3 画面定義
図3 画面定義

 [一覧受信]をクリックしたら、受信メールの一覧をボタン下のListBoxに表示します。

画面のコードビハインド定義

 画面定義が終わったら、次に画面定義に紐づいたコードを記述します。

 ソリューションエクスプローラーで「MainForm.vb」を右クリックして[コード]メニューを選択すると、MainFormと関連づいたコード(コードビハインド)を記述するためのコードエディタが開きます。

リスト3 MainForm.vbのコード
Public Class MainForm
    Private WithEvents ViewModel As New MainViewModel

    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles Me.Load
        Me.ListBox1.DrawMode = DrawMode.OwnerDrawVariable
    End Sub

    Private Async Sub Get_Button_Click(sender As Object, e As EventArgs) _
        Handles Get_Button.Click
        Await Me.ViewModel.GetMail()
        Me.ListBox1.DataSource = Me.ViewModel.Items.ToList
    End Sub
                 :
               (中略)
                :

End Class

 Get_Button_Clickイベントプロシージャでは、MainViewModelクラスのGetMailメソッドを非同期待ち合わせで呼び出しています。この非同期待ち合わせ(Await)は、Visual Studio 2012(.NET Framework 4.5)から採用されたもので、UIスレッドへ制御を戻しつつ、GetMailメソッドの実行が完了するまで待ち合わせる動きが可能になります。つまり、Windowsフォームアプリでありがちな、長時間処理実行中にWindowsフォームが真っ白になったり、「応答待ち」表示になったりすることを防止できます。

メール受信ロジックの記述

 最後に、popコンポーネントを使ったメール受信一覧の取得ロジックを記述しましょう。

リスト4 MailModel
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Imports System.Runtime.CompilerServices
Imports System.Threading

Public Class MailModel
    Implements INotifyPropertyChanged

    Public Class TMail
        Public Property From As String
        Public Property Subject As String
        Public Property SendDate As DateTime
    End Class

    Public Property Items As New ObservableCollection(Of TMail)

    Public Property Pop3Server As String = "popServer"
    Public Property UserId As String = "UserID"
    Public Property Password As String = "Password"

    Public Async Function GetMail() As Task
        Using pop As New Dart.Mail.Pop
            AddHandler pop.Progress, AddressOf PopProgress

            pop.Session.RemoteEndPoint = New Dart.Mail.IPEndPoint(Me.Pop3Server, 110)
            pop.Session.Username = Me.UserId
            pop.Session.Password = Me.Password
            pop.Connect()
            pop.Authenticate(True, True)
            ''ヘッダを取得します
            Await Task.Run(Sub()
                               Try
                                   For Each mes In pop.Messages
                                       mes.Get(0)
                                   Next

                               Catch ex As Exception
                                   Debug.Assert(ex.Message)
                               End Try
                           End Sub)
            pop.Close()
            RemoveHandler pop.Progress, AddressOf PopProgress
        End Using
    End Function

    Private Sub PopProgress(sender As Object, e As Dart.Mail.PopProgressEventArgs)
        If e.Final Then
            Me.Items.Add(New TMail With {
                             .From = e.Message.Message.From,
                             .Subject = e.Message.Message.Subject,
                             .SendDate = e.Message.Message.Date
                         })
        End If
    End Sub

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
        Implements INotifyPropertyChanged.PropertyChanged
    Private Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub
End Class

 PopServerプロパティ、UserIdプロパティ、Passwordプロパティは使用しているメールサーバーの設定に合わせて値を設定しておいてください。

 このクラスで最重要なのはGetMailメソッドの中の動きなので、メソッドの中を少し詳しく見ていきたいと思います。

pop.Session.RemoteEndPoint = New Dart.Mail.IPEndPoint(Me.Pop3Server, 110)

 POP3サーバーのアドレスとポート番号を指定して、接続先をRemoteEndPointメソッドに設定します。

pop.Session.Username = Me.UserId / pop.Session.Password = Me.Password

 POP3接続用のユーザIDとパスワードを指定します。

pop.Connect()

 POP3サーバーに接続します。

pop.Authenticate(True, True)

 認証を行い、POP3サーバーにログインできたら、pop.Messagesにメールの情報を取得します。

Await Task.Run(Sub()…)

 Task.Runメソッドを使って、その中で指定しているコード(For Eachループ)を非同期実行しています。また、Awaitをつけてその非同期実行を待ち合せしているので、For Eachループがすべて回りきった後に次の行のpop.Close()やRemoveHandlerが実行されます。

 MainForm.vbにあるet_Button_Clickイベントプロシージャは、この非同期待ち合わせが完了すると処理が終わることになります。

For Each… mes.Get(0)…

 Task.Runの中で指定しているのは、pop.Messagesに格納されたメール情報を元に1通ずつ、Get(0)メソッドを実行して本文なし(0指定のため)でヘッダだけを受信しています。この受信のタイミングでProgressイベントが随時発生します。

 PopProgressイベントプロシージャの中では、取得できたヘッダ情報から、From、Subject、DateをMe.Itemsに追加しています。

実行結果の確認

 それでは、実行結果を確認してみましょう。

図4 実行結果の確認
図4 実行結果の確認

 日本語のFromやSubjectの文字化けもなく、一覧が取得できました。

WPFアプリへの適用例

(※サンプルファイルの「CZ1310Wpf」に対応)

 Windowsフォームには、Secure iNetSuiteのコンポーネントをツールボックスからドラッグ&ドロップで設置ができます。そのため、WindowsフォームアプリはSecure iNetSuiteが想定しているアプリ形式だともいえるでしょう。

 そこで次の勝手流動作確認として、Windows 8.1+Visual Studio 2013に加えてWPFアプリ形式でもSecure iNetSuiteを使ってみようと思います。WPFアプリでも、popコンポーネントを使ってメール一覧を作成するModel部とWindowsフォームのView部を別クラスになるような構成で作成します。

プロジェクトの構成

 Visual Studio 2013を起動して[ファイル]-[新しいプロジェクト]から[Visual Basic]-[Windows]-[WPFアプリケーション]を選択してWPFアプリの新規プロジェクトを作成します。

 新規プロジェクトが作成できたら、以下の操作を行い、プロジェクトの初期状態を定義します。

  1. 「Views」「ViewModels」「Models」の3つのフォルダを作成
  2. Window1.xamlファイルをMainWindow.xamlファイルにリネームしてからViewsフォルダに移動
  3. ViewModelsフォルダにMainViewModelクラスを作成
  4. ModelsフォルダにMailModelクラスを作成

 MailModelクラスやMainViewModelクラスの役目やコードは、Windowsフォームアプリのサンプルコードと同じ内容になります。

 Secure Mailの参照追加、ライセンスファイルの追加もWindowsフォームアプリのサンプルと同じ手順で行います。ここまで作業が完了したときのプロジェクト構成は、次のようになります。

図5 プロジェクト構成
図5 プロジェクト構成

画面の定義

 画面の構成も、Windowsフォームアプリのサンプルと同じような感じにしてみましょう。

図6 画面定義
図6 画面定義
リスト5 MainWindow.xaml
<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CZ1310Wpf" Height="270" Width="600">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Button Content="一覧受信" 
                Width="75" Height="23" Grid.Row="0" Margin="5" 
                HorizontalAlignment="Left" 
                Command="{Binding GetMailCommand}"/>
        <ListBox Grid.Row="1" Margin="5" ItemsSource="{Binding Items}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ListBoxItem>
                        <StackPanel>
                            <TextBlock Text="{Binding From}" />
                            <TextBlock Text="{Binding Subject}" />
                        </StackPanel>
                    </ListBoxItem>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>         
    </Grid>
</Window>

 [一覧受信]をクリックしたら、受信メールの一覧をボタン下のListBoxに表示します。

 Windowsフォームのときは、ボタンにClickイベントを指定していました。WPFアプリでも同じようにClickイベントを記述することができます。

 このサンプルは、別バリエーションとしてボタンにはCommandプロパティを設定して、その中でMainViewModelのプロパティを呼び出す方式でボタンがクリックされた時の処理を記述しています。これがXAMLのコマンドバインディングと呼ばれるものです。この方式に変更すると、コードビハインド側にClickイベントに対する処理を記述しなくて済みます。

画面のコードビハインド定義

 画面定義がおわったら、次に画面定義に紐づいたコードを記述します。

 ソリューションエクスプローラーで「MainWindow.xaml.vb」をダブルクリックすると、MainWindow.xamlと関連づいたコード(コードビハインド)を記述するためのコードエディタが開きます。

リスト6 MainWindow.xaml.vbのコード
Class MainWindow
    Private ViewModel As New MainViewModel

    Public Sub New()
        InitializeComponent()
        Me.DataContext = Me.ViewModel
    End Sub
End Class

 WPFアプリでは、XAML側でボタンクリックしたときに呼び出すViewModelのプロパティを指定できるので、コードビハインドに記載が必要なコードはほとんどありません。

MainViewModelへの変更

 Windowsフォームアプリを作成したときのMainViewModelクラスでは、ボタンクリック時にMainWindow.vbから呼び出されていたのはGetMailメソッドでした。XAMLからはICommandインターフェースを持ったプロパティにコマンドバインディングされて呼び出されるので、MainViewModelのGetMailメソッド部分を次のように書き換えます。

リスト7 MainViewModelクラスの書き換え部分
        :
      (中略)
        :
    Public Async Function GetMail() As Task
        Await Me.Model.GetMail()
    End Sub
        :
      (中略)
        :
リスト8 MainViewModelクラスの書き換え後
        :
      (中略)
        :
    Private _GetMailCommand As Common.RelayCommand
    Public Property GetMailCommand() As Common.RelayCommand
        Get
            If _GetMailCommand Is Nothing Then
                _GetMailCommand = New Common.RelayCommand(AddressOf Me.GetMail)
            End If
            Return _GetMailCommand
        End Get
        Set(value As Common.RelayCommand)
            _GetMailCommand = value
        End Set
    End Property

    Private Async Sub GetMail()
        Await Me.Model.GetMail()
    End Sub
        :
      (中略)
        :

 記述量は少し増えてしまうのですが、こうすることでXAML側とViewModelの関係はますます疎にできます。なお、Common.RelayCommandクラスはサンプルコードのCommonフォルダの中に新規作成していますので、詳しい内容はサンプルコードをダウンロードして確認してください。

実行結果の確認

 それでは、実行結果を確認してみましょう。

図7 実行結果の確認
図7 実行結果の確認

 残念ながらMailModelクラスの中で実行時エラーとなってしまいました。原因は、Windowsフォームのときと異なり、MailModelクラスのItemsはMainViewModelを介してMainWindowのListBoxにBindingされている点です。つまり、非同期実行しているmes.Get(0)実行時に発生するProgressイベントの処理の中でMe.Items.Addすると、それはUIスレッドでXAMLが更新することになり、非同期スレッドからUIスレッドというスレッド間の連携が生じてしまうからです。

 そのため、PopProgressイベントプロシージャの中を次のように書き換えることで解決ができます。

リスト9 PopProgressイベントプロシージャの書き換え後
        :
      (中略)
        :
    Private Context As SynchronizationContext = SynchronizationContext.Current
        :
      (中略)
        :
    Private Sub PopProgress(sender As Object, e As Dart.Mail.PopProgressEventArgs)
        If e.Final Then
            Me.Context.Post(Sub(o)
                                Me.Items.Add(New TMail With {
                                                 .From = e.Message.Message.From,
                                                 .Subject = e.Message.Message.Subject,
                                                 .SendDate = e.Message.Message.Date
                                             })
                            End Sub,
                Nothing)
        End If
    End Sub
        :
      (中略)
        :

 それでは再度、実行結果を確認してみましょう。

図8 実行結果の確認
図8 実行結果の確認

 今度は正常に表示できました。もちろん文字化けすることもまったくなく、一覧が作成されています。

Windowsストアアプリへの適用例

(※サンプルファイルの「CZ1310Wrt」に対応)

 WPFアプリでもSecure iNetSuiteが使えたので、試しにWindowsストアアプリでも使ってみましょう。デスクトップアプリであるWindowsフォームアプリやWPFアプリは.NET Framework(今回は.NET Framework 4.5)で動作します。対して、クラスの作りは非常によく似ていますが、WindowsストアアプリはWindows Runtimeという別フレームワーク上で動作します。Windows 8.1+Visual Studio 2013+Windows Runtimeの組み合わせは、Secure iNetSuiteの実行環境としてはまったく想定外の環境だと思われます。

プロジェクトの構成

 Visual Studio 2013を起動して[ファイル]-[新しいプロジェクト]から[Visual Basic]-[Windowsストア]-[新しいアプリケーション]を選択し、Windowsストアアプリの新規プロジェクトを作成します。

 新規プロジェクトが作成できたら、以下の操作を行い、プロジェクトの初期状態を定義します。

  1. 「Views」「ViewModels」「Models」の3つのフォルダを作成
  2. MainPage.xamlファイルをViewsフォルダに移動
  3. ViewModelsフォルダにMainViewModelクラスを作成
  4. ModelsフォルダにMailModelクラスを作成

 MailModelクラスやMainViewModelクラスの役目やコードは、WPFアプリのサンプルコードと同じ内容になります。

図9 プロジェクト構成
図9 プロジェクト構成

Secure Mailの参照追加

 Secure Mailコンポーネントの参照設定を行います。

 ソリューションエクスプローラーでプロジェクト名を右クリックして[追加]-[参照]メニューから[参照マネージャー]ダイアログを表示します。続いて[アセンブリ]の中を探してみますが、「PowerTCP Mail for.NET」は表示されません。サポートしていないことがほぼ確定していますが、[参照…]をクリックして「Dart.Mail.dll」を直接参照してみます。

 すると「.NETCoreではなく.NET Frameworkを対象としている」ため、サポートされていませんと明確に断言されてしまいます。

図10 参照の追加
図10 参照の追加

 残念ながらWindowsストアアプリでは、Secure iNetSuiteを現時点で使用することはできないようです。もちろん似ているとはいえ.NET Frameworkとは別の仕組みなので、使えなくて当然なのです。ちょっと無茶しすぎましたね。

まとめ

 あえてツールボックスからドラッグ&ドロップで配置して使う方法を封印してSecure Mailを使ってみましたが、どのような印象になったでしょうか。ドラッグ&ドロップで作った時との相違点は、基本的には「pop As New Dart.Mail.Pop」と明示的にコンポーネントからオブジェクトを生成するコードのみになります。参照追加やライセンスファイルという手間はありましたが、どちらの方法でも難易度に大差はないと言えるでしょう。

 それよりも、WPFアプリなどWindowsフォームアプリ以外でも使えるということの方が重要だと思います。今回は取り上げませんでしたが、Windowsサービスアプリの中でも使用可能なので、サーバーにWindowsサービスとしてSecure iNetSuiteを使ったアプリを常駐させておき、FTPやメールでの自動連携を実現するようなシステムも構築できます。

 ぜひ、Secure iNetSuiteを使って、安心・安全な日本語メール環境/日本語ファイル転送環境を実現してみてください。

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7460 2016/03/14 11:42

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング