Send Email from Java with default mail client - java

I have Java code, that should send emails.
The default mail client opens correctly and also the receiver as well as the subject is smoothly set, but the body is not set. No body is shown. Here's my code:
public void emailOhneStandort() throws URISyntaxException {
try {
composeEmail("benjamin.koubik#daimler.com", "Thanks for the snippet!",
"Hello Raffael,\r\nthis mail was initiated by Java.");
} catch (Exception err) {
err.printStackTrace();
}
System.out.println("Done!");
}
public static void composeEmail(String receiver, String subject, String body) throws Exception {
String mailto = "mailTo:" + receiver;
mailto += "?subject=" + uriEncode(subject);
mailto += "&body=" + uriEncode(body);
String cmd = "";
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
cmd = "cmd.exe /c start " + mailto;
} else if (os.contains("osx")) {
cmd = "open " + mailto;
} else if (os.contains("nix") || os.contains("aix") || os.contains("nux")) {
cmd = "xdg-open " + mailto;
}
// Call default mail client with paramters
Runtime.getRuntime().exec(cmd);
}
private static String uriEncode(String in) {
String out = new String();
for (char ch : in.toCharArray()) {
out += Character.isLetterOrDigit(ch) ? ch : String.format("%%%02X", (int) ch);
}
return out;
}

From trying on Windows, I find that I need to escape the & with a ^.
So, if I do this:
C:\>start mailto:test#example.com?subject=foo&body=bar
I get the following error:
'body' is not recognized as an internal or external command, operable program or batch file.
and my email client opens with the subject populated but not the body.
If I do this:
C:\>start mailto:test#example.com?subject=foo^&body=bar
then it works as expected.
I daresay the equivalent will happen in other environments, but can't test that at the moment.
For the record, it seems worth adding that this is a bit of an odd requirement, and if it's something you're doing for production code that will be used by anyone other than yourself, it's probably not the best approach!

Related

Javamail : Setting timeout for folder.search

I have been using Javamail (version 1.6.4) for a while now, mostly for event listening, mail parsing and copy/delete mails (from Exchnage using IMAPS). Lately i was asked to use sub-folders for a business usecase. When moving mail from the Inbox folder to a sub-folder the UID changes so i'm using folder.search() in order to find the new UID. This works most of the times but sometimes the search goes indefnitley (or its duration is very long) which may lag the entire application.
Is there a way to set a timeout (or other way to throw an exception if it runs too long) for folder.search()?
I understood that imap search is done on the server side but i just wanted to validate. this is an example of how i send search to the server (we can assume subject is unique for this discussion):
private static String findMailIdBySubject(String mailbox, String srcFolder, String subject) {
Folder srcFolderObj = null;
boolean wasConnectionEstablished = connectToMail(mailbox);
if (!wasConnectionEstablished) {
return null;
}
// get mailboxStore object
MailboxStore mailboxStore = MailBoxStoreList.getMailStoreByMailBox(mailbox);
try {
// Open inbox folder to get messages metadata
srcFolderObj = mailboxStore.getStore().getFolder(srcFolder);
srcFolderObj.open(Folder.READ_WRITE);
// create search Term
SearchTerm term = new SearchTerm() {
private static final long serialVersionUID = 7L;
#Override
public boolean match(Message message) {
try {
String mailSubject = message.getSubject();
if (mailSubject == null) {
mailSubject = "";
}
if (mailSubject.equals(subject)) {
return true;
}
} catch (MessagingException ex) {
log.error("Failed to search for mail with mailbox: " + mailbox + " in folder: " + srcFolder
+ " subject: " + subject + " Error: " + ExceptionUtils.getStackTrace(ex));
}
return false;
}
};
// search for the relevant message
Message[] messages = srcFolderObj.search(term);
UIDFolder uf = (UIDFolder) srcFolderObj;
return String.valueOf(uf.getUID(messages[0]));
} catch (Exception e) {
log.error("Subject: Failed to find id of mail in mailbox " + mailbox + " in folder " + srcFolder
+ " , Error: " + ExceptionUtils.getStackTrace(e));
return null;
} finally {
try {
if (srcFolderObj != null && srcFolderObj.isOpen()) {
srcFolderObj.close();
}
} catch (Exception e) {
}
}
}
i also tried to replace SearchTerm override with the following but performance was the same:
SearchTerm searchTerm = new SubjectTerm(subject);
Thanks in advance!

