# Mail über Exchange versenden



## MopsdeBops (12. Apr 2011)

Hallo zusammen

Momentan schreibe ich ein kleines Programm, das lediglich eine E-Mail schreiben und eine empfangen soll. Die Probleme fingen schon früh an, da bei unserem Exchange POP3, SMTP und IMAP im internet Netz deaktiviert sind. Nach aussen natürlich nicht, aber das spielt keine Rolle. Im internet Netz geht das ganze über MAPI.
So habe ich also zuerst gegoolt was ich denn sonst verwenden könnte und bin auf EWS gestossen. Habe dann begonnen das ein wenig auszuprobieren und schon wieder kam der nächste Fehler. An diesem Sitze ich nun schon seit 3 Stunden. Hier mal mein Code


```
import java.net.URI;

import microsoft.exchange.webservices.data.*;
import microsoft.exchange.webservices.data.ExchangeService;


public class SI_Outlook {
	public static void main(String[] args) throws Exception {
		String email = "MLSOSVC-SysMon@bdo.intra";
		String password = "passwort";
		ExchangeService service = new ExchangeService();
		ExchangeCredentials credentials = new WebCredentials(email, password);
		service.setCredentials(credentials);
		service.setUrl(new URI("https://host/EWS/exchange.asmx"));
		Senden(service);
	}
	public static void Senden(ExchangeService service) throws Exception {
		EmailMessage msg= new EmailMessage(service);
		msg.setSubject("Hello world!"); 
		msg.setBody(MessageBody.getMessageBodyFromText("Sent using the EWS Managed API."));
		msg.getToRecipients().add("empfänger@mail");
		msg.send();
	}
}
```

Dann erhalte ich folgenden Error.


```
Exception in thread "main" microsoft.exchange.webservices.data.ServiceRequestException: The request failed. sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at microsoft.exchange.webservices.data.ServiceRequestBase.validateAndEmitRequest(Unknown Source)
	at microsoft.exchange.webservices.data.SimpleServiceRequestBase.internalExecute(Unknown Source)
	at microsoft.exchange.webservices.data.MultiResponseServiceRequest.execute(Unknown Source)
	at microsoft.exchange.webservices.data.ExchangeService.internalCreateItems(Unknown Source)
	at microsoft.exchange.webservices.data.ExchangeService.createItem(Unknown Source)
	at microsoft.exchange.webservices.data.Item.internalCreate(Unknown Source)
	at microsoft.exchange.webservices.data.EmailMessage.internalSend(Unknown Source)
	at microsoft.exchange.webservices.data.EmailMessage.send(Unknown Source)
	at SI_Outlook.Senden(SI_Outlook.java:32)
	at SI_Outlook.main(SI_Outlook.java:20)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
	at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(Unknown Source)
	at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
	at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
	at java.io.BufferedOutputStream.flush(Unknown Source)
	at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:506)
	at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
	at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
	at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
	at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
	at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
	at microsoft.exchange.webservices.data.HttpClientWebRequest.executeRequest(Unknown Source)
	at microsoft.exchange.webservices.data.ServiceRequestBase.emit(Unknown Source)
	... 10 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
	at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
	at sun.security.validator.Validator.validate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
	at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
	at microsoft.exchange.webservices.data.EwsX509TrustManager.checkServerTrusted(Unknown Source)
	... 29 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
	at java.security.cert.CertPathBuilder.build(Unknown Source)
	... 35 more
```

Ich komme einfach nicht weiter. Falls mir jemand einen Tipp hat, wäre ichs sehr dankbar.

MFG Mops


----------



## FArt (12. Apr 2011)

Nur bezogen auf den Fehler: es wird versucht eine sichere Verbindung mit dem Server aufzubauen, aber du vertraust dem Zertifikat des Servers nicht. 
Importiere das Zertifiakt in deinen cert-Store bzw. (wenn der Server ein echtes Zertifikat hat) sorge dafür, das das Zertifikat des Trustcenters in deinem cert-Store enthalten ist.

