System.Net.Mail.SmtpClientクラスSystem.Net.Mail.MailMessageクラスを使ったメールの送信方法、メール作成時の注意点など。

以下の内容は主に.NET Framework 4以降を対象としている。 サンプルコードは.NET Framework 4.5およびMono 3.8で動作検証済み。

メールの送信

SMTPサーバーのホスト名とポート番号を指定してSmtpClientのインスタンスを作成し、Sendメソッドを呼び出すことで指定した宛先にメールを送ることができる。

SmtpClient(System.Net.Mail名前空間)はSystem.dllに含まれているため、ほとんどの場合は参照の追加を行う必要なく使用することができる。

SmtpClientを使ったメールの送信
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    // メール送信に使用するSMTPサーバー
    const string host = "smtp.example.net";
    const int port = 25;

    using (var client = new SmtpClient(host, port)) {
      // 送信者(From)、宛先(To)、件名(Subject)および本文を指定し、
      // コンストラクタで指定されたSMTPサーバーを使ってメールを送信する
      client.Send("from@example.net", // From
                  "to@example.net", // To
                  "Hello!", // Subject
                  "This is a test mail.");
    }
  }
}
SmtpClientを使ったメールの送信
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    ' メール送信に使用するSMTPサーバー
    Const host As String = "smtp.example.net"
    Const port As Integer = 25

    Using client As New SmtpClient(host, port)
      ' 送信者(From)、宛先(To)、件名(Subject)および本文を指定し、
      ' コンストラクタで指定されたSMTPサーバーを使ってメールを送信する
      client.Send("from@example.net", _
                  "to@example.net", _
                  "Hello!", _
                  "This is a test mail.")
    End Using
  End Sub
End Class

SMTPサーバーの接続時に認証が必要になる場合はCredentialsプロパティ、SSLでの接続(あるいはSTARTTLS)が必要になる場合はEnableSslプロパティを設定する。 以下はGMail SMTPサーバーを使ってGMailアカウントからメールを送信する例。

GMailアカウントを使ってメールを送信する例
using System;
using System.Net;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    // GMail SMTPサーバーを使用するSmtpClientを作成
    using (var client = new SmtpClient("smtp.gmail.com", 587)) {
      // SSL接続を有効にする
      client.EnableSsl = true;

      // SMTPサーバーの認証に使用するユーザー名(GMailアカウント名)とパスワードを指定
      client.Credentials = new NetworkCredential("user", "pass");

      client.Send("user@gmail.com", // From
                  "to@example.net", // To
                  "Hello!", // Subject
                  "This is a test mail.");
    }
  }
}
GMailアカウントを使ってメールを送信する例
Imports System
Imports System.Net
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    ' GMail SMTPサーバーを使用するSmtpClientを作成
    Using client As New SmtpClient("smtp.gmail.com", 587)
      ' SSL接続を有効にする
      client.EnableSsl = True

      ' SMTPサーバーの認証に使用するユーザー名(GMailアカウント名)とパスワードを指定
      client.Credentials = New NetworkCredential("user", "pass")

      client.Send("user@gmail.com", _
                  "to@example.net", _
                  "Hello!", _
                  "This is a test mail.")
    End Using
  End Sub
End Class

MailMessageクラスを使うと、送信するメールの内容を細かく指定することができる。 例えば送信先に複数のメールアドレスを指定したり、ヘッダを設定したりすることができる。

MailMessageクラスを使ってメールを作成・送信する例
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      // MailMessageクラスを使って送信するメールを作成する
      var message = new MailMessage();

      // 差出人アドレス
      message.From = new MailAddress("from@example.net");

      // 送信先に3つのメールアドレスを設定する
      message.To.Add(new MailAddress("alice@example.net"));
      message.To.Add(new MailAddress("bob@example.net"));
      message.To.Add(new MailAddress("charlie@example.net"));

      // メールの優先度を設定する
      message.Priority = MailPriority.High;

      // メールの送信日時(Dateヘッダ)を設定する
      message.Headers["Date"] = (new DateTime(2001, 2, 3, 4, 56, 7)).ToString("r");

      // メールの件名
      message.Subject = "Hello!";

      // メールの本文
      message.Body = "This is a test mail.";

      // 作成したメールを送信する
      client.Send(message);
    }
  }
}
MailMessageクラスを使ってメールを作成・送信する例
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      ' MailMessageクラスを使って送信するメールを作成する
      Dim message As New MailMessage()

      ' 差出人アドレス
      message.From = new MailAddress("from@example.net")

      ' 送信先に3つのメールアドレスを設定する
      message.To.Add(New MailAddress("alice@example.net"))
      message.To.Add(New MailAddress("bob@example.net"))
      message.To.Add(New MailAddress("charlie@example.net"))

      ' メールの優先度を設定する
      message.Priority = MailPriority.High

      ' メールの送信日時(Dateヘッダ)を設定する
      message.Headers("Date") = (New DateTime(2001, 2, 3, 4, 56, 7)).ToString("r")

      ' メールの件名
      message.Subject = "Hello!"

      ' メールの本文
      message.Body = "This is a test mail."

      ' 作成したメールを送信する
      client.Send(message)
    End Using
  End Sub
