# SMTP Server per Telnet ansprechen



## StefanG (21. Jun 2011)

Hallo,

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


```
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?


----------



## homer65 (21. Jun 2011)

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, ...


----------



## StefanG (21. Jun 2011)

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.


----------



## homer65 (21. Jun 2011)

Du hast ja auch nicht "helo" gesendet, "helo..." wobei ... für jede Menge anderes Zeugs steht.


----------



## StefanG (21. Jun 2011)

homer65 hat gesagt.:


> Du hast ja auch nicht "helo" gesendet, "helo..." wobei ... für jede Menge anderes Zeugs steht.




```
os.writeBytes("HELO\n");
```

Habe ich nicht?


----------



## homer65 (21. Jun 2011)

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]


----------



## StefanG (21. Jun 2011)

Also wurde das als ein Ausdruck abgeschickt.


```
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?!


----------



## homer65 (21. Jun 2011)

Und wie sieht es aus bei:
[Java]
os.writeBytes("HELO");
os.flush();
[/Java]


----------



## StefanG (21. Jun 2011)

homer65 hat gesagt.:


> Und wie sieht es aus bei:
> [Java]
> os.writeBytes("HELO");
> os.flush();
> [/Java]




Aber bitte "\n" mit anfügen...


```
os.writeBytes("HELO\n");
os.flush();
```


----------



## r.w. (21. Jun 2011)

Nach RFC 2821 (Simple Mail Transfer Protocol) müssen die Zeilen 
mit einem Return, gefolgt von einem LineFeed  abgeschlossen werden.

Also wenn, dann so:

```
//...
   os.writeBytes("HELO\r\n");
//...
```

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

VG ROlf


----------



## StefanG (21. Jun 2011)

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...


```
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;
					}
				}
```


----------



## r.w. (21. Jun 2011)

StefanG hat gesagt.:


> ```
> os.writeBytes("MAIL From: " + sAbsender + "\r\n");
> os.flush();
> while ((sAnswer = br.readLine()) != null) {
> ...



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.


----------

