「SmtpClientクラスを使ってメールを送信する」で紹介したように、SmtpClientクラスを使用すると簡単にSMTPでメールを送信することができます。しかし、送信者や宛先などに指定したメールアドレスによっては、SmtpClientクラスで送信しようとすると例外FormatExceptionがスローされることがあります。これは、MailAddressクラスが事前にメールアドレスをチェックして、RFCに基づいた正式な規則に従っていないメールアドレスが指定された時にFormatExceptionをスローしているためです(詳しくは、「メールアドレスが正式な規則にあっているか検証する」)。しかし規則に違反しているメールアドレスも実在しており、普通に使用されています。このようなメールアドレスにメールを送信できないのは、不便です。
この問題の解決法は、正攻法では、存在しません。よって、「SMTPでメールを送信する」で紹介しているSmtpMailクラスを使用したり、「Socketを使ってSMTPでメールを送信する」のように自分でメールを送信するコードを書いたり、サードパーティーのライブラリを使用するといった解決法になってしまいます。
しかし、強引な方法でもよければ、「Can I turn off the email address validation in System.Net.Mail?」で解決法が紹介されています。この方法によると、非公開のMailAddressコンストラクタ「MailAddress(String, String, String)」をリフレクションで呼び出せば、例外を発生させずにMailAddressオブジェクトを作成できるということです。
しかし、本来はできないことを強引に行っているため、予期せぬトラブルが発生する危険は十分あると思ってください。
この方法でMailAddressオブジェクトを作成する例を示します。SmtpClientクラスでメールを送信する時、メールアドレスを文字列で指定せずに、このように作成したMailAddressオブジェクトを使用するようにしてください。
''' <summary> ''' MailAddressオブジェクトを作成する ''' </summary> ''' <param name="address">メールアドレス。</param> ''' <param name="displayName">表示名。省略する時は、Nothing。</param> ''' <returns>MailAddressオブジェクト</returns> Public Shared Function CreateMailAddress( _ address As String, displayName As String) As System.Net.Mail.MailAddress If displayName Is Nothing Then displayName = String.Empty End If 'メールアドレスをユーザーとホストに分解する '(ユーザー名に@が含まれることは考慮していない) Dim ss As String() = address.Split(New Char() {"@"c}, 2) 'MailAddressオブジェクトを作成する Return DirectCast( _ GetType(System.Net.Mail.MailAddress).InvokeMember( _ Nothing, _ System.Reflection.BindingFlags.CreateInstance Or _ System.Reflection.BindingFlags.NonPublic Or _ System.Reflection.BindingFlags.Instance, _ Nothing, _ Nothing, _ New Object() {displayName, ss(0), ss(1)}), _ System.Net.Mail.MailAddress) End Function
/// <summary> /// MailAddressオブジェクトを作成する /// </summary> /// <param name="address">メールアドレス。</param> /// <param name="displayName">表示名。省略する時は、null。</param> /// <returns>MailAddressオブジェクト</returns> public static System.Net.Mail.MailAddress CreateMailAddress( string address, string displayName) { if (displayName == null) { displayName = string.Empty; } //メールアドレスをユーザーとホストに分解する //(ユーザー名に@が含まれることは考慮していない) string[] ss = address.Split(new char[] { '@' }, 2); //MailAddressオブジェクトを作成する return (System.Net.Mail.MailAddress) typeof(System.Net.Mail.MailAddress).InvokeMember( null, System.Reflection.BindingFlags.CreateInstance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, null, new object[] { displayName, ss[0], ss[1] }); }
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。