End Class

本文や件名に日本語などを使用する方法、文字コードに関する注意点などは後述する。

MailMessageクラス

MailMessageクラスは送信するメールを組み立てるためのクラス。 メールヘッダ・文字コードなどに関する設定や、ファイルの添付を行いたい場合はこのクラスを使ってメールを作成する。

本文の文字コード

本文の文字コードを指定する場合は、BodyEncodingプロパティEncodingクラスを指定する。 SmtpClientは指定された文字コードを使用して本文をエンコードし、送信する。 この際、UTF-8, UTF-16, UTF-32の場合にはContent-Transfer-EncodingにBASE64が使用され、それ以外の場合にはquoted-printableが使用される。

本文の文字コードの指定
using System;
using System.Net.Mail;
using System.Text;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Subject = "こんにちは!";

      message.Body = "これはテストメールです。";
      message.BodyEncoding = Encoding.UTF8; // 文字コードにUTF-8を使用する

      client.Send(message);
    }
  }
}
本文の文字コードの指定
Imports System
Imports System.Net.Mail
Imports System.Text

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Subject = "こんにちは!"

      message.Body = "これはテストメールです。"
      message.BodyEncoding = Encoding.UTF8 ' 文字コードにUTF-8を使用する

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(BodyEncodingにUTF-8を指定した場合、抜粋)
From: from@example.net
To: to@example.net
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: base64

44GT44KM44Gv44OG44K544OI44Oh44O844Or44Gn44GZ44CC
送信されるメールの内容(BodyEncodingにiso-2022-jpを指定した場合、抜粋)
From: from@example.net
To: to@example.net
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: quoted-printable

=1B$B$3$l$O%F%9%H%a!<%k$G$9!#=1B(B

件名(Subject)の文字コード

件名(Subject)の文字コードを指定する場合は、本文の場合と同様SubjectEncodingプロパティEncodingクラスを指定する。 SmtpClientは指定された文字コードを使用して件名をエンコードし、送信する。

.NET Frameworkでは、本文と同様UTF-8, UTF-16, UTF-32の場合にはBASE64(Bエンコード)、それ以外の場合にはquoted-printable(Qエンコード)が使用される。 Mono 3.8時点では、文字コードに関わらず常にquoted-printable(Qエンコード)が使用される模様。

件名の文字コードの指定
using System;
using System.Net.Mail;
using System.Text;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Subject = "こんにちは!";
      message.SubjectEncoding = Encoding.UTF8; // 文字コードにUTF-8を使用する

      message.Body = "This is a test mail.";

      client.Send(message);
    }
  }
}
件名の文字コードの指定
Imports System
Imports System.Net.Mail
Imports System.Text

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Subject = "こんにちは!"
      message.SubjectEncoding = Encoding.UTF8 ' 文字コードにUTF-8を使用する

      message.Body = "This is a test mail."

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(SubjectEncodingにUTF-8を指定した場合、抜粋)
From: from@example.net
To: to@example.net
Subject: =?utf-8?B?44GT44KT44Gr44Gh44GvIQ==?=

This is a test mail.
送信されるメールの内容(SubjectEncodingにiso-2022-jpを指定した場合、抜粋)
From: from@example.net
To: to@example.net
Subject: =?iso-2022-jp?Q?=1B=24B=243=24s=24K=24A=24O=1B=28B=21?=

This is a test mail.

件名にBエンコードを使用したい場合

