SHOEISHA iD

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

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

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

Windows Azure上で「Secure Mail 2.0J」を使ってみよう
~最新の環境で日本語メールを送信する~

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

 昨年3月、『日本語メールの送信で起こりうる予期せぬクレーム~.NET Framework標準機能と市販コンポーネント「Secure Mail」を徹底比較~』という記事にて、日本語メールを送信する場合に文字化けなどの予期せぬクレームを避けるために、グレープシティの「Secure Mail 2.0J」を使用するのが得策だと紹介しました。今回は、ASP.NET MVC 3アプリやWindows Azureアプリで、Secure Mailが使えるかどうか確認します。

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

はじめに

 昨年の記事では、Windowsフォームアプリを使って.NET Framework標準機能とSecure Mailを比較して日本語の扱いがどのように違うかを検証しました。

 今回、日本語メールを送信するために必要不可欠なコンポーネント「Secure Mail」が、ASP.NET MVC 3アプリやWindows Azureアプリで使えるかどうかを確認してみたいと思います。なぜこのような検証を行うかというと、動作保証環境にASP.NET MVC 3アプリが動作するのに必要な.NET Framework 4.0や、Windows AzureのOSであるWindows Server 2008 英語版/Windows Server 2008 R2 英語版が含まれていないためです。

現状の動作保障環境

開発ツール
  • Visual Studio .NET 2003 日本語版
  • Visual Studio 2005/2008 日本語版
フレームワーク
  • .NET Framework 1.1 SP1/2.0/3.0/3.5
OS
  • Windows 2000/XP/Vista 日本語版
  • Windows Server 2003/2008 日本語版

 この記事では、メーカーの代わりに動作保証を行うことを目的とはしていません。しかし、Secure Mailは多く環境で利用されているコンポーネントですので、最新の環境で日本語メールを送信する場合などの参考になればと思い、検証を進めていきます。

ASP.NET MVC 3アプリに適用

 ASP.NET MVC 3は、Webの世界でメジャーなMVCスタイルでの開発をASP.NETで行うためのフレームワークです(参考:『ASP.NET MVC3入門』)。ASP.NET MVC 3アプリの開発にはVisual Studio 2010が必要で、Visual Studio 2010もSecure Mail 2.0Jの動作保証環境ではありません。

プロジェクトの作成

 Visual Studio 2010を起動し、新規プロジェクトの作成で[ASP.NET MVC 3 Webアプリケーション]を選択します。

図1 新規プロジェクトを作成
図1 新規プロジェクトを作成

 最終的にインターネット上のホスティングサービスに配置して動作チェックをするため、テンプレートは[インターネットアプリケーション]を選択します。

図2 テンプレートの選択
図2 テンプレートの選択

Secure Mail 2.0Jを使う前準備

 Visual StudioのプロジェクトでSecure Mail 2.0Jを使うには、Secure Mailのコンポーネントの参照設定が必要です。

  1. ソリューションエクスプローラでプロジェクトを右クリックして[参照の追加]メニューを選択
  2. Dart.PowerTCP.SecureMail.dllを参照に設定
  3. ソリューションエクスプローラでプロジェクトを右クリックして[追加]-[新しい項目]メニューを選択
  4. テキストファイルとして「licenses.licx」を追加
リスト1 licenses.licxの内容
Dart.PowerTCP.SecureMail.Smtp, Dart.PowerTCP.SecureMail
Dart.PowerTCP.SecureMail.MessageStream, Dart.PowerTCP.SecureMail

モデルの追加

 今回のサンプルでは、/Home/Index/のView(Webページ)にメール送信用のページを作成します。このViewで使用するロジックは、ModelsフォルダにHomeModelsモデルを作成して記述するのがMVCスタイルです。そのため、Secure Mailを使用するコードはHomeModelsモデルの中に記述することになります。

図3 プロジェクト構造
図3 プロジェクト構造
リスト2 モデルの記述例
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations

Public Class SendMailModel
    <Required(ErrorMessage:="SMTPサーバは必須です。")>
    <Display(Name:="SMTPサーバ")>
    Public Property SmtpServer As String
    <Required(ErrorMessage:="ポート番号は必須です。")>
    <Display(Name:="ポート番号")>
    Public Property SmtpPort As Integer
    <Required(ErrorMessage:="UserIDは必須です。")>
    <Display(Name:="UserID")>
    Public Property UserID As String
    <Required(ErrorMessage:="パスワードは必須です。")>
    <DataType(DataType.Password)>
    <Display(Name:="パスワード")>
    Public Property Password As String
    <Required(ErrorMessage:="メールアドレスは必須です。")>
    <DataType(DataType.EmailAddress)>
    <Display(Name:="メールアドレス")>
    Public Property MailAddress As String
    <Required(ErrorMessage:="送信先メールアドレスは必須です。")>
    <DataType(DataType.EmailAddress)>
    <Display(Name:="送信先メールアドレス")>
    Public Property ToAddress As String
    <Required(ErrorMessage:="件名は必須です。")>
    <Display(Name:="件名")>
    Public Property Subject As String
    <Required(ErrorMessage:="本文は必須です。")>
    <DataType(DataType.MultilineText)>
    <Display(Name:="本文")>
    Public Property Body As String
End Class

Public Class SendMailService
    Public Function SendMail(smtpServer As String,
                             smtpPort As Integer,
                             userID As String,
                             password As String,
                             mailAddress As String,
                             toAddress As String,
                             subject As String,
                             body As String,
                             result As String) As Boolean
        Dim isOK As Boolean = False

        Try
            Using _smtp As New Dart.PowerTCP.SecureMail.Smtp
                _smtp.Username = userID
                _smtp.Password = password
                _smtp.Server = smtpServer
                _smtp.ServerPort = smtpPort
                Using _msg As New Dart.PowerTCP.SecureMail.MessageStream
                    _msg.From = New Dart.PowerTCP.SecureMail.MailAddress(mailAddress)
                    _msg.To.Add(New Dart.PowerTCP.SecureMail.MailAddress(toAddress))
                    _msg.Charset = "ISO-2022-JP"
                    _msg.ContentType = "text/plain"
                    _msg.Header.Add(HeaderLabelType.ContentTransferEncoding, "7bit")
                    _msg.Subject = subject
                    _msg.Text = body
                    _smtp.Send(_msg)
                    isOK = True
                End Using
            End Using
        Catch ex As Exception
            result = ex.Message
        End Try
        Return isOK
    End Function
End Class
  1. SendMailModelクラス:SendMailModelクラスには、メール送信ページで使う項目をプロパティとして定義します。Required属性で未入力時のエラーメッセージを指定し、Display属性で項目名を定義します。この定義はView側で参照できます。
  2. SendMailServiceクラス:SendMailServiceクラスはメール送信用のクラスです。このクラスの中でSecure Mailを使用しています。SmtpオブジェクトにSMTPサーバーとの接続に必要な情報を設定し、MessageStreamオブジェクトにメールのヘッダ情報と本文を設定して、SmtpオブジェクトのSendメソッドでメール送信します。

Viewデザイン

 ロジック部分が完成したら、コントローラへモデルに記述したロジックを呼び出すコードを記入します。Index関数が2つあるのは、パラメタなしが対応するViewを呼び出したときに実行される関数と、HttpPost属性がついたパラメタありが対応するViewからSubmitされたときに実行される関数の2種類を用意する必要があるためです。

リスト3 コントローラの記述例
Public Class HomeController
    Inherits System.Web.Mvc.Controller

    Public Property SendMailService As New SendMailService

    Function Index() As ActionResult
        ViewData("Message") = "ASP.NET MVC へようこそ"

        Return View()
    End Function

    <HttpPost()> _
    Function Index(ByVal model As SendMailModel) As ActionResult
        If ModelState.IsValid Then
            Dim result As String = ""
            If SendMailService.SendMail(model.SmtpServer,
                                        model.SmtpPort,
                                        model.UserID,
                                        model.Password,
                                        model.MailAddress,
                                        model.ToAddress,
                                        model.Subject,
                                        model.Body,
                                        result) Then
                Return RedirectToAction("Thanks", "Home")
            Else
                ModelState.AddModelError("", result)
            End If
        End If
        Return View(model)
    End Function

    Function Thanks() As ActionResult
        Return View()
    End Function
