最小限コードによるメール送信
System.Net.MailとSecureMailのどちらも、Sendメソッドにパラメータを指定するだけという最小限のコードでもメールを送信することができます(サンプル「CZ1003Simple」)。まずは、この方法でメールを送信し、その結果を比較したいと思います。
メール送信サンプル画面の作成
メール送信用のサンプル画面として、図2のようなフォーマットのWindowsフォームを作成し、件名や本文に日本語を指定したときの動作を確認してみます。
社内に設置した社内向けSMTPサーバーの場合は、25番ポートを使ってSMTP認証ではなくPOP before SMTPで認証するような従来通りの設定が多いようですが、インターネットプロバイダのSMTPサーバーではSMTP認証を行っているところも多く、またポートも25番ではなく587番を使っている場合があります。そのため、最小限のコードとは言っても、サンプルでは図2に示したように「SMTP認証」と「メール送信」という2つの機能を実装しています。
System.Net.Mailの使用方法
Try Dim _smtp As New System.Net.Mail.SmtpClient 'IDisposeを実装してない _smtp.Host = Me.Server_TextBox.Text.Trim _smtp.Port = Me.Port_TextBox.Text.Trim _smtp.Credentials = New System.Net.NetworkCredential(Me.UserId_TextBox.Text.Trim, _ Me.Password_TextBox.Text.Trim) _smtp.Timeout = 100000 _smtp.Send(Me.From_TextBox.Text.Trim, _ Me.To_TextBox.Text.Trim, _ "[SNM]" & Me.Subject_TextBox.Text.Trim, _ Me.MailText_TextBox.Text) isOK = True MessageBox.Show("Sytem.Net.Mail送信終了") Catch ex As Exception MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Finally End Try
System.Net.MailでSMTP認証を行うには、CredentialsプロパティにユーザーIDとパスワードを渡します。しかし、SMTP認証の種類は指定できず、「LOGIN」「PLAIN」「MD5」のいずれにするかはサーバーとの間のネゴシエーションによって自動的に決定されます。また、SMTP認証を行うときには.Timeoutプロパティの値を100,000程度に設定しないと、うまくSMTPサーバーと繋がらないことがあるようです。
ここまで準備ができていれば、後はSendメソッドに「送信元」「送信先」「件名」「本文」を渡すだけでメールが送信できます。サンプルコードの例では、SMTP認証を行っていますが、「POP before SMTP」が使われている場合は、Credentialsプロパティを設定しているコードの代わりにSystem.Net.Socketsを使ってPOP3サーバーに接続するコードを記述します。
Dart.PowerTCP.SecureMailの使用方法
Try Using _smtp As New Dart.PowerTCP.SecureMail.Smtp _smtp.Server = Me.Server_TextBox.Text.Trim _smtp.ServerPort = Me.Port_TextBox.Text.Trim Select Case True Case Me.AuthLogin_RadioButton.Checked smtp.LoginMethod = Dart.PowerTCP.SecureMail.SmtpLoginMethod.AuthLogin Case Me.AuthPlain_RadioButton.Checked smtp.LoginMethod = Dart.PowerTCP.SecureMail.SmtpLoginMethod.AuthPlain Case Me.AuthMd5_RadioButton.Checked smtp.LoginMethod = Dart.PowerTCP.SecureMail.SmtpLoginMethod.AuthCramMd5 End Select _smtp.Username = Me.UserId_TextBox.Text.Trim _smtp.Password = Me.Password_TextBox.Text.Trim _smtp.Send(Me.To_TextBox.Text.Trim, _ Me.From_TextBox.Text.Trim, _ "[GSM]" & Me.Subject_TextBox.Text.Trim, _ Me.MailText_TextBox.Text) _smtp.Close() End Using isOK = True MessageBox.Show("SecureMail送信終了") Catch ex As Exception MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Try
System.Net.Mail.SmtpClientと異なり、SecureMailではSmtpLoginMethodを指定してSMTP認証が行えます。System.Net.Mail.SmtpClientのようなオートネゴシエーションも便利ですが、予期せぬトラブルなどが発生したときに迅速に原因を特定するには、SecureMailのように明示的に指定ができる方が便利です。また、SMTP認証を行っても、タイムアウト値(30,000ミリ秒)を変更せずに問題なくSendメソッドを実行できます。
サンプルコードの例ではSMTP認証を行っていますが、「POP before SMTP」が使われている場合、POP3サーバーに接続するコードを記述します。System.Net.Mailと異なり、SecureMailにはPop3に対応したDart.PowerTCP.SecureMail.Pop3があるので、簡単にPOP3サーバーに接続するコードを記述できます。
Private Function ConnectPop3() As Boolean Using _pop3 As New Dart.PowerTCP.SecureMail.Pop _pop3.Login(Me.Server_TextBox.Text.Trim, _ Me.UserId_TextBox.Text.Trim, _ Me.Password_TextBox.Text.Trim) _pop3.Logout() End Using System.Threading.Thread.Sleep(300) Return True End Function
実行結果
サンプル「CZ1003Simple」を実行して同一宛先に送信し、どのような内容のメールになっているかを確認してみましょう。
サンプルを実行するときに注意したいのは、どこに日本語を指定しておくかという点です。それというのも、メールクライアントソフトにとって日本語はテキストではないからです。そのため、MIME(Multipurpose Internet Mail Extensions)形式にしてISO-2022-JPで7bitエンコードにするのがデファクトスタンダードになっています。
(1)System.Net.Mail.SmtpClient
System.Net.Mail.SmtpClientから送信したメールをメールクライアントソフト「Becky! Internet Mail Version 2.53 [ja]」(以下、Becky!)で受信すると、文字化けせずに正しく受信できます。しかし、本来は文字化けしても仕方がないようなメールであっても、メールクライアントソフトが正しく表示できるように内部処理している可能性があるので、受信したメールそのものをBecky!の[表示]-[ソースの表示]で確認してみます。
MIME-Version: 1.0 From: hatsune@wankuma.com To: hatsune@wankuma.com Date: 14 Mar 2010 20:59:38 +0900 Subject: =?utf-8?B?W1NOTV3ml6XmnKzoqp7jga7ku7blkI3jgYzjganjgYblh6bnkIbjgZXjgozjgovjgYvjga50ZXN055So5Lu25ZCN?= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 5pel5pys6Kqe5pys5paH
MIME-Versionヘッダがあるので、MIME形式のメールとして送信しているのが分かります。前述のとおり、MIME形式の日本語のメールはISO-2022-JPで7bitエンコードにするのがデファクトスタンダードですが、Content-TypeヘッダやContent-Transfer-Encodingヘッダを見るとUTF-8のBase64として送信しています。これでは、デファクトスタンダードの形式しかサポートしていないメールクライアントソフトの場合、文字化けが発生してしまいます。
(2)SecureMail
SecureMailから送信したメールもBecky!で受信すると文字化けもせずに正しく受信できます。こちらもメールそのものをBecky!の[表示]-[ソースの表示]で確認してみましょう。
To: hatsune@wankuma.com From: hatsune@wankuma.com Subject: [GSM]日本語の件名がどう処理されるかのtest用件名 Date: Sun, 14 Mar 2010 20:44:09 +0900 (JST) 日本語本文
大きく異なるのは、MIME-Versionヘッダがないので非MIME形式だという点です。そして、Subjectや本文についてはシフトJISコードで送信されています。また、Content-TypeヘッダやContent-Transfer-Encodingヘッダはありません。シフトJISコードが読めるのであれば文字化けは発生しないと思いますが、7bitではなく8bitで送信しているので、7bitしか通過できない経路を経由した場合、RFC的には文字化けが発生する可能性があります。
メールアドレスに日本語情報を付与して送信した場合の実行結果
メールを送る際、「hogehoge@hoge.jp」ではなく「"初音"<hogehoge@hoge.jp>」のように、メールアドレスだけではなく姓名や役職名なども含めて送信したいときがあります。
このような指定を行った場合、サンプル「CZ1003Simple」の実行結果は次のようになります。
(1)System.Net.Mail.SmtpClientの場合
System.Net.Mail.SmtpClinetのSendメソッドはこの形式のアドレス指定に対応していないため、指定をした場合は実行時エラーとなります。
(2)SecureMailの場合
SecureMailのSendメソッドはこの形式のメールアドレス指定にも対応しているため、正常に送信が行えます。
To: "初音玲" <hatsune@wankuma.com> From: "初音玲" <hatsune@wankuma.com> Subject: [GSM]Fromも件名も日本語がどう処理されるかのtest用件名 Date: Sun, 14 Mar 2010 21:03:33 +0900 (JST) 日本語本文
SecureMailのSendメソッドが日本のデファクトスタンダード仕様をデフォルトでサポートしていれば最も良いのですが、デフォルトが非MIMEメールクライアント用であるというコンセプトは一概に否定できません。