Login with domain/user/account not working with imap on exchange server using javamail - exchange-server

I'm trying to connect to an exchange mailserver (not sure what version) using javamail.
I have the username and password of an account that can impersonate all other users.
I'm trying to open the store of one of the users. (password unknown)
I did find this question How to use Javamail for accessing additional mailboxes (IMAP, Exchange 2010). It's using [domain]/[user]/[sharedaccount] as login.
The connection is made if I only use [domain]/[user], but with the name of the second account behind it [domain]/[user]/[impersonatedaccount] it won't work.
If I use the same credentials in Thunderbird it does make the connection.
Example:
domain: abc
known username with password: admin
mailbox to connect to: wverleur#abc.com (logs in with wverleur)
Working:
abc/admin
not working:
abc/admin/wverleur
credentials contains the following:
rootUrl: mailserver.abc.com
username: admin
password: password
domain: abc
impersonation: wverleur
getImapUsername() returns domain/username/impersonation
My connection code:
private void login() throws MessagingException {
// connection properties
Properties properties = new Properties();
// TLS & SSL
properties.setProperty("mail.imaps.starttls.enable", "true");
properties.setProperty("mail.imaps.ssl.enable", "true");
properties.setProperty("mail.imaps.ssl.trust", credentials.getRootUrl()); // self signed certificate
// login settings
properties.setProperty("mail.imaps.auth.ntlm.disable", "true");
properties.setProperty("mail.imaps.auth.plain.disable", "true");
properties.setProperty("mail.imaps.auth.gssapi.disable", "true");
// retrieve a session
session = Session.getInstance(properties);
// retrieve and open a store
store = session.getStore("imap");
try {
store.connect(credentials.getRootUrl(), credentials.getImapUsername(), credentials.getPassword());
} catch (MessagingException messagingException) {
throw new MessagingException("Error in storeConnect: " + store.toString(),
messagingException);
}
}
Javamail Debug shows the following:
DEBUG IMAP: protocolConnect login, host=[rooturl], user=[domain]\[user]\[impersonate], password=<non-null>
Am I missing something?
Is it even possible at all?

As per request of Bill Shannon I hereby post my answer to the question:
I placed the required certificate in the cacerts file of Java (be sure that you know what you are doing)
I changed my properties to:
please note that they are now imap and not imaps
// TLS & SSL
properties.setProperty("mail.imap.starttls.enable", "true");
properties.setProperty("mail.imap.ssl.enable", "false"); // is now false
// removed the trust for ssl
// login settings
properties.setProperty("mail.imap.auth.ntlm.disable", "true");
properties.setProperty("mail.imap.auth.plain.disable", "true");
properties.setProperty("mail.imap.auth.gssapi.disable", "true");
properties.setProperty("mail.user", credentials.getImapUsername());
properties.setProperty("mail.host", credentials.getRootUrl());
And, for me, it works.
As stated before. This is a very server specific answer and question. I hope it can help other people in their effort to connect their program to their exchange server.
EDIT:
Due to the requirement for support of other mail-servers the code changed:
String protocol = "mail.imap";
switch (encryption){
case SSL:
protocol = protocol + "s";
properties.setProperty(protocol + ".starttls.enable", "false");
properties.setProperty(protocol + ".ssl.enable", "true");
break;
case TLS:
properties.setProperty(protocol + ".starttls.enable", "true");
properties.setProperty(protocol + ".ssl.enable", "false");
break;
case NONE:
properties.setProperty(protocol + ".starttls.enable", "false");
properties.setProperty(protocol + ".ssl.enable", "false");
break;
}
properties.setProperty(protocol + ".auth.ntlm.disable", "true");
properties.setProperty(protocol + ".auth.plain.disable", "true");
properties.setProperty(protocol + ".auth.gssapi.disable", "true");
// other properties you want to set
SSL uses the mail.imaps and TLS and NONE use the mail.imap

Related

Can't seem to send email with jhipster application