End Class
  1. Index関数では画面入力をパラメタとして引き取ります。パラメタの形式は、対応するモデルになります。
  2. ModelStateのIsValidプロパティがFalseならば「入力値に違反がある」ということなので、すぐにReturn View(model)に制御が移ります。
  3. SendMailService.SendMailメソッドがTrue(メール送信成功)であれば、/Home/Thanks/ページに遷移します。

ビューの作成

 [Views]-[Home]フォルダにあるIndex.vbhtmlファイルを開いて、SendMailModelクラスで定義された項目をHTMLの中に埋め込んでいきます。

リスト4 ビューの記述例
@ModelType CZ1106Mvc3.SendMailModel
  
@Code
    ViewData("Title") = "ホーム ページ"
End Code

<h2>@ViewData("Message")</h2>
@Using Html.BeginForm()
    @Html.ValidationSummary(True, "メール送信に失敗しました。エラーを修正し、再試行してください。")
    @<div>
        <fieldset>
            <legend>メール送信</legend>
            <div class="editor-label">
                @Html.LabelFor(Function(m) m.SmtpServer)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(Function(m) m.SmtpServer)
                @Html.ValidationMessageFor(Function(m) m.SmtpServer)
            </div>
                :
                (中略)
                :
            <p>
                <input type="submit" value="送信" />
            </p>
        </fieldset>
    </div>
End Using

 今回のViewはビューエンジンに「ASPX」ではなく「Razor」を採用しているため、HTMLにかなり近い記法になっています。

 Razorらしい記述の1つとして、HTMLヘルパーによるレンダリングがあります。@Html.LabelFor、@Html.TextBoxFor、@Html.ValidationMessageForはすべて「Function(m) m.SmtpServer」というラムダ式をパラメタとして指定していますが、この3つのレンダリング結果はそれぞれ異なります。

  • @Html.LabelFor:LabelForはSmtpServerプロパティのDisplay属性の設定値を表示するHTMLヘルパーなのでレンダリング結果はDisplay属性に指定されている「SMTPサーバ」になります。
  • @Html.TextBoxFor:TextBoxForはSmtpServerプロパティの値をINPUTタブとして表示入力するHTMLヘルパーになります。
  • @Html.ValidationMessageFor:ValidationMessageForはSmtpServerプロパティのRequired属性などのValidation関連の設定値を該当するValidationが発生したときに表示するためのHTMLヘルパーになります。

開発環境での実行

 Model-View-Controlのコードが書けたら、IDE上で実行してみましょう。

図4 実行画面
図4 実行画面

 画面が表示されたら、必要な情報を入力して[送信]ボタンをクリックします。正しく送信できたら「Thanks」ページが表示されます。

 実際にメールクライアントで受信して、日本語表示用の変換を行う前(受信したまま)の状態を表示してみます(例えば、Becky!であれば[表示]-[ソースの表示]にて表示できます)。

リスト5 サンプルからのメール
From: hatsune@wankuma.com
To: hatsune@wankuma.com
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
Subject: =?iso-2022-jp?B?GyRCRnxLXDhsJE43b0w+JHI9aE19JDkkaxsoQnRlc3QbJEJNUTdvTD4bKEI=?=
Date: Wed, 15 Jun 2011 20:25:45 +0900
MIME-Version: 1.0
Message-Id: <20110615110101.A2C4DFA402B@mail.wankuma.com>
X-UIDL: aLG"!lDM"!c\/!!B-l"!

