public class MyMail { // public static final String POP3_SERVER = "pop3.neugebauer.cc"; // // public static final int POP3_PORT = 110; // // public static final String POP3_USER = "informatik@neugebauer.cc"; // // public static final String POP3_PASS = "ifq2_user1"; public static void main(String[] args) { new MyMail(); } private String ip; private int port; private Connection con; private MyMailGUI gui; private String user; private String password; private String lastError; private LoginGUI loginGUI; /** * Verbindet zu einem lokalen POP3-Server. */ public MyMail() { loginGUI = new LoginGUI(this); } public void start(String pIP, int pPort, String pUser, String pPassword) { ip = pIP; port = pPort; user = pUser; password = pPassword; // GUI erstellen und Status setzen. gui = new MyMailGUI(this); gui.setStatus("App gestartet"); getAllMails(); } /** * Stellt die Verbindung zum POP3-Server her. *
* Erstellt ein {@link Connection}-Objekt für die Verbindung zum Server mit der * IP {@link #ip} und dem Port {@link #port}. Laut RFC1939 sendet der * POP3-Server als Erstes eine Begrüßungsnachricht zur Bestätigung der * Verbindung: * *
Once the TCP connection has been opened by a POP3 client, the * POP3 server issues a one line greeting. This can be any positive response. An * example might be: S: +OK POP3 server ready*
* Gibt es beim Verbindungsaufbau einen Fehler, gibt die Methode {@code false} * zurück und setzt {@link #lastError} auf eine sinnvolle Fehlermeldung. *
* Das {@code Connection}-Objekt wird in {@link #con} gespeichert. * * @return {@code true} oder {@code false} * @link https://datatracker.ietf.org/doc/html/rfc1939#section-4 */ private boolean connectToServer() { // TODO: Connection-Objekt initialisieren con = new Connection(ip, port); // Begrüssungsnachricht des Servers empfangen und prüfen String mes = con.receive(); if (mes == null || mes.startsWith("-ERR")) { // Keine "positive response" :-( // Setze einen Fehler und gib "false" zurück. lastError = "Der POP3-Server reagiert nicht!"; return false; } // Verbindung erfolgreich return true; } /** * Authentifiziert den Nutzer beim POP3-Server. *
* Die Methode nutzt die {@code USER} / {@code PASS} Befehle zur Anmeldung mit * dem {@link #user} und {@link #password}. Sie erwartet, dass zuvor erfolgreich * eine Verbindung mit {@link #connectToServer()} hergestellt wurde. *
* Hat die Anmeldung Erfolg, wird {@code true} zurückgegeben. Andernfalls * {@code false} und {@link #lastError} wird auf eine sinnvolle Fehler- meldung * gesetzt. * * @return {@code true} oder {@code false} * @link https://datatracker.ietf.org/doc/html/rfc1939#page-13 */ private boolean login() { String mes = ""; // Speicher für die Antworten des Servers // TODO: Implementieren // USER Kommando senden und Antwort prüfen con.send("USER " + user); mes = con.receive(); if (mes == null || mes.startsWith("-ERR")) { lastError = "Ungueltiger Benutzername!"; return false; } // PASS Kommando senden und Antwort prüfen con.send("PASS " + password); mes = con.receive(); if (mes == null || mes.startsWith("-ERR")) { lastError = "Ungueltiges Passwort!"; return false; } // Anmeldung war erfolgreich return true; } /** * Ermittelt die Anzahl an Nachrichten auf dem Server. *
* Die Methode erwartet, dass zuvor erfolgreich eine Verbindung mit * {@link #connectToServer()} hergestellt wurde und nutzt dann den {@code STAT} * Befehl, um die Anzahl der Mails zu ermitteln. * * @return Die Anzahl an Mails auf dem Server * @link https://datatracker.ietf.org/doc/html/rfc1939#page-6 */ public int getMessageCount() { String mes = ""; // TODO: Implementieren // Sende den STAT Befehl // Prüfe, ob die Antwort ein Fehler ist // Schneide den Teil zwischen den Leerzeichen aus // Finde die Leerzeichen mit indexOf(" ") // Ermittele den Text mit substring(von, bis) // Wandele mit Integer.parseInt() in eine Zahl um con.send("STAT"); mes = con.receive(); int space1 = mes.indexOf(" "); int space2 = mes.indexOf(" ", space1 + 1); return Integer.parseInt(mes.substring(space1, space2).trim()); // ---=== Alternativ ===--- // return Integer.parseInt(mes.split(" ")[1]); } /** * Ruft alle vorhandenen Mails vom Server ab und fügt sie der {@link #gui} * hinzu. */ public void getAllMails() { gui.setStatus("Rufe Mails vom Server ab.."); gui.clearAllMails(); // Gui leeren lastError = null; // Zu Beginn gibt es noch keinen Fehler // Verbindung erstellen und prüfen boolean connected = connectToServer(); if (!connected) { // Letzten Fehler anzeigen (wird in connectToServer gesetzt). lastError = "Fehler beim Verbinden."; return; // Abbrechen } // Anmeldung durchführen und prüfen // Hinweis: Nutze die login() Methode boolean loggedIn = login(); if (!loggedIn) { // Letzten Fehler anzeigen (wird in connectToServer gesetzt). lastError = "Fehler beim Einloggen."; return; // Abbrechen } // Anzahl Mails auf dem Server abfragen int mailCount = 0; mailCount = getMessageCount(); // Abruf der Mails nach fortlaufender Nummer for (int i = 1; i <= mailCount; i++) { // Mail abrufen (nutze getMail(int)) // Mail der GUI hinzufügen (nutze gui.addMailToLost(Mail)) gui.addMailToList(getMail(i)); } // Verbindung beenden con.send("QUIT"); con.close(); if (lastError != null) { // Es gab einen Fehler gui.setError(lastError); } else { // Kein Fehler gui.setStatus("Liste der Mails erfolgreich geladen."); } } /** * Ruft die Mail mit der Nummer pNumber vom Server ab und gibt sie * als {@link Mail}-Objekt zurück. *
* Die Methode erwartet, dass zuvor erfolgreich eine Verbindung mit * {@link #connectToServer()} hergestellt wurde. *
* Tritt ein Fehler auf, gibt die Methode {@code null} zurück und setzt * {@link #lastError} auf eine sinnvolle Nachricht. * * @param pNumber Die Nummer einer E-Mail auf dem Server * @return Ein Mail-Objekt oder {@code null}. */ public Mail getMail(int pNumber) { String mes = ""; // Speicher für Antworten des Servers // Prüfen, ob es eine Mail mit der Nummer pNumber gibt int count = getMessageCount(); if (pNumber > count) { lastError = "Es gibt keine Mail " + pNumber + "!"; } // Mail abrufen (RETR) con.send("RETR " + pNumber); mes = con.receive(); boolean header = true; String date = ""; String sender = ""; String subject = ""; String text = ""; while (!mes.equals(".")) { // Text der Mail parsen // Verarbeite die Metadaten, vor allem: // - Nummer der Mail // - Subject // - From // - Date // Wenn der Textkörper anfängt, speichere alle Zeilen in einen String // // Hinweis: Denke daran die Maskierung des Enzeichens "." rückgängig zu // machen. // Tipp: Merk dir in einem boolean, ob du im Textkörper oder im Header bist. mes = con.receive(); if (header) { // Header werden gesucht if (mes.equals("")) { // Header ist nach leerer Zeile zuende header = false; } else if (mes.startsWith("Delivery-date")) { date = mes.substring(15); } else if (mes.startsWith("From")) { sender = mes.substring(mes.indexOf('<') + 1, mes.indexOf('>')); } else if (mes.startsWith("Subject")) { subject = mes.substring(9); } } else { // Nachricht wird gelesen if (mes.equals(".")) { // ende break; } else if (mes.startsWith("--")) { // weirde header MITTEN DRIN EINFACH SO header = true; } else { // Text der später ausgegeben wird mes = mes.replaceAll("=C3=BC", "ü"); // Umlaute werden ersetzt mes = mes.replaceAll("=C3=A4", "ä"); mes = mes.replaceAll("=C3=B6", "ö"); mes = mes.replaceAll("=C3=9F", "ß"); text += mes + "\n"; } } } // end of while return new Mail(pNumber, date, sender, subject, text); } /** * Löscht eine Mail vom Server. *
* Die Methode stellt eine Verbindung zum Server her, markiert die übergebene * Mail als gelöscht und beendet die Verbindung. *
* Tritt ein Fehler auf, bricht die Methode ab und setzt den Status der GUI auf * eine sinnvolle Fehlermeldung. * * Achtung: Es wird die Mail mit derselben Nummer wie pMail * gelöscht. Es wird nicht garantiert, dass dies auch dieselbe Mail ist. * * @param pMail Das Mailobjekt, das gelöscht werden soll. * @todo Vor Löschen prüfen, ob die Mail auf dem Server dieselbe wie pMail ist. */ public void deleteMail(Mail pMail) { // Verbindung erstellen und prüfen boolean connected = connectToServer(); if (!connected) { // Letzten Fehler anzeigen (wird in connectToServer gesetzt). gui.setStatus("Fehler beim Verbinden."); return; // Abbrechen } // Anmeldung durchführen und prüfen boolean loggedIn = login(); if (!loggedIn) { // Letzten Fehler anzeigen (wird in connectToServer gesetzt). gui.setStatus("Fehler beim Einloggen."); return; // Abbrechen } // Prüfen, ob eine Mail mit der Nummer vorhanden ist // Hinweis: Die Nummer der Mail ist über pMail.getNumber() abrufbar Mail m = getMail(pMail.getNumber()); if (m == null) { gui.setStatus("Die mail konnte nicht gelöscht werden, da sie nicht existiert."); return; } else { // Mail als gelöscht markieren //**** con.send("dele " + pMail.getNumber()); // Löschung ausführen und Verbindung beenden. con.send("quit"); } gui.setStatus("Mail erfolgreich gelöscht."); // Mail aus der GUI entfernen und neu aufbauen.s gui.removeMailFromList(pMail); } }