javamail ignoring socks proxy - proxy

I've setup javamail to run through a socks proxy, but it won't go through it. I tried setting both mail.smtp.socks.host and mail.smtp.socks.port but it keeps going direct to the mail host. I feel like I'm missing something very basic. any help would be appreciated. Here's my properties:
props.setProperty("mail.smtp.host", this.smtpHost);
props.setProperty("mail.smtp.port", Integer.toString(this.smtpPort));
props.setProperty("mail.smtp.user", this.smtpUser);
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.smtp.starttls.enable", Boolean.toString(this.smtpTLS));
props.setProperty("mail.debug", "true");
if (this.useSOCKSProxy) {
logger.info("Using proxy");
props.setProperty("mail.smtp.socks.host", "127.0.0.1");
props.setProperty("mail.smtp.socks.port", Integer.toString(1080));
props.setProperty("mail.smtps.socks.host", this.socksProxyHost);
props.setProperty("mail.smtps.socks.port", Integer.toString(this.socksProxyPort));
props.setProperty("proxySet", "true");
props.setProperty("socksProxyHost", this.socksProxyHost);
props.setProperty("socksProxyPort", Integer.toString(this.socksProxyPort));
}
//Session session = Session.getInstance(props, new SmtpAuthenticator(this.smtpUser,this.smtpPassword));
Session session = Session.getDefaultInstance(props,
new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(smtpUser, smtpPassword);
}
});
//Session session = Session.getInstance(props, null);
session.setDebugOut(System.out);
session.setDebug(true);
//Transport tr = session.getTransport("smtp");
//tr.connect();
//tr.connect(this.smtpHost,this.smtpPort, this.smtpUser, this.smtpPassword);
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(this.smtpFrom));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
msg.setSubject(subject);
msg.setText(msgToSend.toString());
msg.saveChanges();
Transport.send(msg);

Start by fixing these common mistakes.
If that doesn't solve the problem, post the debugging output. Set the System property "mail.socket.debug" to "true" to get additional debugging output.
What version of JavaMail are you using? What JDK?
Unless "props" is coming from System.getProperties(), setting "socksProxyHost" has no effect. And if you do set it as a System property, you don't need the JavaMail socks properties.

You can try to figure out the correct combination of properties, including the common mistakes Bill mentioned, or you can also go the easy way and let Simple Java Mail (open source) figure it out for you:
Your example converted:
Mailer mailer = new Mailer(
new ServerConfig(smtpHost, smtpPort, smtpUser, smtpPassword),
TransportStrategy.SMTP_TLS,
this.useSOCKSProxy ? new ProxyConfig(socksProxyHost, socksProxyPort) : null
);
mailer.setDebug(true);
mailer.sendMail(new EmailBuilder()
.from(null, smtpForm)
.to(null, email)
.subject(subject)
.text(msgToSend.toString())
.build());
Note how you don't have to deal with any properties or JavaMail API anymore. You can also use authenticated proxy if you need.

Related

Upgrade code from org.eclipse.jetty.websocket.websocket-client to org.eclipse.jetty.websocket.websocket-jakarta-client