件名にBエンコード(BASE64)を使用した文字列を指定したい場合は、次のようにする。

.NET Framework 4.5以降の場合
SubjectEncodingプロパティを設定せず、Bエンコードを二回施した文字列をSubjectプロパティに設定する
.NET Framework 4.0以前の場合
SubjectEncodingプロパティを設定せず、Bエンコードを施した文字列をSubjectプロパティに設定する

なお、version 3.8時点のMonoでも、.NET Framework 4.0以前と同じくBエンコードを1度だけ施した文字列を設定することにより件名にBエンコードを使用することができる。

件名にBエンコードを使用する例
using System;
using System.Net.Mail;
using System.Text;

class Sample {
  private static string BEncode(string str, Encoding encoding)
  {
    return string.Format("=?{0}?B?{1}?=", encoding.HeaderName, Convert.ToBase64String(encoding.GetBytes(str)));
  }

  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");
      var iso2022jp = Encoding.GetEncoding("iso-2022-jp");

      // .NET Framework 4.5以降では、Bエンコードを二回施した文字列を指定する
      message.Subject = BEncode(BEncode("こんにちは!", iso2022jp), iso2022jp);

      // .NET Framework 4.5より前またはMonoの場合は、Bエンコードを施した文字列を指定するだけでOK
      //message.Subject = BEncode("こんにちは!", iso2022jp);

      message.Body = "This is a test mail.";

      client.Send(message);
    }
  }
}
件名にBエンコードを使用する例
Imports System
Imports System.Net.Mail
Imports System.Text

Class Sample
  Private Shared Function BEncode(ByVal str As String, ByVal encoding As Encoding) As String
    Return String.Format("=?{0}?B?{1}?=", encoding.HeaderName, Convert.ToBase64String(encoding.GetBytes(str)))
  End Function

  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")
      Dim iso2022jp As Encoding = Encoding.GetEncoding("iso-2022-jp")

      ' .NET Framework 4.5以降では、Bエンコードを二回施した文字列を指定する
      message.Subject = BEncode(BEncode("こんにちは!", iso2022jp), iso2022jp)

      ' .NET Framework 4.5より前またはMonoの場合は、Bエンコードを施した文字列を指定するだけでOK
      'message.Subject = BEncode("こんにちは!", iso2022jp)

      message.Body = "This is a test mail."

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
From: from@example.net
To: to@example.net
Subject: =?iso-2022-jp?B?GyRCJDMkcyRLJEEkTxsoQiE=?=

This is a test mail.

差出人(From)・宛先(To)・CCなどメールアドレスの表示名と文字コード

メールアドレスを文字列ではなくMailAddressクラスで渡すと、アドレスの表示名(DisplayName)を指定することができる。 表示名の文字コードにはUTF-8が用いられ、Qエンコードされる。

アドレスに表示名を付けてメールを送信する例
using System;
using System.Net.Mail;
using System.Text;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      // メールアドレスと表示名
      var addressFrom = new MailAddress("from@example.net", "差出人");
      var addressTo = new MailAddress("to@example.net", "宛先");

      // MailAddressを使ってインスタンスを作成
      var message = new MailMessage(addressFrom, addressTo);

      // MailAddressはCCなどにも使用することができる
      message.CC.Add(new MailAddress("cc@example.net", "カーボンコピー"));

      message.Subject = "Hello!";

      message.Body = "This is a test mail.";

      client.Send(message);
    }
  }
}
アドレスに表示名を付けてメールを送信する例
Imports System
Imports System.Net.Mail
Imports System.Text

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      ' メールアドレスと表示名
      Dim addressFrom As New MailAddress("from@example.net", "差出人")
      Dim addressTo As New MailAddress("to@example.net", "宛先")

      ' MailAddressを使ってインスタンスを作成
      Dim message As New MailMessage(addressFrom, addressTo)

      ' MailAddressはCCなどにも使用することができる
      message.CC.Add(New MailAddress("cc@example.net", "カーボンコピー"))

      message.Subject = "Hello!"

      message.Body = "This is a test mail."

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
From: =?utf-8?Q?=E5=B7=AE=E5=87=BA=E4=BA=BA?= <from@example.net>
To: =?utf-8?Q?=E5=AE=9B=E5=85=88?= <to@example.net>
Cc: =?utf-8?Q?=E3=82=AB=E3=83=BC=E3=83=9C=E3=83=B3=E3=82=B3=E3=83=94=E3?=
 =?utf-8?Q?=83=BC?= <cc@example.net>