Wenn jetzt viele Fragezeichen bei dir auftauchen, dann schaue erst mal, ob du nicht unverschlüsselt auf den Server zugreifen kannst oder ob du nicht (Forensuche) versuchen möchtests, einach blind allen Zertifkation zu vertrauen.


----------



## MopsdeBops (12. Apr 2011)

Das Zertifikat habe ich bereits in den Keystore per Keytool importiert. Auch auf meinem Computer ist das Zertifikat installiert. Wenn du mit cert-Store etwas anderes als den Keystore meinst, müsstest du mir dies kurz erklären. Dies ist mein erster Kontakt mit dem Thema Sichere Verbindungen in Java. Daher auch keine Erfahrung


----------



## FArt (12. Apr 2011)

Wäre sinnvoll gewesen, das zu erwähnen ;-)

Und wird der keystore auch hergenommen? Hast du die Properties entsprechend gesetzt bzw. hast du (wenn das Property nicht gesetzt ist) das Zertifikat in den Default-Keystore der JRE gelegt?

Wenn ja: google mal nach java ssl debug... da gibt es noch ein paar Systemproperties, wenn man die setzt bekommt man eine Menge Logausgaben, die den ganzen SSL Verbindungsversuch beschreiben... inklusive Handshake usw.... da sieht man dann eine genauere Fehlermeldung.


----------



## MopsdeBops (12. Apr 2011)

Habe beide Varianten versucht, einmal ins Default-Keystorefile und einmal ein neues erstellt und mit 
	
	
	
	





```
System.setProperty("javax.net.ssl.trustStore", "zert.keystore");
```
 referenziert. Beides wirkungslos.

Werde nun einmal SSL-Debug versuchen. Vielen Dank schon mal für deine Hilfe 

//Edit

Als ich heute Morgen wieder an meinen Arbeitsplatz sitze, gab mir Java erstaunlicherweise eine komplett andere Fehlermeldung.


```
13.04.2011 09:09:27 org.apache.commons.httpclient.auth.AuthChallengeProcessor selectAuthScheme
INFO: NTLM authentication scheme selected
microsoft.exchange.webservices.data.ServiceVersionException: Exchange Server doesn't support the requested version.
	at microsoft.exchange.webservices.data.ServiceRequestBase.processWebException(Unknown Source)
	at microsoft.exchange.webservices.data.ServiceRequestBase.validateAndEmitRequest(Unknown Source)
	at microsoft.exchange.webservices.data.SimpleServiceRequestBase.internalExecute(Unknown Source)
	at microsoft.exchange.webservices.data.MultiResponseServiceRequest.execute(Unknown Source)
	at microsoft.exchange.webservices.data.ExchangeService.findItems(Unknown Source)
	at microsoft.exchange.webservices.data.ExchangeService.findItems(Unknown Source)
	at microsoft.exchange.webservices.data.ExchangeService.findItems(Unknown Source)
	at SI_Outlook.pageThroughEntireInbox(SI_Outlook.java:43)
	at SI_Outlook.main(SI_Outlook.java:20)
Exception in thread "main" java.lang.NullPointerException
	at SI_Outlook.pageThroughEntireInbox(SI_Outlook.java:49)
	at SI_Outlook.main(SI_Outlook.java:20)
```


----------



## FArt (13. Apr 2011)

Ganz so erstaunlich nicht... vermutlich erwartet der Server eine Authentifizierung über NTLM, evtl. über LDAP (vermutlich bis du an einer Domäne angemeldet)... LDAP kriegt man mit Java hin... NTLM ist Windows-eigen... das könnte schwieriger werden.

Evtl. hilft dir eine API wie SPNEGO weiter... sonst kann ich dir nur noch Google und evtl. Microsoft-Foren empfehlen...


----------



## AlexSpritze (14. Apr 2011)

