Receiving Email in VB.NET App

rustyd

Well-known member
Joined
Mar 5, 2003
Messages
112
Hi,

New to the sockets stuff and I have some questions about attempting to retrieve email via a .NET application. Ive read quite a few posts about sending email, but the receiving posts seem to say they have a problem and subsequent posts recommend Email components or they figured it out themselves with no solution.

So, here we go a journey to create my own email component.

First, using sockets do I connect to my mail server? Ive read some posts about listening on port 110. So, I connect to mail server, then listen on port 110. Am I on the right track?

Any help is appreciated.

Thanks
 
Other way round, the mail server (if it is POP3) will listen on 110 - you will need to connect to it.
Most of the work involved is simple comands that would be sent / received as simple ASCII text over a connection to port 110.
 
Found a C# example and converted to VB.NET

I found a C# example and converted to VB.NET.

I cant get it to connect to my mail server. The Connect(mailsite, 110) doesnt error out, but when I get the response I get the error:
Operation not allowed on non-connected sockets

I have a form with 3 textboxes (mailserver, user,pass) and a button that
when clicked calls a routine GetMail. GetMail creates and instance of my
Pop3 class which inherits Net.Sockets.TcpClient and I call the overloaded
function Connect(mailserver, 110). Once the Connect call is made it returns
and I call Response() which uses the NetworkStream object and GetStream().
This is where the error occurs. Ive include the exact error message and the entire Pop3 class.

Here is the exact error message:

Code:
System.InvalidOperationException: Operation not allowed on non-connected sockets.
   at System.Net.Sockets.TcpClient.GetStream()
   at TestMail.Pop3.Response() in C:\Documents and Settings\Rusty\My Documents\Visual Studio Projects\TestMail\Pop3.vb:line 141
   at TestMail.Pop3.Connect(String server, String username, String password) in C:\Documents and Settings\Rusty\My Documents\Visual Studio Projects\TestMail\Pop3.vb:line 13
   at TestMail.Form1.GetMail() in C:\Documents and Settings\Rusty\My Documents\Visual Studio Projects\TestMail\Form1.vb:line 130

Here is my class:
Code:
Public Class Pop3
  Inherits System.Net.Sockets.TcpClient

  Public Overloads Sub Connect(ByVal server As String, ByVal username As String, ByVal password As String)

    Dim message As String
    Dim response1 As String
    Dim x As New Net.Sockets.TcpClient()

    x.Connect(server, 110)
    response1 = Response()

    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If

    message = "USER " + username + vbCrLf
    Write(message)
    response1 = Response()
    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If

    message = "PASS " + password + vbCrLf
    Write(message)
    response1 = Response()
    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If
  End Sub

  Public Sub Disconnect()
    Dim message As String
    Dim response1 As String

    message = "QUIT" & vbCrLf
    Write(message)
    response1 = Response()
    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If
  End Sub

  Public Function List() As ArrayList

    Dim message As String
    Dim response1 As String

    Dim retval As New ArrayList()

    message = "LIST" & vbCrLf
    Write(message)
    response1 = Response()
    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If

    Do While (True)
      response1 = Response()
      If (response1 = "." & vbCrLf) Then
        Return retval
      Else
        Dim msg = New Pop3Message()
        Dim seps As Char = " "
        Dim values() As String = response1.Split(seps)

        msg.number = Int32.Parse(values(0))
        msg.bytes = Int32.Parse(values(1))
        msg.retrieved = False
        retval.Add(msg)
        continue()
      End If
    Loop
  End Function

  Public Function Retrieve(ByVal rhs As Pop3Message) As Pop3Message
    Dim message As String
    Dim response1 As String

    Dim msg = New Pop3Message()
    msg.bytes = rhs.bytes
    msg.number = rhs.number

    message = "RETR " + rhs.number + vbCrLf
    Write(message)
    response1 = Response()
    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If

    msg.retrieved = True
    Do While (True)
      response1 = Response()
      If (response1 = "." & vbCrLf) Then
        Exit Do
      Else
        msg.message += Response()
      End If
    Loop

    Return msg
  End Function

  Public Sub Delete(ByVal rhs As Pop3Message)
    Dim message As String
    Dim response1 As String

    message = "DELE " + rhs.number + vbCrLf
    Write(message)
    response1 = Response()
    If (response1.Substring(0, 3) <> "+OK") Then
      Dim Pop3Ex As Pop3Exception
      Pop3Ex.Pop3Exception(response1)
    End If
  End Sub

  Private Sub Write(ByVal message As String)
    Dim en = New System.Text.ASCIIEncoding()

    Dim WriteBuffer(1024) As Byte
    WriteBuffer = en.GetBytes(message)

    Dim stream As Net.Sockets.NetworkStream
    stream.Write(WriteBuffer, 0, WriteBuffer.Length)

    Debug.WriteLine("WRITE:" + message)
  End Sub

  Private Function Response() As String
    Dim enc = New System.Text.ASCIIEncoding()
    Dim serverbuff(1024) As Byte
 **********************
 ERROR OCCURS ON THIS LINE
    Dim stream As Net.Sockets.NetworkStream = GetStream()

    Dim count As Integer = 0
    Do While (True)
      Dim buff(2) As Byte
      Dim bytes As Integer = stream.Read(buff, 0, 1)
      If (bytes = 1) Then
        serverbuff(count) = buff(0)
        count += 1
        If (buff(0) = vbLf) Then
          Exit Do
        End If
      Else
        Exit Do
      End If
    Loop

    Dim retval As String = enc.GetString(serverbuff, 0, count)
    Debug.WriteLine("READ:" + retval)
    Return retval
  End Function
End Class
 
Last edited by a moderator:
It sounds like youre not connected to the server. I would get rid of everything else and concentrate on establishing a TCP connection with the mail server first. Once you have that you can gradually add functionality and test things incrementally. A good way to practice POP3 commands is to telnet into the mail server and then send the commands by typing them in by hand on your telnet client. The remote mail server should respond and send you back some ASCII characters containing the email header, body, and other things. This will give you an idea of how the information is flowing and will allow you to better understand the process of handling the raw bytes for the connection. I believe RFC 1939 is the one that lists the POP3 specification.
 
Telnet vs. My app

I can connect successfully via telnet with the command:
open mymailserver 110

responds with:
+OK Hello There!

I overload the connect method in my Pop3 class and use:
Connect(mailserver, 110)

I get the error:
Operation not allowed on non-connected sockets

I change the Connect to:

Connect("open " + mailserver, 110)

I get the error:
System.Net.Sockets.SocketException: The requested name is valid and was
found in the database, but it does not have the correct associated data
being resolved

What do you make of this?
 
On to the next problem

Wanted to report that I remembered reading a post about someone having problems with their sockets program and they were told about mscorcfg.exe to setup permissions for the program.

I added TestMail.exe to the applications and I can connect!!

OK, enough of the good news. Now I have problems in the Response() call. It crashes on the line

Code:
If (buff(0) = vbLf) Then

Im comparing a byte to a string. So, Ill get this figured out. Thanks for your help so far.
 
Yeah!! Got it to connect.

Fixed the Response() function. Now onto getting it to pull emails.
 
Back
Top