This is a test mail.

他の文字コードを指定したり、Bエンコードを使用したい場合は、エンコード済みの文字列をDisplayNameに指定すれば、そのまま送信される。

表示名をBエンコードしてメールを送信する例
using System;
using System.Net.Mail;
using System.Text;

class Sample {
  private static string BEncode(string str, Encoding encoding)
  {
    return string.Format("=?{0}?B?{1}?=", encoding.HeaderName, Convert.ToBase64String(encoding.GetBytes(str)));
  }

  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var iso2022jp = Encoding.GetEncoding("iso-2022-jp");

      // 表示名にBエンコードした文字列を指定する
      var addressFrom = new MailAddress("from@example.net", BEncode("差出人", iso2022jp));
      var addressTo = new MailAddress("to@example.net", BEncode("宛先", iso2022jp));

      var message = new MailMessage(addressFrom, addressTo);

      message.CC.Add(new MailAddress("cc@example.net", BEncode("カーボンコピー", Encoding.UTF8)));

      message.Subject = "Hello!";

      message.Body = "This is a test mail.";

      client.Send(message);
    }
  }
}
表示名をBエンコードしてメールを送信する例
Imports System
Imports System.Net.Mail
Imports System.Text

Class Sample
  Private Shared Function BEncode(ByVal str As String, ByVal encoding As Encoding) As String
    Return String.Format("=?{0}?B?{1}?=", encoding.HeaderName, Convert.ToBase64String(encoding.GetBytes(str)))
  End Function

  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim iso2022jp As Encoding = Encoding.GetEncoding("iso-2022-jp")

      ' 表示名にBエンコードした文字列を指定する
      Dim addressFrom As New MailAddress("from@example.net", BEncode("差出人", iso2022jp))
      Dim addressTo As New MailAddress("to@example.net", BEncode("宛先", iso2022jp))

      Dim message As New MailMessage(addressFrom, addressTo)

      message.CC.Add(New MailAddress("cc@example.net", BEncode("カーボンコピー", Encoding.UTF8)))

      message.Subject = "Hello!"

      message.Body = "This is a test mail."

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
From: "=?iso-2022-jp?B?GyRCOjk9UD9NGyhC?=" <from@example.net>
To: "=?iso-2022-jp?B?GyRCMDhAaBsoQg==?=" <to@example.net>
Cc: "=?utf-8?B?44Kr44O844Oc44Oz44Kz44OU44O8?=" <cc@example.net>

This is a test mail.

HTMLメールの送信

IsBodyHtmlプロパティtrueにすると、Bodyプロパティに設定した内容をHTML(text/html)として送信することができる。

HTMLメールを送信する例
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Subject = "Hello!";

      message.IsBodyHtml = true;

      message.Body = @"<html>
<head>
  <title>Hello!</title>
</head>
<body>
  <p>This is a <span style=""color: red;"">test</span> mail.</p>
</body>
</html>";

      client.Send(message);
    }
  }
}
HTMLメールを送信する例 
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Subject = "Hello!"

      message.IsBodyHtml = True

      message.Body = "<html>
<head>
  <title>Hello!</title>
</head>
<body>
  <p>This is a <span style=""color: red;"">test</span> mail.</p>
</body>
</html>"

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
Subject: Hello!
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

<html>=0D=0A<head>=0D=0A  <title>Hello!</title>=0D=0A</head>=0D=0A=
<body>=0D=0A  <p>This is a <span style=3D"color: red;">test</span=
> mail.</p>=0D=0A</body>=0D=0A</html>

ファイルの添付

送信するメールにファイルを添付したい場合はAttachmentクラスを使用する。 添付したいファイルごとにAttachmentを作成し、Attachmentsプロパティに追加する。