$BF|K\8lK\J8(B

 昨年の記事のWindowsフォームアプリの時と同様に、「MIME形式でISO-2022-JPで7bitエンコードされたメール」として送信されていることが分かります。もちろん、普通の表示方式で表示すれば、タイトルも本文もきちんと表示されます。

図5 受信したメール
図5 受信したメール

実環境に配置するときの注意点

 ホスティングサービスなどで提供される環境には、Secure Mailはインストールされていません。しかし、Secure Mailを参照設定した場合は、自動的に[ローカルコピー]プロパティが「True」となっているため、Webの発行を行って配置すれば実行に必要なSecure MailのDLLがコピーされます。

 ホスティングサービスによってはVisual Studioからの直接発行には対応していないところもありますが、そのような場合でもファイルシステムなどに発行して、そこからFTP転送などをすればよいでしょう。

Windows Azureアプリに適用

 ASP.NET MVC 3アプリからSecure Mailが使えるのであれば、ASP.NET MVC 3アプリをWindows Azure上で動かした場合もSecure Mailが使えるかもしれないと考えました。現在、Windows AzureとしてSMTPサーバ機能は提供されていないため、Windows Azureアプリからメールを送信する時は、外部のSMTPサーバに接続してメール送信を行います。

 Windows AzureにももちろんSecure Mailはインストールされていませんが、ASP.NET MVC 3をホスティングサービスへ発行する場合と同様に、DLLのローカルコピープロパティを「True」にしておけば、Windows Azureアプリとして作成してWindows Azureに配置した場合もSecure Mailの動作に必要なDLLがコピーされます。

Windows Azureアプリを作成

 Windows Azureアプリを作成するには次の手順を踏みます。

  1. Visual Studio 2010を管理者として実行
  2. 新規プロジェクトの作成から[Windows Azureプロジェクト]を選択

    図6 プロジェクトテンプレートの選択
    図6 プロジェクトテンプレートの選択
  3. ロールはどのロールも選択しない
  4. ソリューションエクスプローラでソリューション名を右クリックして[追加]-[既存のプロジェクト]メニューを使って、既存のASP.NET Webアプリのプロジェクトを追加
  5. Windows Azureプロジェクト側で「ソリューションWebロールプロジェクト」の追加を実施

    図7 WebRoleの追加
    図7 WebRoleの追加
  6. ASP.NET MVC 3の動作に必要なDLLは残念ながらまだWindows Azureにはインストールされていないため、Secure Mailと同様に必要なDLLの参照設定の[ローカルコピー]プロパティを「True」にしてします。どの参照設定の変更が必要かは『ASP.NET MVC 3をAzureで動かす』を参考にしてください。

    図8 Windows Azureアプリのソリューション構成
    図8 Windows Azureアプリのソリューション構成

 この手順によりASP.NET MVC 3アプリとして稼働していたサンプルをWindows Azure上で動作させるためのWindows Azureアプリが完成します。

Windows Azureに配置

 Windows AzureアプリのVisual Studioでの一通りの動作確認が完了したら、ソリューションエクスプローラのWindows Azureプロジェクトを右クリックして[配置]メニューを選択します。

図9 Windows Azure プロジェクトの配置
図9 Windows Azure プロジェクトの配置

 必要な情報を入れて[OK]ボタンをクリックすればWindows Azureにプログラムの配置が行われます。

図10 Windows Azure Portalでの確認
図10 Windows Azure Portalでの確認

Windows Azure環境での動作確認

 Windows Azure Portalに表示されているDNS nameのURLをクリックすればWindows Azure上で稼働するWebアプリに接続します。

 ここで各種情報をいれて[送信]ボタンをクリックすれば文字化けなく受信できるメールが送信されます。

図11 Windows Azure環境での動作確認
図11 Windows Azure環境での動作確認
リスト6 サンプルからのメール
From: hatsune@wankuma.com
To: hatsune@wankuma.com
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit
Subject: =?iso-2022-jp?B?GyRCJDMkbCRPGyhCdGVzdBskQiRHJDkhIxsoQg==?=
Date: Tue, 14 Jun 2011 13:57:38 +00
MIME-Version: 1.0
Status:  U
X-UIDL: 1308059860.25181.mbox401-3

$B$3$l$O(Btest$B$NK\J8$G$9!#(B
図12 受信したメール
図12 受信したメール

おわりに

 ASP.NET MVC 3アプリからWindows Azureアプリを作成してSecure Mailですんなりメールが送信できたのには理由があります。それは次の3行の存在です。

_msg.Charset = "ISO-2022-JP"
_msg.ContentType = "text/plain"
_msg.Header.Add(Dart.PowerTCP.SecureMail.HeaderLabelType.ContentTransferEncoding, "7bit")

 Windows Azureは英語環境なので、明示的に日本語を指定しないと「Content-Type: text/plain; charset="iso-8859-1"」となってしまい、メール本文が文字化けを起こします。Windows Azureを使うときの鉄則である「省略値は日本語指定とは限らないので、明示的に日本語を指定できるときは指定する」はここでも当てはまっていると言えるでしょう。

製品情報

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

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

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

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6003 2011/06/23 14:00

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング