SmtpClientを自前で実装する

携帯電話で設定できるメールアドレスがRFC2822のdot-atomに当てはまらない場合、 .NETで提供されるMailAddressクラスにメールアドレスを設定することができません。

そこで、TCPClinetクラスを使ってメールの送信を行ってみます。

実装例

Protected m_objTCPClient As New TcpClient ' TCP通信のクライアント
Protected m_objNetworkStream As NetworkStream ' データの送受信に使用するNetworkStream

Public Sub SendMail()

    Dim strAddrFrom As string = "local-part@domain"
    Dim strAddrTo As string = "local-part@domain"
    Dim strMailHeader As String
    Dim strMailBody As String

    m_objTCPClient = New TcpClient("SMTPサーバー;", "ポート(25)")
    m_objNetworkStream = m_objTCPClient.GetStream()

    If Not CheckResponse(ReceiveData()) Then Return

    SendCommand("EHLO " & "[127.0.0.1]")
    If Not CheckResponse(ReceiveData()) Then
        SendCommand("HELO " & "[127.0.0.1]")
        If Not CheckResponse(ReceiveData()) Then Return
    End If


    ' 送信元のメールアドレスを送信
    SendCommand("MAIL FROM:<" & strAddrFrom & ">" )

    If Not CheckResponse(ReceiveData()) Then Return

    ' 送信先のメールアドレスを送信
    SendCommand("RCPT TO:<" & strAddrTo & ">")

    If Not CheckResponse(ReceiveData()) Then Return

    ' ヘッダーおよび本文を送信するようサーバーへ送信
    SendCommand("DATA")

    If Not CheckResponse(ReceiveData()) Then Return

    ' 件名やFrom、To、CCなどのメールヘッダーを作成し送信します。
    strMailHeader = "From: " & strAddrFrom & vbCrLf & _
        "To:" & strAddrTo & vbCrLf & _
        "Subject: Mail Test"& vbCrLf & _
        "MIME-Version: 1.0" & vbCrLf & _
        "Content-Type: text/plain;" & vbCrLf & _
        "    charset=""shift_jis"";" & vbCrLf & _
        "Content-Transfer-Encoding: 7bit" & vbCrLf

    SendCommand(strMailHeader)

    ' 本文を作成し送信します。
    strMailBody = "Mail Message" & vbCrLf & _
        vbCrLf & "." & vbCrLf

    SendCommand(strMailHeader)

    If Not CheckResponse(ReceiveData()) Then Return

    SendCommand("QUIT")

    If Not CheckResponse(ReceiveData()) Then Return

End Sub

' サーバーからのレスポンスを受信する
Private Function ReceiveData() As Byte()
    Dim bytReceiveBuff(RECEVIE_BUFFER_SIZE - 1) As Byte
    Dim intReceiveSize As Integer

    Array.Clear(bytReceiveBuff, 0, bytReceiveBuff.Length)

    Do
        intReceiveSize = m_objNetworkStream.Read(bytReceiveBuff, 0, bytReceiveBuff.Length)
    Loop While m_objNetworkStream.DataAvailable

    Return bytReceiveBuff

End Function

' リプライコードの判定
Private Function CheckResponse(ByVal ReceivedBytes() As Byte) As Boolean

    Dim strText As String = Encoding.ASCII.GetString(ReceivedBytes)

    Select Case strText.Substring(0, 1)
        Case "2", "3"
            Return True
        Case "4", "5"
            Return False
        Case Else
            Return False
    End Select
End Function

' サーバーへの送信
Private Sub SendCommand(ByVal Command As String)
    Dim bytBuff As Byte()

    bytBuff = Encoding.ASCII.GetBytes(Command & vbCrLf)
    m_objNetworkStream.Write(bytBuff, 0, bytBuff.Length)

End Sub

件名に日本語を使ったり本文に日本語を使う場合、文字コードをJIS(iso-2022-jp)にエンコードしたり、 Base64でエンコードする必要があります。

Base64でエンコードするには、Convert.ToBase64Stringというメソッドが用意されています。