[C#] POP3 Email Browser

Drucken
( 5 Votes )
Hauptkategorie: Programmieren Kategorie: C#
Erstellt am 27.11.2012 Zuletzt aktualisiert am 28.11.2012 Geschrieben von Jonny132
Leider bietet .NET nicht von Haus aus an, Emails konfortabel von eineim POP3 Server zu laden.
Deshalb muss man sich selber etwas mit TCP und Streams auseinandersetzten.

In diesem Tutorial zeige ich euch wie ihr euch selber einen Emailbrowser mittels POP3 Server nachbauen könnt.

Dazu erstellen wir zuerst ein neues Forms-Projekt mit einer ListBox um die Emails aufzulisten, 2 Labels für Sender und Betreff, eine Textbox für den Inhalt (MultiLine = true) und einem Button welcher das Runterladen der Emails vom POP3 Server startet.

Somit hätten wir die Grundlegende Oberfläche um die POP3 Emails anzeigen zu lassen.

Nun wechseln wir in die Codeansicht, in der wir uns zuerst eine Email-Klasse erstellen, die uns den Umgang mit den Emails erleichtert.

Die Email-Klasse beinhaltet 4 Eigenschaften:


Desweiteren erstellen wir einen Konstruktor, welcher uns als Parameter die Email als Quellcode entgegennimmt (Plain). Aus diesem Plain-Text können wir uns dann die benötigten Daten aus dem Header und aus dem Body herausholen.

Email-Klasse:

  public class Email
  {
    public string Sender { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }

    public string SenderAndSubject
    {
      get
      {
        return Sender + ": " + Subject;
      }
    }

    public Email(string plainEmailText)
    {
      string[] headerLines =
          plainEmailText.Substring(0,
              plainEmailText.IndexOf(Environment.NewLine + Environment.NewLine)).Split(Environment.NewLine.ToCharArray());

      Sender = headerLines.First(s => s.StartsWith("From")).Substring(6);
      Subject = headerLines.First(s => s.StartsWith("Subject")).Substring(9);

      Body = plainEmailText.Substring(plainEmailText.IndexOf(Environment.NewLine + Environment.NewLine));

    }
  }

Um den Header vom Body zu unterscheiden, müssen wir uns etwas mit dem Format auskennen. Der Trick dabei ist, dass dazwischen immer ein doppeltes NewLine vorkommt und somit können wir an dieser Stelle Splitten.

Nun kommt der Interessante Teil. Das holen der Emails vom POP3 Server im Klick-Ereignis des Buttons.
Dazu benötigen wir zuerst eine List<> Objekt das unsere Emails beinhaltet. Dieses können wir dann an unsere Controls bzw. unsere Oberfläche mittels Databinding binden. 
Darüber hinaus benötigen wir jeweils ein Using für ein TcpClient-, NetworkStream- und StreamReader-Objekt.
Das Ganze packen wir noch in einen Try-Catch Block um einen möglichen Fehler abzufangen.

Databinding & Using-Statements:
    private void button1_Click(object sender, EventArgs e)
    {
      try
      {
        List<Email> mails = new List<Email>();

        using (TcpClient server = new TcpClient("host", 110))
        {
          if (server.Connected)
          {
            using (NetworkStream stream = server.GetStream())
            {
              using (StreamReader reader = new StreamReader(stream))
              {
                 // Hier kommt die eigentliche Kommunikation mit dem POP3 Server
              }
            }
          }
        }

        BindingSource bs = new BindingSource(mails, "");

        lbEmails.DataSource = bs;
        lbEmails.DisplayMember = "SenderAndSubject";

        lblSubject.DataBindings.Add("Text", bs, "Subject");
        lblSender.DataBindings.Add("Text", bs, "Sender");
        tbContent.DataBindings.Add("Text", bs, "Body");
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.ToString());
      }
    }

Wie ihr seht, erwartet der Konstruktor der TcpClient den Host und den Port.
Um zu überprüfen ob der POP3 Server verbunden ist, können wir die Connected-Eigenschaft abfragen.

Da ein POP3-Server immer mithilfe von Befehlen arbeitet, habe ich mir eine kleine Hilfsfunktion geschrieben, welche einen Befehl absetzt und überprüft ob die Antwort des Servers OK ist und diese als Boolschen Wert zurückgibt.

Hilfsfunktion SendCommand():
    private bool SendCommand(NetworkStream stream, StreamReader reader, string command)
    {
      byte[] commandBytes = Encoding.ASCII.GetBytes(command + Environment.NewLine);
      stream.Write(commandBytes, 0, commandBytes.Length);

      return reader.ReadLine().Contains("+OK");
    }

Der POP3-Server erwartet immer einen Befehl mit abschliessendem Zeilenumbruch.
Da ein Stream immer auf Byteebene arbeitet, müssen wir den Befehl mittels Encoding in ein ByteArray umwandeln.
Enhält die Antwort vom Server ein OK, so wurde der Befehl erfolgreich durchgeführ und wir können mit der Verarbeitung des Codes weitermachen.

Nun kommen wir wieder zum eigentlichen Code - Dieser gehört, gleich wie der vorige Code, in das Button - Click Ereignis, wo der Kommentar steht und wurde im Tutorial zur Übersicht getrennt.

Kommunikation mit dem Server:
                if (SendCommand(stream, reader, "USER username"))
                {
                  if (SendCommand(stream, reader, "PASS password"))
                  {
                    if (SendCommand(stream, reader, "LIST"))
                    {
                      string emailData;
                      while ((emailData = reader.ReadLine()) != "." && mails.Count <= 5)
                      {
                        int mailID = -1;

                        if (emailData.IndexOf(" ") > 0 && int.TryParse(emailData.Substring(0, emailData.IndexOf(" ")), out mailID))
                        {
                          StreamReader mailReader = new StreamReader(stream);


                          SendCommand(stream, mailReader, "RETR " + mailID);
                          string plainEmailLine;
                          StringBuilder plainEmailLines = new StringBuilder();
                          while ((plainEmailLine = mailReader.ReadLine()) != ".")
                          {
                            plainEmailLines.AppendLine(plainEmailLine);
                          }
                          mails.Add(new Email(plainEmailLines.ToString()));
                        }
                      }

                    }
                    else
                    {
                      MessageBox.Show("Verbindung zum Server wurde verweigert");
                    }
                  }
                }

Zuerst müssen wir uns am POP3-Server authentifizieren.
Dies geschieht in dem wir zuerst den User und anschliessen das zugehörige Passwort per Befehl abschicken und die Antwort auswerten.

Mithilfe des LIST-Befehl, bekommen wir eine Liste der EmailId's über welche wir iterieren können. Damit wir nicht das Ganze Postfach abholen, habe ich die Ausgabe mittels Count im Code auf fünf beschränkt.

Zu guter letzt wird noch der RETR-Befehl mit zugehöriger EmailId ausgeführt, für welchen wir eine neue Reader instanz brauchen. Dieser lädtd die Email als Plaintext nun zur Gänze vom POP3-Server. Genau diesen Plaintext können wir nun an unseren Konstukter der Email-Klasse übergeben und so ein neues Email-Objekt erstellen. 

Oberfläche:
POP3 Email Browser


 

 

Veröffentlichen Sie ihre Kommentare ...