I'm trying to make a simple form that when submited sends and email to a fixed email.
I'm using spring and i've searched on how to configure the application.yml and i'm using the mailsend method that seems to have been generated with my jhipster application.
I've built my FE service to connect to the back end :
sendForm(): Observable<any>{
return this.http.post(SERVER_API_URL + 'api/sendForm', "");
}
i've built the onsubmit method to make the subscribe to the method above:
onSubmit() {
this.auth.sendForm().subscribe( data => {
console.log(data);
})
}
i've hard coded the mail resource just to mock an email to make sure its working:
#PostMapping("/sendForm")
public void sendForm() {
this.mailService.sendEmail("mymail#gmail.com","Header","texto",false,true);
}
the sendMail method that im sending the information for the mail submition is autogenerated and I believe it should be working
#Async
public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
isMultipart, isHtml, to, subject, content);
// Prepare message using a Spring helper
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name());
message.setTo(to);
message.setFrom(jHipsterProperties.getMail().getFrom());
message.setSubject(subject);
message.setText(content, isHtml);
javaMailSender.send(mimeMessage);
log.debug("Sent email to User '{}'", to);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn("Email could not be sent to user '{}'", to, e);
} else {
log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
}
}
}
and heres my application-dev.yml (i'm still on dev)
spring:
profiles:
active: dev
mail:
host: smtp.gmail.com
port: 587
username: gmailuserid#gmail.com #Replace this field with your Gmail username.
password: ************ #Replace this field with your Gmail password.
protocol: smtp
tls: true
properties.mail.smtp:
auth: true
starttls.enable: true
ssl.trust: smtp.gmail.com
the errors im getting goes as follows:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localh
ost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeo
ut -1;
All I expect is a mail with the mock i've used and I cant seem to be able to put this working.
I hope i've not made the post to long and that everything is well explained.
Thank you in advance for anyone willing to help
Apparently somewhy the properties-prod.yml wasnt being loaded to the server. I had to create a config file with all the configurations for it to work

Redirect HTTP requests to HTTPS in netty

I am modifying elasticsearch code to configure HTTPS without x-pack and reverse proxies.
I modified initchannel() method in the netty4HttpServerTransport file , https is working fine,but i want to redirect http to https..
The code is,
char[] password = "your5663".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("C:/OpenSSL-Win64/bin/keystore1.jks"),password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext .init( kmf.getKeyManagers(), tm, null);
SSLEngine sslengine = sslContext .createSSLEngine();
sslengine.setUseClientMode(false);
String[] DEFAULT_PROTOCOLS = { "TLSv1", "TLSv1.1", "TLSv1.2","TLSv1.3" };
String[] DEFAULT_CIPHERS = {"TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA"};
sslengine.setEnabledProtocols(DEFAULT_PROTOCOLS);
sslengine.setEnabledCipherSuites(DEFAULT_CIPHERS);
SslHandler sslHandler = new SslHandler(sslengine);
ch.pipeline().addLast("ssl", sslHandler);
ch.pipeline().addAfter("ssl","handshake",new StringEventHandler());
How do i make http to https redirect in this code.
Redirect works on the payload (http) level, not ssl transport level. You would need to listen on both protocol (http and https) and on the http channel you can respond with redirect status code. Long story short - there is no direct place on in your code you can do that.
Very commonly a proxy server is used for this task. I am not sure if you can do it in elasticsearch, you can try to configure a filter servlet to check the protocol respond with a redirect. This may be helpful https://github.com/elastic/elasticsearch-transport-wares
Another fact - if the redirect is for service clients (not browser based ui), the clients may/will consider a redirect response an an error response. Depending on your environment - maybe you can just expose the ssl endpoint (no redirects) and clients will have to comply
Netty has a built in handler for this, OptionalSslHandler.
You put it at the front of your pipeline and it detects if the message is encrypted or not. If it is, then the message will be sent onto the normal SSL pipeline, if not then you can specify somewhere else to send it, e.g. to a 301 redirect to https.
You could either use this Netty version or make your own handler that does something similar.
However, to use the Netty version you will need to refactor slightly to produce a Netty SslContext io.netty.handler.ssl.SslContext, instead of an SSLEngine.
Something like this:
char[] password = "your5663".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("C:/OpenSSL-Win64/bin/keystore1.jks"),password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
SslContext sslContext = SslContextBuilder.forServer(keyManagerFactory).build();
ch.pipeline().addLast("ssl", sslHandler);
// this is an imaginary handler you create that sends HTTP a 301 to HTTPS
// non-SSL can be detected easily because there is no SslHandler on this channel
ch.pipeline().addLast("redirectHandler", new RedirectHandler());
ch.pipeline().addLast("handshake",new StringEventHandler());

Getting Error - javax.net.ssl.SSLHandshakeException: Server chose TLSv1, but that protocol version is not enabled or not supported by the client

Getting Error - javax.net.ssl.SSLHandshakeException: Server chose TLSv1, but that protocol version is not enabled or not supported by the client when making a call to a secured webservice.
Appended the following option to the JAVA_OPTIONS variable in the mydomain\bin\ setDomainEnv.cmd as advised in the oracle site but same issue.
-Dweblogic.security.SSL.protocolVersion=TLS1
Java client code :
File pKeyFile = new File("C:\\myJKS.jks");
if (pKeyFile.exists() && !pKeyFile.isDirectory()) {
logger.debug("JKS file exists, and it is a file");
}
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(pKeyFile.toString()),
pKeyPassword.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
**SSLContext context = SSLContext.getInstance("TLSv1.1");**
context.init(keyManagerFactory.getKeyManagers(), null,
new SecureRandom());
sockFact = context.getSocketFactory();
if(sockFact == null){
logger.debug("SocketFactory is null");
throw new NullPointerException("socketFactory == null");
}
Client Env - JDK version: 7, Application server:Weblogic.
Trying to make it work from couple of days, but no luck.

Search Guard With Spring Data ES

I followed steps mentioned here to secure my local ES installation using SearchGuard (no tag exist for it on SO). Now, it is reachable via Postman only through basic authentication with username password as default admin/admin.
Now, I need to allow my Spring Data ES project to be able to access this ES installation.
I tried:
Settings esSettings = Settings.settingsBuilder()
.put("path.home", ".")
.put("cluster.name", clusterName)
.put("searchguard.ssl.transport.enabled", true)
.put("searchguard.ssl.transport.keystore_filepath", "kirk-keystore.jks")
.put("searchguard.ssl.transport.truststore_filepath", "truststore.jks")
.put("searchguard.ssl.transport.enforce_hostname_verification", false)
.put("request.headers.sg.impersonate.as", "admin")
.build();
TransportClient client = TransportClient.builder().settings(esSettings)
.build().addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(elasticsearchHost), elasticsearchPort));
client.prepareGet().putHeader("Authorization", "Basic " + Base64.encodeBase64("admin:admin".getBytes())).get();
return client;
Added header as suggested here.
But all I get is:
[elasticsearch[Meteorite][generic][T#3]] INFO org.elasticsearch.client.transport -
[Meteorite] failed to get node info for {#transport#-1}{127.0.0.1}{127.0.0.1:9300}, disconnecting...
org.elasticsearch.transport.NodeDisconnectedException: [][127.0.0.1:9300][cluster:monitor/nodes/liveness] disconnected
I need to get and post new data in ES (2.4.4).

How to validate credentials in EWS Java API

I am using EWSJavaAPI 1.1.5. I am trying to login with invalid credentials, but I don't get any exceptions.
Please advise how to detect and handle invalid login.
Here is my code:
String host = "myhost";
ExchangeService service = null;
try {
service = new ExchangeService();
ExchangeCredentials credentials = new WebCredentials("wrongemail",
"wrongpass");
service.setCredentials(credentials);
service.setUrl(new java.net.URI("https://" + host
+ "/EWS/Exchange.asmx"));
} catch (Exception e) {
e.printStackTrace();
}
Found it, i had to bind the service to a folder:
Folder.bind(service, WellKnownFolderName.Inbox);
and if the credentials are wrong, HttpErrorException is thrown.

Resources