Can you please tell me how to use SubethaSmtp library? I just want to retrieve the mails from my Gmail inbox and display them or one of them in console window.
I studied most of the API doc but I'm not being able to put the pieces together to get the things working.
Can you please tell me about a working example?
I wrote this code to build a grails application. You may find some bad code habits but it's okey for a sample application.
Here is the code in src/groovy folder :
class MessageHandlerFactoryImpl implements MessageHandlerFactory {
#Override
MessageHandler create(MessageContext ctx) {
return new MessageHandlerImpl(ctx)
}
}
class MessageHandlerImpl implements MessageHandler {
MessageContext context
MessageHandlerImpl(MessageContext context) {
this.context = context
}
#Override
void from(String from) {
println "FROM: ${from}"
}
#Override
void recipient(String recipient) {
println "RECIPIENT: ${recipient}"
}
#Override
void data(InputStream data) {
println "DATA"
println "-------------------"
BufferedReader reader = new BufferedReader(new InputStreamReader(data))
StringBuilder builder = new StringBuilder()
String line
while ((line = reader.readLine()) != null) {
builder.append(line + "\n")
}
println builder.toString()
}
#Override
void done() {
println "DONE"
}
}
class SimpleMessageListenerImpl implements SimpleMessageListener {
#Override
boolean accept(String from, String recipient) {
println "accept: ${from} \n>> ${recipient}"
return false
}
#Override
void deliver(String from, String recipient, InputStream data) {
try {
println "deliver: ${from} \n>> ${recipient} \n>>> ${data.read()}"
} catch (TooMuchDataException e) {
println "TooMuchDataException: ${e.message}"
} catch (IOException e) {
println "IOException: ${e.message}"
}
}
}
class UsernamePasswordValidatorImpl implements UsernamePasswordValidator {
#Override
void login(String username, String password) {
try {
println "LOGIN:::::::"
} catch(LoginFailedException e) {
println "LoginFailedException: ${e.message}"
}
}
}
And here is my controller code.
class SubethaController {
SMTPServer server
def index() {
MessageHandlerFactoryImpl factory = new MessageHandlerFactoryImpl()
server = new SMTPServer(factory)
server.hostName = "imap.gmail.com"
server.port = 993
server.authenticationHandlerFactory = new EasyAuthenticationHandlerFactory(new UsernamePasswordValidatorImpl())
server.start()
}
def stop() {
server?.stop()
}
Wiser wiser
def wiser() {
server = new SMTPServer(new SimpleMessageListenerAdapter(new SimpleMessageListenerImpl()))
server.start()
wiser = new Wiser()
wiser.setPort(25001)
wiser.start()
for (WiserMessage message : wiser.getMessages())
{
String eSender = message.getEnvelopeSender()
String eReceiver = message.getEnvelopeReceiver()
println ">>>>>>>message.getMimeMessage ${message.getMimeMessage()}"
}
}
def wiserS() {
wiser?.stop()
}
}
Thanks.
Okey... I found the answer... The code is well written and is working fine. I just didn't know how to send messages to listening smtp server on the port. I just used telnet program and sent emails to the smtp server running on localhost. Now I will create DNS mapping to make it work on the Internet.
Thanks Nicolás for showing your interest.
Related
Total Kerberos and Active Directory newb here trying to get a very small sample working.
Found a Java Active Directory JAAS example onLine and here is the code.
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
public class ActiveDirectoryValidator
{
private static final String USERNAME = "FOO";
private static final String PASSWORD = "BAR";
private ActiveDirectoryValidator()
{
}
public boolean validateUser(String userName, String password)
{
try
{
LoginContext lc = null;
ADCallbackHandler ch = new ADCallbackHandler();
ch.setUserId(userName);
ch.setPassword(password);
lc = new LoginContext("JaasConfig", ch);
lc.login();
return true;
}
catch (LoginException le)
{
System.err.println("Authentication failed:");
System.err.println(" " + le.getMessage());
return false;
}
catch (NullPointerException e)
{
System.err.println("Authentication failed:");
System.err.println(" " + e.getMessage());
return false;
}
}
public static void main(String[] args) throws Exception
{
ActiveDirectoryValidator validateUser = new ActiveDirectoryValidator();
if (validateUser.validateUser(USERNAME, PASSWORD))
{
System.out.print("Authentication Successful");
}
else
{
System.out.print("Authentication Failed");
}
}
}
and
import javax.security.auth.callback.*;
import java.io.IOException;
public class ADCallbackHandler implements CallbackHandler
{
private String ADUserId;
private char[] ADPassword;
public void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof NameCallback)
{
NameCallback cb = (NameCallback)callbacks[i];
cb.setName(ADUserId);
}
else if (callbacks[i] instanceof PasswordCallback)
{
PasswordCallback cb = (PasswordCallback)callbacks[i];
cb.setPassword(ADPassword);
}
else
{
throw new UnsupportedCallbackException(callbacks[i]);
}
}
}
public void setUserId(String userid)
{
ADUserId = userid;
}
public void setPassword(String password)
{
ADPassword = new char[password.length()];
password.getChars(0, ADPassword.length, ADPassword, 0);
}
}
Where does the Active Directory Server name go?
I would not expect it to be in the jaas.conf file as I have seen other programs set it via the UI interface and the jaas.conf file never changes.
What am I missing?
Is this example showing something totally different?
Moved my test to a Linux machine and ultimately found 2 missing components.
1 - when executing, I needed to include the
-Djava.security.auth.login.config=mylocation/jaas.conf
2 - I needed to edit the following file to include my Active Directory information
/etc/krb5.conf
After making the necessary references and entries, it worked.
I'm stuck with CompletableFuture exception handling
My logic is to send email and save status of this action. If send email throws exception I need to save the status with the exception message.
public interface MyService {
CompletableFuture<Boolean> sendEmail(String content, String address);
CompletableFuture<StatusResult> saveStatus(String content, String address);}
Processor class currently has this code. It works properly, but is not graceful as for me. How can we get rid of error local field that we use to share state between stages?
#Component
public class Processor {
private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class);
#Autowired
private MyService myService;
public CompletableFuture<StatusResult> sendEmail(String content, String address) {
AtomicReference<String> error = new AtomicReference<>();// just to forward error message from exception block to thenCompose
return myService.sendEmail(content, address).exceptionally(e -> {
LOGGER.error("Exception during send email ", e);
error.set(e.getMessage());
return null;
}).thenCompose(x -> {
if (x == null) {
return myService.saveStatus(error.get(), address);
} else {
return myService.saveStatus("good", address);
}
});
}
}
Looks like handle method should help, but it returns CompletableFuture of CompletableFuture
public CompletableFuture<StatusResult> sendEmail(String content, String address) {
CompletableFuture<CompletableFuture<StatusResult>> result = myService.sendEmail(content, address).handle((x, e) -> {
if (e != null) {
LOGGER.error("Exception during send email ", e);
return myService.saveStatus("error", address);
} else {
return myService.saveStatus("good", address);
}
});
}
You can convert to your save status upfront.
public CompletableFuture<String> sendEmail(String content, String address) {
return myService.sendEmail(content, address)
.thenApply(b -> "good")
.exceptionally(Throwable::getMessage)
.thenCompose(status -> myService.saveStatus(status, address));
}
Another working solution :
public CompletableFuture<StatusResult> sendEmailAndSaveStatus(String content, String address) {
CompletableFuture<Boolean> sendEmail = myService.sendEmail(content, address);
CompletableFuture<StatusResult> result = new CompletableFuture<>();
sendEmail.exceptionally(e -> {
LOGGER.info("Exception during send email ");
myService.saveStatus(e.getMessage(), address).thenApply(x -> result.complete(x));
return false;
});
sendEmail.thenCompose(x -> myService.saveStatus("good", address)).thenApply(x -> result.complete(x));
return result;
}
I am testing nv-websocket-client on Android using Android Studio 2.2.3/JRE1.8.0_76.
My code is basically the same as the echo sample application in the README.md file. The class runs fine under Java 8 Update 111, but fails under Android Studio. I walked the code in debug mode and it failed at:
Source:com/neovisionaries/ws/client/Address.java:36
InetSocketAddress toInetSocketAddress()
{
return new InetSocketAddress(mHost, mPort);// mHost = "echo.websocket.org", mPort = 80.
}
Error message in Android Studio:
Method threw 'java.lang.NullPointerException' exception. Cannot evaluate java.net.InetSocketAddress.toString()
Any idea what I did wrong here?
My Test Class:
public class TestWS {
private String m_msg;
private String m_uriStr; // = "ws://echo.websocket.org";
private static final int TIMEOUT = 5000;
public TestWS(String uriStr) {
m_uriStr = uriStr;
m_msg = "";
}
public void RunTest() {
try {
// Connect to the echo server.
WebSocket ws = connect();
ws.sendText("This is a test");
Thread.sleep(1000); // Make sure m_msg is updated before function return.
ws.disconnect();
}
catch(Exception ex)
{
m_msg += "Exception: " + ex.getMessage(); // getMessage() returns null.
}
}
private WebSocket connect() throws IOException, WebSocketException
{
return new WebSocketFactory()
.setConnectionTimeout(TIMEOUT)
.createSocket(m_uriStr)
.addListener(new WebSocketAdapter() {
// A text message arrived from the server.
#Override
public void onTextMessage(WebSocket websocket, String message) {
m_msg += "Echo: " + message;
}
})
.addExtension(WebSocketExtension.PERMESSAGE_DEFLATE)
.connect(); // <= failed in this function.
}
public String GetMsg(){
return m_msg;
}
}
I have builded a Java server that listen on a port (6666). Now, i need to connect to this server with a LDAP Browser (I use Softerra). The connection is done, but i have to know when there is an LDAP bind/search, and i have no idea of how to do that.
Here is the code of my server (feel free to tell me if it's not very clear/good, i'm quite new to Java Prog.):
package net.nantes.littleldap;
import java.net.*;
import java.io.*;
public class Serverside {
public static void main(String[] args) {
ServerSocket socketserver ;
Socket socket ;
BufferedReader in;
PrintWriter out;
try {
Authenticate auth = new Authenticate();
socketserver = new ServerSocket(6666);
System.out.println("Le serveur est à l'écoute du port "+socketserver.getLocalPort());
auth.connect();
socket = socketserver.accept();
String inputLine = new String();
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
System.out.println("Connecté au serveur");
while ((inputLine = in.readLine()) != null){
System.out.println(inputLine);
out = new PrintWriter(socket.getOutputStream());
out.println("Connection réussie");
out.flush();
}
socket.close();
socketserver.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
Sorry, the message are in french, but it's not really important. I think maybe I could do something with InputLine (when I print it, it returns some String relative to LDAP, but i can be hard to parse).
So, any idea ? Thanks a lot !
I would strongly recommend you utilize either JNDI or one of the LDAP SDKs that are available.
We like: https://www.unboundid.com/products/ldap-sdk/
-jim
In addition to listening to the port, your server has to "understand" the LDAP protocol.
I use the OpenDS LDAP SDK (http://www.middleware.vt.edu/pubs/opends-sdk-0.9.0/).
Code is like this
public class MyLdapServer
implements ServerConnectionFactory<LDAPClientContext, Integer> {
private LDAPListener listener;
public void init() {
try {
listener = new LDAPListener(1389, this);
} catch (IOException e) {
logger.error("error opening LDAP listener", e);
}
}
public void destroy() {
listener.close();
}
#Override
public ServerConnection<Integer> handleAccept(LDAPClientContext context)
throws ErrorResultException {
if (logger.isDebugEnabled())
logger.debug("ldap connection from: " + context.getPeerAddress());
IncomingLdapConnection ilc = new IncomingLdapConnection(context);
return ilc;
}
private static Logger logger = LoggerFactory.getLogger(MyLdapServer.class);
}
The IncomingLdapConnection allows you to handle the LDAP operations:
public class IncomingLdapConnection
implements ServerConnection<Integer> {
public void handleBind(Integer ctx, int version, BindRequest request,
ResultHandler<? super BindResult> resultHandler,
IntermediateResponseHandler intermediateResponseHandler)
throws UnsupportedOperationException {
if (request.getAuthenticationType() != -128) {
logger.warn("LDAP BIND: unsupported authentication type: " + request.getAuthenticationType());
resultHandler.handleResult(Responses.newBindResult(ResultCode.AUTH_METHOD_NOT_SUPPORTED));
return;
}
String bindName = request.getName();
if (bindName.length() > 0) {
if (request instanceof GenericBindRequest) {
GenericBindRequest bindRequest = (GenericBindRequest)request;
String userName = parseUidDn(bindName);
if (userName == null) {
// manche LDAP-Clients senden keine DN, sondern direkt den Namen
userName = bindName;
}
String password = bindRequest.getAuthenticationValue().toString();
logger.debug("LDAP BIND: non-anonymous bind, user = " + userName);
anonymous = false;
} else {
logger.warn("LDAP BIND: non-anonymous bind, but unsupported request");
resultHandler.handleResult(Responses.newBindResult(ResultCode.AUTH_METHOD_NOT_SUPPORTED));
return;
}
} else {
logger.debug("LDAP BIND: anonymous bind");
anonymous = true;
}
boolean success = anonymous;
if (!anonymous) {
// authenticate user, set "success"
}
if (success)
resultHandler.handleResult(Responses.newBindResult(ResultCode.SUCCESS));
else
resultHandler.handleResult(Responses.newBindResult(ResultCode.INVALID_CREDENTIALS));
authenticated = success;
}
EDIT:
OpenDS Code for answering to LDAP search requests
public void handleSearch(Integer ctx, SearchRequest request,
SearchResultHandler responseHandler, IntermediateResponseHandler intermediateResponseHandler)
throws UnsupportedOperationException {
if (request.getScope() == SearchScope.BASE_OBJECT && request.getName().isRootDN()) {
logger.debug("LDAP Search: BASE_OBJECT");
responseHandler.handleEntry(Responses.newSearchResultEntry(rootEntry));
} else {
// do the search
// parameters: request.getName(), request.getScope(), request.getFilter()
}
responseHandler.handleResult(Responses.newResult(ResultCode.SUCCESS));
}
Check out the UnboundID LDAP SDK and some sample code.
EDIT:
I would not recommend the use of JNDI:
JNDI uses a deprecated configuration
JNDI has software defects
JNDI does not fully support LDAP standards
see also
LDAP: Programming Practices
I have developed an app in phonegap (html5, JQuery, JS) and I want to develop a plugin to print to a BT printer.
I download printer manufacturer's SDK and I imported the appropriate .jar file to my project with all the methods I will need in my project.
I create the below plugin, following an internet tutorial, in order to call from JS the JAVA methods from printer manufacturers SDK.
JS
var HelloPlugin = {
callNativeFunction: function (success, fail, resultType) {
return cordova.exec(success, fail, "com.tricedesigns.HelloPlugin", "nativeAction", [resultType]);
}
};
JAVA
package com.tricedesigns;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import com.starmicronics.stario.StarIOPort;
import com.starmicronics.stario.StarIOPortException;
import com.starmicronics.stario.StarPrinterStatus;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.util.Log;
public class HelloPlugin extends Plugin {
public static final String NATIVE_ACTION_STRING="nativeAction";
public static final String SUCCESS_PARAMETER="success";
#Override
public PluginResult execute(String action, JSONArray data, String callbackId) {
if (NATIVE_ACTION_STRING.equals(action)) {
this.ctx.runOnUiThread(new Runnable()
{
public void run()
{
String resultType = null;
StarIOPort port = null;
String message = null;
String portName = "bt:";
String portSettings = "mini";
byte[] texttoprint = new byte[]{0x1b, 0x40, 0x1b,0x74,0x0D,(byte) 0x91,(byte) 0x92,(byte) 0x93,(byte) 0x94,(byte) 0x95,(byte) 0x96,(byte) 0x97,(byte) 0x98,(byte) 0x99,0x0A,0x0A,0x0A,0x0A,0x0A};
try
{
port = StarIOPort.getPort(portName, portSettings, 10000);
try
{
Thread.sleep(500);
}
catch(InterruptedException e) {}
}
catch (StarIOPortException e)
{
Builder dialog = new AlertDialog.Builder((Context)ctx);
dialog.setNegativeButton("Ok", null);
AlertDialog alert = dialog.create();
alert.setTitle("Failure");
alert.setMessage("Failed to connect to printer");
alert.show();
}
finally
{
if(port != null)
{
try
{
StarIOPort.releasePort(port);
} catch (StarIOPortException e) {}
}
}
}
});
}
return null;
}
}
Printer command manual say:
GetPort is what you will be using to “open” the port to the printer. Using one of the valid
inputs for portName and portSettings as mentioned previously before this, you can pass your
connection string into the StarIO class so that it will correctly set its private variables.
//The following would be an actual usage of getPort:
StarIOPort port = null;
try
{
port = StarIOPort.getPort(portName, portSettings, 10000);
}
catch (StarIOPortException e)
{
//There was an error opening the port
}
StarIOPort is a part of StarIO and this will allow you to create a “port” handle. The
above example shows the port being created and set to null then being assigned the actual
port hook on the following line that contains getPort.
Always use a try, catch when using getPort. If the port cannot be opened
because of connection problems, your program will crash unless you use a
try, catch like the above example.
Is the above syntax of plugin correct or is there something i missed?
When I run my app always i receive "Failed to connect to printer" even if the printer is on and connected to my device.
try this:
public PluginResult execute(String action, JSONArray data, String callbackId) {
PluginResult result = null;
if (PRINT_ACTION.equals(action))
{
JSONObject printerStatusJSON = new JSONObject();
try {
Boolean prtStatus = false;
String msg ="Failed to connect to printer";
String portName = "";
ArrayList<PortInfo> dvss = PrinterFunctions.getDevices();//BTPortList = StarIOPort.searchPrinter("BT:");
if (Looper.myLooper() == null) {
Looper.prepare();
}
for(PortInfo dvs : dvss) {
Map<String, String> st = PrinterFunctions.CheckStatus(dvs.getPortName(), "mini");//port = StarIOPort.getPort(portName, portSettings, 1000);
if(st.get("status") == "true") {
prtStatus = true;
portName = st.get("portName");
break;
}
msg = st.get("message");
}
if(!portName.isEmpty()) {
PrinterFunctions.PrintSomething(portName, data);//MiniPrinterFunctions.PrintSampleReceipt(String portName, JSONArray data);
}
printerStatusJSON.put("prtStatus", prtStatus);
printerStatusJSON.put("message", msg);
result = new PluginResult(Status.OK, printerStatusJSON);
}
catch (Exception jsonEx) {
Log.e("YourApplicationName", "Got JSON Exception " + jsonEx.getMessage());
jsonEx.printStackTrace();
result = new PluginResult(Status.JSON_EXCEPTION);
}
}
else {
result = new PluginResult(Status.INVALID_ACTION);
Log.e(TAG, "Invalid action : " + action);
}
return result;
}