I have the following application code in an application that I would like to migrate to Spring3 in order to do so javax is replaced with jakarta.
Any one have any Idea how to migrate the following code:
// Let's create and start the Web Socket
//
// For internal test, we have a self-signed certificate. So we need to short cut certificate check.
// DO NOT DO THAT IN PRODUCTION!
boolean trustAll = (System.getProperty("com.graphql-java-generator.websocket.nosslcheck") != null);
org.eclipse.jetty.util.ssl.SslContextFactory.Client sslContextFactory = new org.eclipse.jetty.util.ssl.SslContextFactory.Client(
trustAll);
org.eclipse.jetty.client.HttpClient httpClient = new HttpClient(sslContextFactory);
org.eclipse.jetty.websocket.client.WebSocketClient wsClient = new WebSocketClient(httpClient);
SubscriptionClientWebSocket<R, T> subscriptionClientWebSocket = new SubscriptionClientWebSocket<R, T>(request,
subscriptionName, subscriptionCallback, subscriptionType, messageType,
graphQLRequest.getGraphQLObjectMapper());
URI uri = getWebSocketURI();
try {
wsClient.start();
org.eclipse.jetty.websocket.client.ClientUpgradeRequest clientUpgradeRequest = new ClientUpgradeRequest();
wsClient.connect(subscriptionClientWebSocket, uri, clientUpgradeRequest);
logger.debug("Connecting to {}", uri);
} catch (Exception e) {
String msg = "Error while opening the Web Socket connection to " + uri;
logger.error(msg);
throw new GraphQLRequestExecutionException(msg, e);
}
Having not found any documentation on how to proceed with this migration.
Tried using the JakartaWebSocketClientContainer but could not find how to use with an UpgradeRequest
Your code is not using javax.websocket, so there's nothing to upgrade.
The techniques you are using in your code to manage the SSL behavior is also not possible in either javax.websocket or jakarta.websocket (There is no API you can use to manage SSL/TLS in those)

How to ignore ssl on the microprofile rest client of quarkus