Commands sent from Java client side gets chopped into multiple parts before received by C++ server side

I'm trying to send commands from my client side, implemented with Java, to the server side, implemented using C++, through TCP connection. The server-side code is given and tested, so I'm fairly certain that the parsing of the command is not the problem. But when I try to send String commands from the Java side, the server side receives multiple packages sometimes so it does not get parsed correctly. Since the server only executes a command when it ends with a new line symbol, the first part of the command gets discarded and an unknown message error is thrown.
I'm using the DataOutputStream for the Java side, and using DataOutputStream.writeBytes(String s) to write my command, and using a BufferedReader to read the message returned by the server.
I'm able to test the server by using telnet to connect to the server without launching Java side code. From telnet, I can successfully send multiple commands and they get parsed correctly. However, when I try to send commands from Java, they get broken up into pieces. The first command is always fine, which is always "add_server 3\n", and the second command, which is "dec_dimmer\n" gets chopped up into "d" and "ec_dimmer\n" and all the subsequent commands in a similar fashion.
Here's how the send command part is implemented:
DataOutputStream outToServer = null;
try {
outToServer = new DataOutputStream(mClientSocket.getOutputStream());
} catch(IOException e) {
e.printStackTrace();
}
try {
String cmd = command + '\n';
if(mDebug) {
System.out.println("Sending Command: " + cmd);
}
outToServer.writeBytes(cmd);
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader inFromServer = null;
try {
inFromServer = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
} catch(IOException e) {
e.printStackTrace();
}
String jsonOutput = null;
try {
jsonOutput = inFromServer.readLine();
} catch(IOException e) {
e.printStackTrace();
}
if(mDebug) {
System.out.println("FROM SERVER: " + jsonOutput);
}
return jsonOutput;
In addition, the exact same client has been implemented in c++ before and is working perfectly fine. The following function is the send command function from the c++ version of the client:
std::string SwimClient::sendCommand(const char* command) {
if (!socket.is_open()) {
throw std::runtime_error("socket is closed");
}
boost::system::error_code ignored_error;
cout << "sending command = " << command << endl;
boost::asio::write(socket, boost::asio::buffer(command, strlen(command)),
boost::asio::transfer_all(), ignored_error);
vector<char> buffer(128);
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buffer), error);
if (error)
throw boost::system::system_error(error);
string reply(buffer.data(), len);
if (reply.compare(0, 6, "error:") == 0) {
// trim strings
size_t last = reply.length() - 1;
while (isspace(reply.at(last))) {
reply.erase(last--);
}
string cmd(command);
last = cmd.length() - 1;
while (isspace(cmd.at(last))) {
cmd.erase(last--);
}
throw std::logic_error(reply + "(cmd " + cmd + ')');
}
return reply;
}

OutputStream.write only writing part of a String in Java