using System;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Subject = "Hello!";
      message.Body = "This is a test mail.";

      // ファイル"thumbnail.jpg"から添付ファイルを作成する
      var attach1 = new Attachment("thumbnail.jpg", MediaTypeNames.Image.Jpeg);

      // 添付ファイルの名称(メールクライアント上で表示される名称)を設定する
      // (オリジナルのファイル名をそのまま使用する場合は設定しなくてもよい)
      attach1.Name = "サムネイル.jpg";
      attach1.NameEncoding = Encoding.UTF8;

      attach1.ContentDisposition.Inline = true; // 添付した画像をインライン表示する

      // ファイル"image.jpg"から添付ファイルを作成する
      var attach2 = new Attachment("image.jpg", MediaTypeNames.Image.Jpeg);

      attach2.Name = "写真.jpg";
      attach2.NameEncoding = Encoding.UTF8;

      // ファイル"files.zip"から添付ファイルを作成する
      var attach3 = new Attachment("files.zip", MediaTypeNames.Application.Zip);

      // 作成した添付ファイルをメールに追加する
      message.Attachments.Add(attach1);
      message.Attachments.Add(attach2);
      message.Attachments.Add(attach3);

      // 作成したメールを送信する
      client.Send(message);
    }
  }
}
Imports System
Imports System.Net.Mail
Imports System.Net.Mime
Imports System.Text

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Subject = "Hello!"
      message.Body = "This is a test mail."

      ' ファイル"thumbnail.jpg"から添付ファイルを作成する
      Dim attach1 As New Attachment("thumbnail.jpg", MediaTypeNames.Image.Jpeg)

      ' 添付ファイルの名称(メールクライアント上で表示される名称)を設定する
      ' (オリジナルのファイル名をそのまま使用する場合は設定しなくてもよい)
      attach1.Name = "サムネイル.jpg"
      attach1.NameEncoding = Encoding.UTF8

      attach1.ContentDisposition.Inline = True ' 添付した画像をインライン表示する

      ' ファイル"image.jpg"から添付ファイルを作成する
      Dim attach2 As New Attachment("image.jpg", MediaTypeNames.Image.Jpeg)

      attach2.Name = "写真.jpg"
      attach2.NameEncoding = Encoding.UTF8

      ' ファイル"files.zip"から添付ファイルを作成する
      Dim attach3 As New Attachment("files.zip", MediaTypeNames.Application.Zip)

      ' 作成した添付ファイルをメールに追加する
      message.Attachments.Add(attach1)
      message.Attachments.Add(attach2)
      message.Attachments.Add(attach3)

      ' 作成したメールを送信する
      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
From: from@example.net
To: to@example.jp
Subject: Hello!
Content-Type: multipart/mixed;
 boundary=--boundary_0_8cf3cbdb-6a8b-45fa-a6e2-9fa6e86b1419

----boundary_0_8cf3cbdb-6a8b-45fa-a6e2-9fa6e86b1419
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

This is a test mail.
----boundary_0_8cf3cbdb-6a8b-45fa-a6e2-9fa6e86b1419
Content-Type: image/jpeg; name="=?utf-8?B?44K144Og44ON44Kk44OrLmpwZw==?="
Content-Transfer-Encoding: base64
Content-Disposition: inline

/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDAAMCAgMCAgMDAwME
AwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBD
    :
    :
AAAAAAAAAID/2gAIAQEAAT8QFn//2Q==
----boundary_0_8cf3cbdb-6a8b-45fa-a6e2-9fa6e86b1419
Content-Type: image/jpeg; name="=?utf-8?B?5YaZ55yfLmpwZw==?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment

/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDAAMCAgMCAgMDAwME
AwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBD
    :
    :
xAAUEAEAAAAAAAAAAAAAAAAAAADA/9oACAEBAAE/EBYH/9k=
----boundary_0_8cf3cbdb-6a8b-45fa-a6e2-9fa6e86b1419
Content-Type: application/zip; name=files.zip
Content-Transfer-Encoding: base64
Content-Disposition: attachment

UEsDBBQAAAAIACa2QUUj5UOEDQEAAD8XAAAJABwAaW1hZ2UuanBnVVQJAANXBixURgYsVHV4CwAB
BOgDAAAE6AMAAO2XT0oDMRSH30smM+kkMyZtMnZZTzKLQm0FwSsIFnQrBZd6BA/gYaR4CP9suvYQ
    :
    :
AFBLBQYAAAAAAgACAKIAAACPAgAAAAA=
----boundary_0_8cf3cbdb-6a8b-45fa-a6e2-9fa6e86b1419--