I'd like to ignore hostname verify and ignore client side certification validation while calling https rest api with RestClient
I cannot find a way to do it without using builder.
and seems that the hostverifier does not work at all.
public interface RHPAMRestClient {
// Starts a new process instance of a specified process.
#POST
#Path("/server/containers/{containerId}/processes/{processId}/instances")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
Object startProcess(#PathParam String containerId, #PathParam String processId, Object req);
}
RHPAMRestClient c = RestClientBuilder.newBuilder()
.baseUri(new URI(""))
.sslContext(SSLContexts.custom().loadTrustMaterial((chain, authType) -> true).build())
.hostnameVerifier((hostname, session) -> {
System.err.println("hostname verifier");
return true;
})
.build(RHPAMRestClient.class);
c.startProcess("", "", null);
It seems that there is a missconfiguration in Quarkus.
According to the documents, https://quarkus.io/guides/native-and-ssl, ssl support should be enabled when using quarkus-rest-client and the property quarkus.ssl.native should be true.
But it seems that it is false, this causes the org.jboss.resteasy.microprofile.client.RestClientBuilderImpl to override your settings
if (!SSL_ENABLED) {
resteasyClientBuilder.httpEngine((new URLConnectionClientEngineBuilder()).resteasyClientBuilder(resteasyClientBuilder).build());
resteasyClientBuilder.sslContext((SSLContext)null);
resteasyClientBuilder.trustStore((KeyStore)null);
resteasyClientBuilder.keyStore((KeyStore)null, "");
}
Forcing the property to true will magically make everything work as expected.
So, just set
quarkus.ssl.native=true in your application.properties file
(using Quarkus 1.3.1.Final)

Protecting webapi with IdentityServer and Autofac - can't get claims

I'm trying to protect my webapi with IdentityServer and OpenID Connect using Autofac. I'm using OWIN. But for some reason I can't get claims of the user. It seems that AccessTokenValidation is not triggered at all. That makes me think there is something wrong in the order of my declarations at my startup. Here is my startup.
public class Startup {
public void Configuration(IAppBuilder appBuilder) {
// Add authentication
this.AddAuthentication(appBuilder);
HttpConfiguration config = new HttpConfiguration();
var container = CreateAutofacContainer();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
WebApiConfig.Register(config);
config.EnsureInitialized();
// Register config - you can't add anything to pipeline after this
appBuilder.UseAutofacMiddleware(container);
appBuilder.UseAutofacWebApi(config);
appBuilder.UseWebApi(config);
}
private static IContainer CreateAutofacContainer() {
var autofacBuilder = new ContainerBuilder();
var assembly = Assembly.GetExecutingAssembly();
// Register your Web API controllers.
autofacBuilder.RegisterApiControllers(assembly);
// For general logging implementation
autofacBuilder.RegisterType<ConsoleLogger>().As<ILogger>();
// Create empty usage context to be filled in OWIN pipeline
IUsageContext usageContext = new RuntimeUsageContext();
autofacBuilder.RegisterInstance(usageContext).As<IUsageContext>().SingleInstance();
// We need to get usage context builded
autofacBuilder.RegisterType<OIDCUsageContextProvider>().InstancePerRequest();
var container = autofacBuilder.Build();
return container;
}
private void AddAuthentication(IAppBuilder app) {
var options = new IdentityServerBearerTokenAuthenticationOptions();
options.Authority = "MYAUTHORITY";
options.RequiredScopes = new[] { "openid", "profile", "email", "api" };
options.ValidationMode = ValidationMode.ValidationEndpoint;
app.UseIdentityServerBearerTokenAuthentication(options);
// Add local claims if needed
app.UseClaimsTransformation(incoming => {
// either add claims to incoming, or create new principal
var appPrincipal = new ClaimsPrincipal(incoming);
// incoming.Identities.First().AddClaim(new Claim("appSpecific", "some_value"));
return Task.FromResult(appPrincipal);
});
}
I'm using hybrid flow and api is called from SPA-application. I've verified (by calling my identity server's endpoint directly) that access token is valid and there are claims available. I also downloaded IdentityServer.AccessTokenValidation project and attached it as a reference. When I set some breakpoints to methods in that project, they never get called. That is why I think there is something wrong with my startup and OWIN pipeline.
I've declared UsageContext in my startup. It is a class I'm using to collect claims and some configuration settings - to be injected to actual controllers. I think it would be nice way to handle this, so in controllers there is always valid UsageContext available.
I've read a lot of samples and examples but still haven't found exactly same situation. I'll appreciate any attempts to point me into right direction.
Regards,
Borre
Could it be your registration of UsageContext as a Singleton? You mention this class contains claims, so this object should be resolved once pr http request - shouldn't it?
It turned out that there was some mysterious line in AccessTokenValidation - library that didn't work. I use that library to get claims. After changing the line everything seemed to work.
So basically my question is closed now and stuff works. But I'm still not totally convinced this is the right way to do this.
Thanks John for your comments!

JUnit needs special permissions?

My builds have been failing due to some of the integration tests I've been running. I'm stuck on why it won't work. Here is an example of the output:
I'm using Maven to first build, then it calls the JUnit tests. I'm seeing this 401 Unauthorized message in every single test, and I believe that's what is causing the builds to fail. In my mind, this means there are some permissions / authentication parameters that need to be set. Where would I go about doing this in JUnit?
Edit
#Test
public void testXmlHorsesNonRunners() throws Exception {
String servletUrl = SERVER + "sd/date/2013-01-13/horses/nonrunners";
Document results = issueRequest(servletUrl, APPLICATION_XML, false);
assertNotNull(results);
// debugDocument(results, "NonRunners");
String count = getXPathStringValue(
"string(count(hrdg:data/hrdg:meeting/hrdg:event/hrdg:nonrunner/hrdg:selection))",
results);
assertEquals("non runners", "45", count);
}
If you can, try to ignore the detail. Effectively, this is making a request. This is a sample of a test that uses the issueRequest method. This method is what makes HTTP requests. (This is a big method, which is why I didn't post it originally. I'll try to make it as readable as possible.
logger.info("Sending request: " + servletUrl);
HttpGet httpGet = null;
// InputStream is = null;
DefaultHttpClient httpclient = null;
try {
httpclient = new DefaultHttpClient();
doFormLogin(httpclient, servletUrl, acceptMime, isIrishUser);
httpGet = new HttpGet(servletUrl);
httpGet.addHeader("accept", acceptMime);
// but more importantly now add the user agent header
setUserAgent(httpGet, acceptMime);
logger.info("executing request" + httpGet.getRequestLine());
// Execute the request
HttpResponse response = httpclient.execute(httpGet);
// Examine the response status
StatusLine statusLine = response.getStatusLine();
logger.info(statusLine);
switch (statusLine.getStatusCode()) {
case 401:
throw new HttpResponseException(statusLine.getStatusCode(),
"Unauthorized");
case 403:
throw new HttpResponseException(statusLine.getStatusCode(),
"Forbidden");
case 404:
throw new HttpResponseException(statusLine.getStatusCode(),
"Not Found");
default:
if (300 < statusLine.getStatusCode()) {
throw new HttpResponseException(statusLine.getStatusCode(),
"Unexpected Error");
}
}
// Get hold of the response entity
HttpEntity entity = response.getEntity();
Document doc = null;
if (entity != null) {
InputStream instream = entity.getContent();
try {
// debugContent(instream);
doc = documentBuilder.parse(instream);
} catch (IOException ex) {
// In case of an IOException the connection will be released
// back to the connection manager automatically
throw ex;
} catch (RuntimeException ex) {
// In case of an unexpected exception you may want to abort
// the HTTP request in order to shut down the underlying
// connection and release it back to the connection manager.
httpGet.abort();
throw ex;
} finally {
// Closing the input stream will trigger connection release
instream.close();
}
}
return doc;
} finally {
// Release the connection.
closeConnection(httpclient);
}
I notice that your test output shows HTTP/1.1 500 Internal Server Error a couple of lines before the 401 error. I wonder if the root cause could be hiding in there. If I were you I'd try looking for more details about what error happened on the server at that point in the test, to see if it could be responsible for the authentication problem (maybe the failure is in a login controller of some sort, or is causing a session to be cancelled?)
Alternately: it looks like you're using the Apache HttpClient library to do the request, inside the issueRequest method. If you need to include authentication credentials in the request, that would be the code you'd need to change. Here's an example of doing HTTP Basic authentication in HttpClient, if that helps. (And more examples, if that one doesn't.)
(I'd second the observation that this problem probably isn't specific to JUnit. If you need to do more research, I'd suggest learning more about HttpClient, and about what this app expects the browser to send. One possibility: use something like Chrome Dev Tools to peek at your communications with the server when you do this manually, and see if there's anything important that the test isn't doing, or is doing differently.
Once you've figured out how to login, it might make sense to do it in a #Before method in your JUnit test.)
HTTP permission denied has nothing to do with JUnit. You probably need to set your credentials while making the request in the code itself. Show us some code.
Also, unit testing is not really meant to access the internet. Its purpose is for testing small, concise parts of your code which shouldn't rely on any external factors. Integration tests should cover that.
If you can, try to mock your network requests using EasyMock or PowerMock and make them return a resource you would load from your local resources folder (e.g. test/resources).

Changing mail configuration in runtime

I've just started to investigate grails framework and first task I'm trying to resolve is sending email. Basic tutorial and community answers provided lot of information for quick start, and yes I've created simple app with possibility to send email. But, next point of my investigation was changing mail configuration in runtime. So, first my configuration in Config.grovy was
grails {
mail {
host = ""
port = 0
username = ""
password = ""
props = [""]
}
}
with values, and all worked corectlly, after that I've tried to re-config it
like that
grailsApplication.config.grails.mail.host = "smtp.gmail.com"
grailsApplication.config.grails.mail.port = 465
grailsApplication.config.grails.mail.username = ""
from controller, and found that mail is sending from old adress, after debugs I've found that there are auto-wired instances in mail plugins like mailSender and one obvious solution is recreate mailSender and re-set it, but judging to Spring singleton policy it will be hard solution, so, My question Are there possibilities to re-configure mail in runtime without class-reloading ?
Thanks.
Fixed using re-init mailsender instance but waiting for other solutions, Thanks
mailSender.setHost("smtp.gmail.com")
mailSender.setPort(465)
mailSender.setJavaMailProperties(new Properties() {
{
put("mail.smtp.auth", "true");
put("mail.smtp.socketFactory.port", "465");
put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
put("mail.smtp.socketFactory.fallback", "false");
}
})
try following way
sendMail {
mailSender.username = 'abc#gmail.com'
mailSender.password = "pwd"
to "nagaraj.s#hotmail.com"
subject "Hi"
message "Hi"
}

Resources