I'm working on a Java-based IRC client as a way to learn both Java and more about writing networked applications.
The client I've designed mostly works, except when I post a message. The message goes through alright, but only up to the first space. I've tried everything: I've dumped my text into a StringArray, into a byte array, in a loop. But each time, only the first word of the intended message gets posted.
Here's the part of the code that I believe is relevant, although I'm happy to post the entire code if necessary (it's only a few hundred lines, and I can cut out the unimportant parts):
public void send(String msg) throws UnsupportedEncodingException {
if ( ! msg.startsWith("/")) {
msg = ("PRIVMSG " + chan + " " + msg);
// DEBUG confirm that msg == command+chan+userText
System.out.println(msg);
} else if ( msg.toUpperCase().startsWith("/JOIN ")) {
// System.out.println("\nJoin mode");
chan = msg.substring(6);
msg = (msg.toUpperCase().substring(1) + "\r\n");
} else { // some other command
msg = (msg.toUpperCase().substring(1) + "\r\n");
}
System.out.println(msg);
ostream.print(msg + " \r\n"); // doesn't work
ostream.flush();
}
}
I have also tried this sort of thing:
CRS = msg.split("\\s+");
CharSequence chars = msg;
ostream.printf( "%s,\r\n", msg); // doesn't work
ostream.print( String.join(" ", CRS) + "\r\n" ); // nope
And this:
ostream.append(chars);
ostream.append("\r\n"); // nope
I've also tried all of the above with byte arrays.
This sort of thing, however, does work:
// this, however, works as expected
void pong(String ping) {
String msg = "PONG " + ping;
byte[] bs = null;
bs = (msg.substring(1) + "\r\n").getBytes();
try {
ostream.write(bs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I've also tried changing my OutputStream object (the connection to the IRC server) to a PrintStream. Same results.
What about OutputStream am I not comprehending?
The IRC protocol requires you to escape messages that contain spaces with a preceding colon (":"). I think your code actually works, you've just not implemented the IRC protocol correctly.
Try making your PRIVMSG command:
msg = ("PRIVMSG " + chan + " :" + msg);
Only the first word is appearing because the IRC server ignores the trailing content after the first space. A valid message should look like:
PRIVMSG #target :Hello, world

Trying to run multiple python scripts in Java

I have a python script called generate_graphs.py that generates graphs with python libraries. The graphs are trends we show to customers with our internal data.
I'm trying to run the script from Java, but I don't see any evidence of it running. There is no evidence of logs showing it ran, but I'm not sure if this is the script itself not running, or if its the implementation of the exec method.
The script inserts data into a database as part of its process, and nothing is inserted. However, when running the script command from command line separately, the script runs perfectly fine.
Here's the execute command implementation used from mkyong.com:
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
Here's the method that is called about 40 times in total, roughly once per 3 seconds:
/**
* Runs a command to execute the generate_graph python script
*
* #param server_id
*/
public void generateGraph(List<String> list_name, String server_id, String email_addr, String report_str) {
String generate_graph_cmd = "python2.7 generate_graphs.py --l '%s' --server_name '%s' --email_addr '%s' --report_string '%s' --debug";
//We want to remove the lm_ part from the server name
String server_name = server_id.split("_")[1].replace("\'", "");
String list_name_str = "";
for (String name : list_name){
list_name_str += name + ",";
}
//We want to remove the trailing comma left by the above loop
if (list_name_str.length() > 1){
list_name_str = list_name_str.substring(0, list_name_str.length() - 1);
}
generate_graph_cmd = String.format(generate_graph_cmd, list_name_str, server_name, email_addr, report_str);
try {
System.out.println("[Py Output] " + executeCommand(generate_graph_cmd));
} catch (Exception e) {
e.printStackTrace();
}
log.debug("Generating graph with the following parameters:\nserver_id: " + server_id + "\nlist_id: " + list_name.toString());
}
I only see the log.debug portion of the output in the logs. Am I calling it too quickly/incorrectly? Any help would be appreciated, thanks!
I ended up using Apache Common's Exec to solve my issue.

Start user's standard mail client with attachment pre-attached

I'm looking for a way that my application can call the user's standard mail application (e.g. Outlook, Thunderbird, etc.). And give it an recipient address, the email text and an attachment.
So, basically the standard email application should pop up have the email ready for me (with recipient, text and attachment) and all that is left to do for me is pressing "send" in my outlook, thunderbird etc.
I've been googling for a while now, but I couldn't find a real solution.
I've been looking into mapi a bit but it seems like 1. it's deprecated and 2. it's mainly built for outlook.
Any help/suggestions/solutions greatly appreciated!
Edit: I have seen the question Start Mail-Client with Attachment but no working answer was provided there and also the question is more than 3 years old.
Edit: Other languages would be ok, too. Has to work on Windows XP, Vista, 7, 8 (both 32 and 64 bit)
UPDATE: It seems to be more difficult than I have thought it to be.
I've been looking into JMAPI, which apparently only works for 32bit Systems.
I've also seen the solutions on codeproject.org (here and here), but I somehow couldn't get them to work.
Now I'm trying to do it with command line:
1. Read user's default mail client
2. Call a batch file according to the email client. (Yes you have to write a batch file for every common mail client.
Example for outlook:
"outlook.exe" /a "F:\test.png" /m "test.test#test.test&cc=test#test.test&subject=subject123&body=Hello, how are you%%3F%%0D%%0Anew line"
--> see my provided answer for futher info on that method
So...
After days of research I gave up to get a general solution.
I came up with a solution working at least for the two most common clients (Thunderbird & Outlook)
My solution is basically calling the application from command line.
For those interested, here is my solution: (I haven't tested it cross platform - works on my old XP laptop though)
import java.io.IOException;
/*
:: Punctuation Hexadecimal equivalent
:: ----------------------------------------------
:: Space ( ) %20
:: Comma (,) %2C
:: Question mark (?) %3F
:: Period (.) %2E
:: Exclamation point (!) %21
:: Colon (:) %3A
:: Semicolon (;) %3B
:: Line feed %0A --> New line %0D%0A
:: Line break (ENTER key) %0D --> New line %0D%0A
*/
public class Main {
static String test = "hi";
private static String attachment;
private static String to;
private static String cc;
private static String subject;
private static String body;
public static void main (String[] args){
attachment = "F:\\pietquest.png";
to = "test#test.de";
cc = "a.b#c.de";
subject = "TestSubject 123";
body = "Hi, what\'s going on%0D%0Anew line";
body = replace(body);
subject = replace(subject);
String[] value = WindowsRegistry.readRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Clients\\Mail", "");
if (value[10].contains("Thunderbird")){
System.out.println("Thunderbird");
String[] pfad = WindowsRegistry.readRegistry("HKEY_LOCAL_MACHINE\\SOFTWARE\\Clients\\Mail\\Mozilla Thunderbird\\shell\\open\\command", "");
String Pfad = pfad[10] + " " + pfad[11];
String argument = Pfad + " /compose \"to=" + to + ",cc=" + cc + ",subject=" + subject + ",body=" + body + ",attachment=" + attachment + "\"";
// System.out.println(argument);
try {
Runtime.getRuntime().exec(argument);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if (value[10].contains("Outlook")){
System.out.println("Outlook");
String[] pfad = WindowsRegistry.readRegistry(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Clients\\Mail\\Microsoft Outlook\\shell\\open\\command", "");
String Pfad = pfad[10];
String argument = Pfad + " /a " + attachment + " /m \"" + to
+ "&cc=" + cc + "&subject=" + subject + "&body=" + body + "\"";
// System.out.println(argument);
try {
Runtime.getRuntime().exec(argument);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static String replace(String toReplace){
toReplace = toReplace.replace(" ", "%20");
toReplace = toReplace.replace(",", "%2C");
toReplace = toReplace.replace("?", "%3F");
toReplace = toReplace.replace(".", "%2E");
toReplace = toReplace.replace("!", "%21");
toReplace = toReplace.replace(":", "%3A");
toReplace = toReplace.replace(";", "%3B");
return toReplace;
}
}
and this is the Windows Registry Class: (got that from here)
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
public class WindowsRegistry {
/**
*
* #param location path in the registry
* #param key registry key
* #return registry value or null if not found
*/
public static final String[] readRegistry(String location, String key){
try {
// Run reg query, then read output with StreamReader (internal class)
Process process = Runtime.getRuntime().exec("reg query " +
'"'+ location);
StreamReader reader = new StreamReader(process.getInputStream());
reader.start();
process.waitFor();
reader.join();
// Parse out the value
String[] parsed = reader.getResult().split("\\s+");
if (parsed.length > 1) {
return parsed;
}
} catch (Exception e) {}
return null;
}
static class StreamReader extends Thread {
private InputStream is;
private StringWriter sw= new StringWriter();
public StreamReader(InputStream is) {
this.is = is;
}
public void run() {
try {
int c;
while ((c = is.read()) != -1)
sw.write(c);
} catch (IOException e) {
}
}
public String getResult() {
return sw.toString();
}
}
you can use C#: Example C# or java: Example Java
EDIT
You can use Boost for ssl and send email via smtp

Categories

Resources