Mono 3.8の時点では、Attachment.ContentDispositionFileNameプロパティを設定していなくてもContent-Dispositionヘッダにfilenameパラメータが設定されるが、その内容が正しくエンコードされないため注意が必要。

送信されるメールの内容(Mono 3.8の場合、抜粋)
From: from@example.net
To: to@example.net
Subject: Hello!
Content-Type: multipart/mixed; boundary=--boundary_0_38305959-29ce-476a-919d-f1b701c7d52a

----boundary_0_38305959-29ce-476a-919d-f1b701c7d52a
content-type: text/plain; charset=us-ascii
content-transfer-encoding: 7bit

This is a test mail.

----boundary_0_38305959-29ce-476a-919d-f1b701c7d52a
content-type: image/jpeg; charset=utf-8; name="=?utf-8?Q?=E3=82=B5=E3=83=A0=E3=83=8D=E3=82=A4=E3=83=AB.jpg?="
content-transfer-encoding: base64
content-disposition: inline; filename=繧オ繝繝阪う繝ォ.jpg

  :
  :

ヘッダの長さと折り返し

SubjectプロパティやHeadersプロパティでヘッダの内容を指定する場合、長さは特に制限されない上、ヘッダの折り返しもされない模様。

Subjectヘッダに長い文字列を指定する例
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Body = "This is a test mail.";

      // 件名に360文字の'x'を指定して送信する
      message.Subject = new string('x', 360);

      client.Send(message);
    }
  }
}
Subjectヘッダに長い文字列を指定する例
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Body = "This is a test mail."

      ' 件名に360文字の'x'を指定して送信する
      message.Subject = New String("x"c, 360)

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
From: from@example.net
To: to@example.net
Subject: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: text/plain; charset=us-ascii

This is a test mail.

.NET Frameworkでは半角空白が含まれている個所で自動的に折り返しが行われる。 一方Monoではこの場合も折り返されずにそのまま送信される。

Subjectヘッダに半角空白を含む長い文字列を指定する例
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Body = "This is a test mail.";

      message.Subject =
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx " +
        "xxxxxxxxxx";

      client.Send(message);
    }
  }
}
Subjectヘッダに半角空白を含む長い文字列を指定する例
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Body = "This is a test mail."

      message.Subject = _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx " + _
        "xxxxxxxxxx"

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(.NET Framework 4.5の場合、抜粋)
From: from@example.net
To: to@example.net
Subject: xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx
 xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx
Content-Type: text/plain; charset=us-ascii

This is a test mail.
送信されるメールの内容(Mono 3.8の場合、抜粋)
From: from@example.net
To: to@example.net
Subject: xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx xxxxxxxxxx
Content-Type: text/plain; charset=us-ascii

This is a test mail.

また、Subjectプロパティに設定する文字列に改行とタブを含めることによって強制的にヘッダの折り返しを行わせる方法については、.NET FrameworkではArgumentExceptionとなるため使用できない。 一方Monoではこの方法によってヘッダの折り返しを行うことができる。

SubjectプロパティではなくHeadersプロパティを使ってヘッダに直接値を設定することもできるが、この方法はMonoのみで使用できる。 .NET Frameworkの場合、Headersプロパティを使って値を設定してもSubjectヘッダには反映されない(Subjectヘッダが設定されず、件名が空になる)。

Subjectヘッダの折り返しを行う例
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Body = "This is a test mail.";

      // .NET Frameworkでは件名に改行文字やタブを含めようとするとArgumentExceptionがスローされる
      // Monoでは折り返されたヘッダが送信される
      message.Subject = "aaa\r\n\tbbb\r\n\tccc";
      message.Subject = "aaa\r\n bbb\r\n ccc";
      message.Subject = "aaa\n bbb\n ccc";

      // .NET Frameworkでは値が反映されず、Subjectヘッダが設定されない
      // Monoでは折り返されたヘッダが送信される
      message.Headers["Subject"] = "aaa\r\n\tbbb\r\n\tccc";
      message.Headers["Subject"] = "aaa\r\n bbb\r\n ccc";
      message.Headers["Subject"] = "aaa\n bbb\n ccc";

      client.Send(message);
    }
  }
}
Subjectヘッダの折り返しを行う例
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Body = "This is a test mail."

      ' .NET Frameworkでは件名に改行文字やタブを含めようとするとArgumentExceptionがスローされる
      ' Monoでは折り返されたヘッダが送信される
      message.Subject = "aaa" + vbCrLf + vbTab + "bbb" + vbCrLf + vbTab + "ccc"
      message.Subject = "aaa" + vbCrLf + " " + "bbb" + vbCrLf + " " + "ccc"
      message.Subject = "aaa" + vbLf + " " + "bbb" + vbLf + " " + "ccc"

      ' .NET Frameworkでは値が反映されず、Subjectヘッダが設定されない
      ' Monoでは折り返されたヘッダが送信される
      message.Headers("Subject") = "aaa" + vbCrLf + vbTab + "bbb" + vbCrLf + vbTab + "ccc"
      message.Headers("Subject") = "aaa" + vbCrLf + " " + "bbb" + vbCrLf + " " + "ccc"
      message.Headers("Subject") = "aaa" + vbLf + " " + "bbb" + vbLf + " " + "ccc"

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(.NET FrameworkでHeadersプロパティを設定した場合、抜粋)
From: from@example.net
To: to@example.net
Content-Type: text/plain; charset=us-ascii

