SMTP Server per Telnet ansprechen

StefanG

Aktives Mitglied
Hallo,

ich möchte mir zum testen eines Virtuellen SMTP Servers auf einem Microsoft Server 2008 R2 ein kleines Teststool bauen.

Java:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.UnknownHostException;

import org.apache.commons.net.telnet.TelnetClient;

public class TelnetSMTP extends TelnetClient {

	public static void main(String[] args)  {

		TelnetClient myTelnetClient = null;

		DataOutputStream os = null;
		BufferedReader br = null;

		String sAnswer = null;

		String sEmpfaenger = "empfanger@domain.de";
		String sAbsender = "absender@domain.de";
		String sServerDNS = "mein-server";
		int iServerPort = 25;

		myTelnetClient = new TelnetClient();

		// Verbindungsaufbau
		try {
			myTelnetClient.connect(sServerDNS, iServerPort);

			os = new DataOutputStream(myTelnetClient.getOutputStream());

			br = new BufferedReader(new InputStreamReader(
					myTelnetClient.getInputStream()));
		} catch (UnknownHostException e) {
			System.err.println(sServerDNS + " - Host unbekannt!");
		} catch (IOException e) {
			System.err.println(sServerDNS + " - I/O Exception!");
		}

		// SMTP Befehle abschicken
		if (myTelnetClient != null && os != null && br != null) {
			try {
				os.writeBytes("HELO\n");
				os.writeBytes("MAIL From: " + sAbsender + "\n");
				os.writeBytes("RCPT To: " + sEmpfaenger + "\n");
				os.writeBytes("DATA\n");
				os.writeBytes("From: " + sAbsender + "\n");
				os.writeBytes("Testnachricht\n"); // message body
				os.writeBytes("\n.\n");
				os.writeBytes("QUIT");

				while ((sAnswer = br.readLine()) != null) {
					System.out.println("Server: " + sAnswer);
					if (sAnswer.indexOf("Ok") != -1) {
						break;
					}
				}
				os.close();
				br.close();
				myTelnetClient.disconnect();
			} catch (UnknownHostException e) {
				System.err.println(sServerDNS + " - Host unbekannt: " + e);
			} catch (IOException e) {
				System.err.println(sServerDNS + " - I/O Exception!: " + e);
			}
		}
	}
}

Ich erhalte in der Konsole folgende Ausgabe:

Server: 220 mein-server Microsoft ESMTP MAIL Service, Version: 6.0.3790.4675 ready at Tue, 21 Jun 2011 12:38:23 +0200

Jedoch passiert dann nichts mehr und die Verbindung wird mit Timeout Fehler beendet. Habt ihr nen Tipp für mich woran es hapert? Sollte ich vielleicht eher eine Socket Verbindung nehmen?
 
Du kannst auch nicht alle SMTP Befehle sofort hintereinander schicken.
Du mußt erst einen Befehl schicken, dann auf Antwort warten, dann einen Befehl schicken, dann auf antwort warten, ...
 
Das Protokoll des SMTP Servers liefert folgende Einträge:

10.xx.xx.xx, -, 21.06.2011, 12:55:15, SMTPSVC1, mein-client, mein-server, 611125, 0, 652, 121, 188677898, TIMEOUT, -, -,
10.xx.xx.xx, -, 21.06.2011, 12:55:15, SMTPSVC1, mein-client, mein-server, 611125, 0, 652, 240, 611125, QUIT, -, -,

Also kann man Schlussfolgern, das nicht einmal das helo gesendet wird.
 
So ist es. Alles hintereinander weg, ohne auf antwort zu warten.
[Java]
os.writeBytes("HELO\n");
os.writeBytes("MAIL From: " + sAbsender + "\n");
os.writeBytes("RCPT To: " + sEmpfaenger + "\n");
os.writeBytes("DATA\n");
os.writeBytes("From: " + sAbsender + "\n");
os.writeBytes("Testnachricht\n"); // message body
os.writeBytes("\n.\n");
os.writeBytes("QUIT");
[/Java]
 
Also wurde das als ein Ausdruck abgeschickt.

Java:
os.writeBytes("HELO\n");
				//os.writeBytes("MAIL From: " + sAbsender + "\n");
				//os.writeBytes("RCPT To: " + sEmpfaenger + "\n");
				//os.writeBytes("DATA\n");
				//os.writeBytes("From: " + sAbsender + "\n");
				//os.writeBytes("Testnachricht\n"); // message body
				//os.writeBytes("\n.\n");
				//os.writeBytes("QUIT");

Habe es einfach mal auskommentiert, erziele aber trotzdem keine Rückmeldung?!
 
Nach RFC 2821 (Simple Mail Transfer Protocol) müssen die Zeilen
mit einem Return, gefolgt von einem LineFeed abgeschlossen werden.

Also wenn, dann so:
Java:
//...
   os.writeBytes("HELO\r\n");
//...

Trotzdem sollte man schon auf die Antworten des Servers warten und ggf. darauf reagieren.

VG ROlf
 
Hier mal die genaue Umsetzung am Beispiel des "MAIL from:". Es wird gewartet bis der Server den Absender bestätigt. Man müsste jetzt nur noch eine "Fehlerbehandlung" einbauen, die bei einer falschen Eingabe die Verbindung sauber trennt...

Java:
os.writeBytes("MAIL From: " + sAbsender + "\r\n");
				os.flush();
				while ((sAnswer = br.readLine()) != null) {
					System.out.println("Server: " + sAnswer);
					if (sAnswer.indexOf("Sender OK") != -1) {
						System.out.println("Absender angenommen!\r\n");
						break;
					}
				}
 
Java:
os.writeBytes("MAIL From: " + sAbsender + "\r\n");
				os.flush();
				while ((sAnswer = br.readLine()) != null) {
					System.out.println("Server: " + sAnswer);
					if (sAnswer.indexOf("Sender OK") != -1) {
						System.out.println("Absender angenommen!\r\n");
						break;
					}
				}

Besser wäre sicher, die Serverantwort an Hand der Reply-Codes (die Zahl am Anfang der Zeile) auszuwerten.
Hier mal ein Link zu einem entsprechenden RFC-Dokument:

http://www.ietf.org/rfc/rfc2821.txt

Die Beschreibung der Reply-Codes findest Du ab Mitte der Seite 41ff.
 

Zurück
Oben