Eine Alternative, aber total unsicher und wirklich nur zum Testen empfehlenswert, wäre, dass du einen DummyTrustManager und eine DummySSLSocketFactory benutzt. Die akzeptieren alle Zertifikate.

Schau mal hier: Kiran Thakkar's Blog: Dummny certificate authentication implementation


----------



## FArt (14. Apr 2011)

P.S.:
Die letzte Fehlermeldung könnte man auch so deuten, dass die Client-Library von der Version her nicht zu dem Server passt, die Authentifizierung aber schon erfolgreich vorgenommen wurde. Kann das sein?


----------



## MopsdeBops (14. Apr 2011)

Die Fehlermeldung könnte auch daher kommen, dass mein Java Programm auf einem Windows Server 2008 R2 läuft und unsere Exchange auf Windows Server 2008. Daher könnte es sein, dass die NTLM Authentifierierung auf dem R2 eine neure Version ist. Ich werde nun dem einmal nachgehen.

Danke für eure Tipps

//Edit

Bin wieder einen Schritt weiter gekommen. Habe nun folgendes gemacht:


```
ExchangeService service = new ExchangeService (ExchangeVersion.Exchange2007_SP1);
```

Somit erhalte ich "nur" noch diese Fehlermeldung.


```
org.apache.commons.httpclient.auth.AuthChallengeProcessor selectAuthScheme
INFO: NTLM authentication scheme selected
```

Doch hier komme ich wieder nicht weiter.


----------



## MopsdeBops (19. Apr 2011)

Falls mir noch jemand einen Tipps hätte, wäre ich sehr froh. Denn ich bekomme diesen Error einfach nicht weg.


----------



## AlexSpritze (19. Apr 2011)

MopsdeBops hat gesagt.:


> ```
> ExchangeService service = new ExchangeService (ExchangeVersion.Exchange2007_SP1);
> ```
> 
> ...



Woran machst du fest, dass diese INFO-Log-Ausgabe eine Fehlermeldung ist? Hast du noch mehr Ausgaben dazu?


----------



## MopsdeBops (19. Apr 2011)

Nein, diese zwei Zeilen sind meine einzige Ausgabe. Allerdings ist es meiner Meinung nach ein Fehler, da er ja sonst die Nachricht verschicken würde.


```
public static void Senden(ExchangeService service) {
		EmailMessage msg;
		try { 
			msg = new EmailMessage(service);
			msg.setSubject("Hello world!"); 
			msg.setBody(MessageBody.getMessageBodyFromText("Sent using the EWS Managed API."));
			msg.getToRecipients().add("pascal.grotz@bdo.ch");
			msg.send();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
```

Der Fehler tritt bei Zeile 8 dieses Code-Stückes auf. Weiter kommt er dann auch nicht. Wenn ich z.B. testweise ein System.out.print nach dem msg.send einfüge, führt er dies nicht aus.


----------



## AlexSpritze (19. Apr 2011)

Bleibt er in Zeile 8 komplett hängen? Kommt dann nichts mehr? Also weder der Stacktrace in Zeile 11 noch ein System.out.println("xx"); zwischen Zeile 12 und 13?


----------



## MopsdeBops (19. Apr 2011)

Hm hab jetzt nach Zeile 7, 8, 11 und 12 ein System.out.print gemacht. Zeile 7, 8 und 12 macht er, 11 nicht. Er geht also nicht so wie ich vermutet habe in den catch Block. Das heisst er hängt sich eigentlich nicht auf, aber die Nachricht sendet er trotzdem nicht.

//Edit
Ich glaubs ja nicht. Es geht. Naja bringt wohl doch was wenn man seine Arbeit aufschiebt. Das letzte mal als ich es getestet habe, kam er nur bis msg.send. Ein print danach hat er nicht gemacht. Heute geht es und ich gehe in meine Mailbox und siehe da. die Mails kamen an. Jetzt müsste ich es eigentlich nur noch schaffen diese Fehler/Info auszuschalten, damit es nicht ersichtlich ist. Danke für deine/eure Hilfe


----------