This is a test mail.
送信されるメールの内容(Monoの場合、抜粋)
From: from@example.net
To: to@example.net
Subject: aaa
	bbb
	ccc
Content-Type: text/plain; charset=us-ascii

This is a test mail.

ヘッダの折り返しではなく改行文字そのものを件名に含めたい場合などは、Bエンコード(あるいはQエンコード)した文字列を設定する必要がある。 (件名にBエンコードを使用する場合の注意点: §.件名にBエンコードを使用したい場合)

Subjectヘッダに改行を含む文字列を設定する例
using System;
using System.Net.Mail;
using System.Text;

class Sample {
  private static string BEncode(string str, Encoding encoding)
  {
    return string.Format("=?{0}?B?{1}?=", encoding.HeaderName, Convert.ToBase64String(encoding.GetBytes(str)));
  }

  static void Main()
  {
    using (var client = new SmtpClient("smtp.example.net", 25)) {
      var message = new MailMessage("from@example.net", "to@example.net");

      message.Body = "This is a test mail.";

      // Bエンコードして件名に改行を含む文字列を設定する
      message.Subject = BEncode("こんにちは!\r\nこんにちは!", Encoding.GetEncoding("iso-2022-jp"));

      client.Send(message);
    }
  }
}
Subjectヘッダに改行を含む文字列を設定する例
Imports System
Imports System.Net.Mail
Imports System.Text

Class Sample
  Private Shared Function BEncode(ByVal str As String, ByVal encoding As Encoding) As String
    Return String.Format("=?{0}?B?{1}?=", encoding.HeaderName, Convert.ToBase64String(encoding.GetBytes(str)))
  End Function

  Shared Sub Main()
    Using client As New SmtpClient("smtp.example.net", 25)
      Dim message As New MailMessage("from@example.net", "to@example.net")

      message.Body = "This is a test mail."

      ' Bエンコードして件名に改行を含む文字列を設定する
      message.Subject = BEncode("こんにちは!" + vbCrLf + "こんにちは!", Encoding.GetEncoding("iso-2022-jp"))

      client.Send(message)
    End Using
  End Sub
End Class
送信されるメールの内容(抜粋)
From: from@example.net
To: to@example.net
Subject: =?iso-2022-jp?B?GyRCJDMkcyRLJEEkTxsoQiENChskQiQzJHMkSyRBJE8bKEIh?=
Content-Type: text/plain; charset=us-ascii

This is a test mail.

SmtpClientクラス

サーバー証明書の検証

SSL接続を有効にする場合、サーバーが自己署名証明書を使用しているなど、サーバー証明書の検証エラーが原因でSmtpExceptionがスローされる場合がある。 以下はMonoでの例。

サーバー証明書の検証エラーによってスローされたSmtpException
Unhandled Exception:
System.Net.Mail.SmtpException: Message could not be sent. ---> System.IO.IOException: The authentication or decryption has failed. ---> System.IO.IOException: The authentication or decryption has failed. ---> System.InvalidOperationException: SSL authentication error: RemoteCertificateNotAvailable, RemoteCertificateChainErrors

この場合は、ServicePointManagerクラスにコールバックデリゲートを設定し、サーバー証明書の検証を行うコードを記述する必要がある。

