Recipe 17.9. Sending Email Using SMTPProblemYou want to send an email automatically from your application without using an external application such as Outlook. SolutionSample code folder: Chapter 17\SendEmail
Use the
System.Net. Mail.SmtpClient
class in the .NET Framework, supplying the server
DiscussionThe System.Net.Mail.SmtpClient class encapsulates an email submission. All you need to do is fill in its properties and call the Send() method, and your mail is delivered to the target recipient.
Create a new Windows Forms application, and add five TextBox controls named ServerHost, FromEmail, ToEmail, SubjectText , and BodyText . Set the BodyText control's Multiline property to true . Also add a Button control named ActSend , and set its Text property to Send . Add informational labels if desired. Your form should look something like Figure 17-11. Figure 17-11. Controls for the email-sending sample
Now add the following code to the form's class template: Imports System.Net.Mail Public Class Form1 Private Sub ActSend_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ActSend.Click ' ----- Send the requested email. Dim emailSender As SmtpClient Dim theMessage As MailMessage ' ----- Connect to the server. A second optional ' argument lets you alter the port number from ' the default. emailSender = New System.Net.Mail.SmtpClient( _ ServerHost.Text) ' ----- Build the content details. theMessage = New MailMessage theMessage.From = New MailAddress(FromEmail.Text) theMessage.To.Add(ToEmail.Text) theMessage.Subject = SubjectText.Text theMessage.Body = BodyText.Text ' ----- Fill in the details and send. emailSender.Send(theMessage) End Sub End Class The MailMessage object includes properties that let you add attachments and specify the properties of the email message. Its To property is a collection that lets you add an unlimited number of email recipients. It also includes parallel CC and Bcc collections. |
Recipe 17.10. Getting POP3 EmailsProblemYou want to access emails from an application, perhaps just to get a quick count of available emails or to get the complete contents. SolutionSample code folder: Chapter 17\Pop3Email Use the TcpClient class in the System.Net. Sockets namespace. The Pop3 class presented here wraps this class with supporting code to make it easier to access your emails. DiscussionThe following class code creates Pop3 objects to simplify accessing emails from a standard POP3 server. Note that some servers require SSL or other authentication, in which case this code will need modification. For standard POP3 servers, it works well as presented. Create a new Windows Forms application, add a new class named Pop3.vb , and use this code for its definition:
Public Class Pop3
' ----- The default TCP/IP port number for POP3 is 110.
Public Port As Integer = 110
Public Messages As Integer = 0
Private Const CommandFailure As String = "-ERR"
Private Pop3Server As TcpClient
Private CommandSender As NetworkStream
Private ContentReceiver As StreamReader
Public Sub Connect(ByVal serverName As String, _
ByVal userName As String, ByVal password As String)
' ----- Initiate the connection to a POP3 server.
Dim commandData As String
Dim contentBuffer() As Byte
Dim responseString As String
Dim parts() As String
' ----- Connect to the POP3 server.
Try
Pop3Server = New TcpClient(serverName, Port)
CommandSender = Pop3Server.GetStream()
ContentReceiver = New StreamReader(CommandSender)
Catch
Throw
End Try
If (userName <> "") Then
' ----- Authenticate with the user ID.
commandData = "USER " & userName & vbCrLf
contentBuffer = _
System.Text.Encoding.ASCII.GetBytes( _
commandData.ToCharArray())
CommandSender.Write(contentBuffer, 0, _
contentBuffer.Length)
responseString = ContentReceiver.ReadLine()
If (Left(responseString, Len(CommandFailure)) = _
CommandFailure) Then
Throw New Exception("Invalid user name.")
End If
' ----- Send the authenticating password.
commandData = "PASS " & password & vbCrLf
contentBuffer = _
System.Text.Encoding.ASCII.GetBytes( _
commandData.ToCharArray())
CommandSender.Write(contentBuffer, 0, _
contentBuffer.Length)
responseString = ContentReceiver.ReadLine()
If (Left(responseString, Len(CommandFailure)) = _
CommandFailure) Then
Throw New Exception("Invalid password.")
End If
End If
' ----- Logged in. On some servers, the PASS command
' is not enough to push the server into a
' transaction state. Send a STAT command twice.
commandData = "STAT" + vbCrLf
contentBuffer = System.Text.Encoding.ASCII.GetBytes( _
commandData.ToCharArray())
CommandSender.Write(contentBuffer, 0, _
contentBuffer.Length)
responseString = ContentReceiver.ReadLine()
' ----- Get a count of the messages.
commandData = "STAT" + vbCrLf
contentBuffer = System.Text.Encoding.ASCII.GetBytes( _
commandData.ToCharArray())
CommandSender.Write(contentBuffer, 0, _
contentBuffer.Length)
responseString = ContentReceiver.ReadLine()
If (Left(responseString, Len(CommandFailure)) = _
CommandFailure) Then
Throw New Exception( _
"Could not retrieve message count.")
End If
' ----- The response includes two integers: a count
' and a size, separated by a space. Skip over
' the "+OK" part also.
parts = Split(responseString, " ")
Messages = Val(parts(1))
End Sub
Public Sub Disconnect()
' ----- Disconnect from the
POP3 server.
Dim commandData As String
Dim contentBuffer() As Byte
Dim responseString As String
' ----- Tell the server we're through.
commandData = "QUIT" & vbCrLf
contentBuffer = System.Text.Encoding.ASCII.GetBytes( _
commandData.ToCharArray())
CommandSender.Write(contentBuffer, 0, _
contentBuffer.Length)
responseString = ContentReceiver.ReadLine()
' ----- End the connection.
ContentReceiver.Close()
CommandSender.Close()
Pop3Server.Close()
End Sub
Function GetMessage(ByVal whichMessage As Integer) _
As String
' ----- Retrieve a single email message.
Dim commandData As String
Dim contentBuffer() As Byte
Dim responseString As String
Dim theMessage As New System.Text.StringBuilder
Dim oneLine As String
' ----- Check for an invalid message.
If (whichMessage < 1) Or (whichMessage > Messages) Then
Throw New ArgumentOutOfRangeException(whichMessage, _
"Messages are numbered from 1 to the number " & _
"identified by the Messages property.")
End If
Try
' ----- Request the message.
commandData = "RETR " & whichMessage & vbCrLf
contentBuffer = _
System.Text.Encoding.ASCII.GetBytes( _
commandData.ToCharArray())
CommandSender.Write(contentBuffer, 0, _
contentBuffer.Length)
responseString = ContentReceiver.ReadLine()
If (Left(responseString, Len(CommandFailure)) = _
CommandFailure) Then
Throw New Exception("Message retrieval failed.")
End If
' ----- The message is all data until a line with
' a single dot (.) appears.
Do While (ContentReceiver.EndOfStream = False)
oneLine = ContentReceiver.ReadLine()
If (oneLine = ".") Then Exit Do
theMessage.AppendLine(oneLine)
Loop
Catch ex As InvalidOperationException
MsgBox("Message retrieval failed: " & ex.Message)
End Try
' ----- Return the constructed message.
Return theMessage.ToString()
End Function
End Class
Return to Form1 , and add three TextBox controls named ServerName, UserName , and UserPassword . Set the UserPassword control's PasswordChar field to the asterisk character (*). Add a ListBox control named MessageList and two Button controls named ActGet and ActView . Set the Button controls' Text properties to Get Messages and View Message , respectively. Add informational labels if desired. The form should look like the one in Figure 17-12. Figure 17-12. Controls for the POP3 sample
Now add the following code to Form1 's class template:
Private POP3Connection As Pop3 = Nothing
Private Sub ActGet_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ActGet.Click
' ----- Initiate a POP3 connection.
Dim counter As Integer
' ----- First, disconnect any previous connection.
If (POP3Connection IsNot Nothing) Then
Try
POP3Connection.Disconnect()
Catch ex As Exception
' ----- Ignore.
End Try
End If
POP3Connection = Nothing
' ----- Clear any previous messages.
MessageList.Items.Clear()
' ----- Try the new connection.
Try
POP3Connection = New Pop3
POP3Connection.Connect(ServerName.Text, _
UserName.Text, UserPassword.Text)
Catch ex As Exception
MsgBox("Connection failure: " & ex.Message)
POP3Connection = Nothing
Return
End Try
' ----- How many messages?
If (POP3Connection.Messages = 0) Then
MsgBox("No messages found.")
POP3Connection.Disconnect()
POP3Connection = Nothing
Return
End If
' ----- Show each message.
For counter = 1 To POP3Connection.Messages
MessageList.Items.Add("Message Number " & counter)
Next counter
End Sub
Private Sub ActView_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ActView.Click
' ----- Show a message.
Dim whichMessage As Integer
Dim parts As String()
Dim content As String
' ----- Which message? Each item has the format:
' Message Number x
If (MessageList.SelectedIndex = -1) Then Return
parts = Split(CStr(MessageList.SelectedItem), " ")
whichMessage = CInt(Val(parts(2)))
' ----- Get the content.
content = POP3Connection.GetMessage(whichMessage)
' ----- Show the content.
MsgBox(content)
End Sub
Private Sub MessageList_DoubleClick(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles MessageList.DoubleClick
' ----- Same as the View button.
ActView.PerformClick()
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, _
ByVal e As System.Windows.Forms.FormClosingEventArgs) _
Handles Me.FormClosing
' ----- Disconnect before leaving.
On Error Resume Next
If (
POP3Connection IsNot Nothing) Then
POP3Connection.Disconnect()
POP3Connection = Nothing
End If
End Sub
When you successfully connect to a POP3 server through the
ActGet
button, it displays a simple list of each message stored on the server. It's not as good as a real email program such as Microsoft Outlook because it hasn't yet read even the sender name or subject text, but it does add one entry for each available message. Clicking on the
ActView
button retrieves the content for one email message from the server through the
Pop3
class's
GetMessage()
method. The connection to the email server is closed when the form
Figure 17-13 shows the content from a test email retrieved from a POP3 server. This rather short sample email arrives with considerable overhead in the header details. The message body is near the end, and it shows the email was sent using HTML content. Figure 17-13. An email retrieved from a POP3 server
|