如何正确接受 SMTP 邮件
How to properly accept a SMTP message
我想设置一个简单的 SMTP 服务器,我正在使用 Net.Mail.SmtpClient 发送邮件。一切正常,除非您下次发送消息。一旦服务器接受 TCP 客户端,然后 SMTP 客户端就会抛出错误。它说服务器违反了协议,响应正常。异常不会阻止消息通过。它只是不干净,我想了解为什么会这样。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim smtpMail As New Net.Mail.SmtpClient
Dim msg As New Net.Mail.MailMessage
With smtpMail
.UseDefaultCredentials = False
.Port = 25
.EnableSsl = False
.Host = "127.0.0.1"
End With
With msg
.From = New MailAddress("me@test.com")
.To.Add("lookup@test.com")
.Subject = "Subject"
.Body = "Body"
End With
smtpMail.Send(msg)
End Sub
我的服务器在上面的 Sub 之后通过 运行:
- EHLO(“250 正常”)
- 邮件(“250 OK”)
- RCPT(用户找到后显示“250 OK”。)
- DATA("354开始邮件输入;以.结尾")
- MIME(“250 OK”)
- BODY(“250 OK”)
在 BODY 命令之后,我没有得到进一步的响应。
While True
Dim handler As TcpClient = _Listener.AcceptTcpClient()
Dim smtpReady() As Byte = Encoding.ASCII.GetBytes("220 Test SMTP Service ready" & vbCrLf)
handler.GetStream().Write(smtpReady, 0, smtpReady.Length)
Dim Message As String = String.Empty
Try
While True
bytes = New Byte(1024) {}
Dim bytesRec As Integer = handler.GetStream().Read(bytes, 0, bytes.Length)
dta = Encoding.ASCII.GetString(bytes, 0, bytesRec)
Dim CMD As String = dta.Substring(0, 4).ToUpper
Dim ReturnCMD() As Byte = Nothing
Select Case CMD
Case HELLO
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case MAIL
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case RECIPIENT
Dim SentTo As String = dta.Substring(8).Trim
If SentTo.ToLower <> "<lookup@test.com>" Then
ReturnCMD = Encoding.ASCII.GetBytes("550 No such user here" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Else
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
End If
Case data
ReturnCMD = Encoding.ASCII.GetBytes("354 Start mail input; end with ." & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case QUIT
ReturnCMD = Encoding.ASCII.GetBytes("221 Service closing transmission channel" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Exit While
Case RESET
ReturnCMD = Encoding.ASCII.GetBytes("221 Service closing transmission channel" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Exit While
Case EHELLO
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case MIME
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case BODY
Message += dta
RaiseEvent DataReceived(Message)
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
End Select
End While
handler.Close()
Catch ex As Exception
End Try
End While
代码可能有些 redundancy/is 混乱。到目前为止,这只是对其他东西的测试。我只是想了解 SMTP。
调用 SmtpClient.Dispose
解决了我的问题。这会向服务器发送 QUIT
,并正常关闭连接。
由于关闭连接似乎是问题所在,因此在您的 SMTP 客户端周围添加一个 Using
块可能会有用。 Using
就像一个 try-catch 一样,在它到达关闭 End Using
-
时安全地关闭和处理任何资源连接
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using smtpMail As New Net.Mail.SmtpClient
Using msg As New Net.Mail.MailMessage
With smtpMail
.UseDefaultCredentials = False
.Port = 25
.EnableSsl = False
.Host = "127.0.0.1"
End With
With msg
.From = New MailAddress("me@test.com")
.To.Add("lookup@test.com")
.Subject = "Subject"
.Body = "Body"
End With
smtpMail.Send(msg)
End Using
End Using
End Sub
我想设置一个简单的 SMTP 服务器,我正在使用 Net.Mail.SmtpClient 发送邮件。一切正常,除非您下次发送消息。一旦服务器接受 TCP 客户端,然后 SMTP 客户端就会抛出错误。它说服务器违反了协议,响应正常。异常不会阻止消息通过。它只是不干净,我想了解为什么会这样。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim smtpMail As New Net.Mail.SmtpClient
Dim msg As New Net.Mail.MailMessage
With smtpMail
.UseDefaultCredentials = False
.Port = 25
.EnableSsl = False
.Host = "127.0.0.1"
End With
With msg
.From = New MailAddress("me@test.com")
.To.Add("lookup@test.com")
.Subject = "Subject"
.Body = "Body"
End With
smtpMail.Send(msg)
End Sub
我的服务器在上面的 Sub 之后通过 运行:
- EHLO(“250 正常”)
- 邮件(“250 OK”)
- RCPT(用户找到后显示“250 OK”。)
- DATA("354开始邮件输入;以.结尾")
- MIME(“250 OK”)
- BODY(“250 OK”)
在 BODY 命令之后,我没有得到进一步的响应。
While True
Dim handler As TcpClient = _Listener.AcceptTcpClient()
Dim smtpReady() As Byte = Encoding.ASCII.GetBytes("220 Test SMTP Service ready" & vbCrLf)
handler.GetStream().Write(smtpReady, 0, smtpReady.Length)
Dim Message As String = String.Empty
Try
While True
bytes = New Byte(1024) {}
Dim bytesRec As Integer = handler.GetStream().Read(bytes, 0, bytes.Length)
dta = Encoding.ASCII.GetString(bytes, 0, bytesRec)
Dim CMD As String = dta.Substring(0, 4).ToUpper
Dim ReturnCMD() As Byte = Nothing
Select Case CMD
Case HELLO
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case MAIL
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case RECIPIENT
Dim SentTo As String = dta.Substring(8).Trim
If SentTo.ToLower <> "<lookup@test.com>" Then
ReturnCMD = Encoding.ASCII.GetBytes("550 No such user here" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Else
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
End If
Case data
ReturnCMD = Encoding.ASCII.GetBytes("354 Start mail input; end with ." & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case QUIT
ReturnCMD = Encoding.ASCII.GetBytes("221 Service closing transmission channel" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Exit While
Case RESET
ReturnCMD = Encoding.ASCII.GetBytes("221 Service closing transmission channel" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Exit While
Case EHELLO
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case MIME
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
Case BODY
Message += dta
RaiseEvent DataReceived(Message)
ReturnCMD = Encoding.ASCII.GetBytes("250 OK" & vbCrLf)
handler.GetStream().Write(ReturnCMD, 0, ReturnCMD.Length)
End Select
End While
handler.Close()
Catch ex As Exception
End Try
End While
代码可能有些 redundancy/is 混乱。到目前为止,这只是对其他东西的测试。我只是想了解 SMTP。
调用 SmtpClient.Dispose
解决了我的问题。这会向服务器发送 QUIT
,并正常关闭连接。
由于关闭连接似乎是问题所在,因此在您的 SMTP 客户端周围添加一个 Using
块可能会有用。 Using
就像一个 try-catch 一样,在它到达关闭 End Using
-
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using smtpMail As New Net.Mail.SmtpClient
Using msg As New Net.Mail.MailMessage
With smtpMail
.UseDefaultCredentials = False
.Port = 25
.EnableSsl = False
.Host = "127.0.0.1"
End With
With msg
.From = New MailAddress("me@test.com")
.To.Add("lookup@test.com")
.Subject = "Subject"
.Body = "Body"
End With
smtpMail.Send(msg)
End Using
End Using
End Sub