サーバー証明書の検証を行うコールバックデリゲートを設定する例
using System;
using System.Net;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    // サーバー証明書の検証を省略し、エラーがあっても証明書を受け付ける
    // (接続先が信頼できる場合を除き、適切な検証を行うべき)
    ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };

    using (var client = new SmtpClient("smtp.example.net", 587)) {
      // SSL接続を有効にする
      client.EnableSsl = true;

      // SMTPサーバーの認証に使用するユーザー名とパスワードを指定
      client.Credentials = new NetworkCredential("from", "pass");

      client.Send("from@example.net", // From
                  "to@example.net", // To
                  "Hello!", // Subject
                  "This is a test mail.");
    }
  }
}
サーバー証明書の検証を行うコールバックデリゲートを設定する例
Imports System
Imports System.Net
Imports System.Net.Mail
Imports System.Net.Security
Imports System.Security.Cryptography.X509Certificates

Class Sample
  Private Shared Function ValidateRemoteCertificate(ByVal sender As Object, _
                                                    ByVal certificate As X509Certificate, _
                                                    ByVal chain As X509Chain, _
                                                    ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
    ' サーバー証明書の検証を省略し、エラーがあっても証明書を受け付ける
    ' (接続先が信頼できる場合を除き、適切な検証を行うべき)
    Return True
  End Function

  Shared Sub Main()
    ServicePointManager.ServerCertificateValidationCallback = AddressOf ValidateRemoteCertificate

    Using client As New SmtpClient("smtp.example.net", 587)
      ' SSL接続を有効にする
      client.EnableSsl = True

      ' SMTPサーバーの認証に使用するユーザー名とパスワードを指定
      client.Credentials = New NetworkCredential("from", "pass")

      client.Send("from@example.net", _
                  "to@example.net", _
                  "Hello!", _
                  "This is a test mail.")
    End Using
  End Sub
End Class

アプリケーション構成ファイルを使った設定

SmtpClientでは、コンストラクタでの指定を省略するとアプリケーション構成ファイルに記述されている内容を読み込んでデフォルト値として使用する。 そのため、構成ファイルを適切に記述しておけばコード上でHost, Port, Credentailsなどのプロパティを指定しなくてもSmtpClientを使用することができるようになる。 (<smtp> 要素 (ネットワーク設定))

コードを書き換えずに使用するSMTPサーバーを変更したい場合などには構成ファイルを使うことができる。 SmtpClientインスタンスを作成したあとプロパティを上書きすれば構成ファイルと異なるサーバーを使用することも出来る。

例としてGMailを使用するようにする場合は、構成ファイルを次のように記述する。

test.exe.config: SmtpClientクラスのデフォルト値を設定するアプリケーション構成ファイル
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.net>
    <mailSettings>
      <smtp deliveryMethod="network">
        <!-- GMail -->
        <network
          host      = "smtp.gmail.com"
          port      = "587"
          enableSsl = "true"
          userName  = "user"
          password  = "pass"
        />
      </smtp>
    </mailSettings>
  </system.net>
</configuration>

コード上では、コンストラクタに何も指定せずにSmtpClientを作成すれば上記の設定が使用される。

test.exe; 構成ファイルに設定されたSmtpClientのデフォルト値を使用するプログラム
using System;
using System.Net.Mail;

class Sample {
  static void Main()
  {
    // 構成ファイルに記述されている設定を使用してSmtpClientを作成する
    using (var client = new SmtpClient()) {
      // メールを送信する
      client.Send("user@gmail.com", // From
                  "to@example.net", // To
                  "Hello!", // Subject
                  "This is a test mail.");
    }
  }
}
test.exe; 構成ファイルに設定されたSmtpClientのデフォルト値を使用するプログラム
Imports System
Imports System.Net.Mail

Class Sample
  Shared Sub Main()
    ' 構成ファイルに記述されている設定を使用してSmtpClientを作成する
    Using client As New SmtpClient()
      ' メールを送信する
      client.Send("user@gmail.com", _
                  "to@example.net", _
                  "Hello!", _
                  "This is a test mail.")
    End Using
  End Sub
End Class

なおnetwork要素で指定できる属性のうち、enableSslのサポートは.NET Framework 4.0以降となっている。 .NET Framework 3.5以前ではenableSslを指定しても読み込まれないため、コード上でEnableSslプロパティを設定する必要がある。