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
Related
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!
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
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.
I'm making a whois in java for android to train about streams and tcp connections.
But I have a problem. I have a php script, I wrote some time ago and I´m trying to make the same in java.
this is my java code :
public String consultawhois(String domain,String tld)
{
String domquest = domain + "." + tld;
String resultado = "";
Socket theSocket;
String hostname = "whois.internic.net";
int port = 43;
try {
theSocket = new Socket(hostname, port, true);
Writer out = new OutputStreamWriter(theSocket.getOutputStream());
out.write(domquest + "\r\n");
out.flush();
DataInputStream theWhoisStream;
theWhoisStream = new DataInputStream(theSocket.getInputStream());
String s;
while ((s = theWhoisStream.readLine()) != null) {
resultado = resultado + s + "\n";
}
}
catch (IOException e) {
}
return resultado;
}
The answer of the server is not correct and I think the problem is that I'm sending a bad query. The query I send is "dominio.com\r\n" and in my php whois code, it works perfectly.
It seems that the DNS query matches multiple records. At least, that is how I interpret the response. In the returned reponse you should see the following line:
To single out one record, look it up with "xxx", where xxx is one of the
of the records displayed above. If the records are the same, look them up
with "=xxx" to receive a full display for each record.
So if you prepend the query with "=" it returns the data of that record only. The following worked for me.
public String consultawhois(String domain,String tld)
{
String domquest = domain + "." + tld;
String resultado = "";
Socket theSocket;
String hostname = "whois.internic.net";
int port = 43;
try {
theSocket = new Socket(hostname, port, true);
Writer out = new OutputStreamWriter(theSocket.getOutputStream());
out.write("="+domquest + "\r\n");
out.flush();
DataInputStream theWhoisStream;
theWhoisStream = new DataInputStream(theSocket.getInputStream());
String s;
while ((s = theWhoisStream.readLine()) != null) {
resultado = resultado + s + "\n";
}
}
catch (IOException e) {
}
return resultado;
}
One thing to consider: Use English for method names, variables, etc. instead of Spanish. It will make your code easier to read internationally. The programming language itself also uses English words. Try to avoid a strange mix of English and your native language.
The lookup for dominio.com results in three matches:
DOMINIO.COM.BR
DOMINIO.COM.ASCPROBIENESTARIDSS.COM
DOMINIO.COM
You should specify wich one you are interested in with the query.
=dominio.com<newline>
This will allways work, even cases where there are no multiple matches.
The Java application that I support is logging some details in a flat file. the problem I face some times is that, the entry is very low compared to the previous day. This entry is most essential because our reports are generated based on the file. I went thro code for writing I couldn't figure out any issues. the method which is writing is sync method.
Any suggestions? I can also provide the code for you is you may need?
public synchronized void log (String connID, String hotline, String callerType,
String cli, String lastMenu, String lastInput,
String status, String reason)
{
//String absoluteFP = LOG_LOC + ls + this.getFilename();
//PrintWriter pw = this.getPrintWriter(absoluteFP, true, true);
try
{
pw.print (this.getDateTime ()+ ","+connID +","+hotline+","+callerType+","+ cli+"," + lastMenu + "," + lastInput + "," + status + "," + reason);
//end 1006
pw.print (ls);
pw.flush ();
//pw.close();
}
catch (Exception e)
{
e.printStackTrace ();
return;
}
}
private synchronized PrintWriter getPrintWriter (String absoluteFileName,
boolean append, boolean autoFlush)
{
try
{
//set absolute filepath
File folder = new File (absoluteFileName).getParentFile ();//2009-01-23
File f = new File (absoluteFileName);
if (!folder.exists ())//2009-01-23
{
//System.out.println ("Call Detailed Record folder NOT FOUND! Creating a new);
folder.mkdirs ();
//System.out.println ("Configure log folder");
this.setHiddenFile (LOG_LOC);//set tmp directory to hidden folder
if (!f.exists ())
{
//System.out.println ("Creating a new Call Detailed Record...");//2009-01-23
f.createNewFile ();//2009-01-23
}
}
else
{
if (!f.exists ())
{
//System.out.println ("Creating a new Call Detailed Record...");//2009-01-23
f.createNewFile ();//2009-01-23
}
}
FileOutputStream tempFOS = new FileOutputStream (absoluteFileName, append);
if (tempFOS != null)
{
return new PrintWriter (tempFOS, autoFlush);
}
else
{
return null;
}
}
catch (Exception ex)
{
ex.printStackTrace ();
return null;
}
}
/**
* Set the given absolute file path as a hidden file.
* #param absoluteFile String
*/
private void setHiddenFile (String absoluteFile)
{
//set hidden file
//2009-01-22, KC
Runtime rt = Runtime.getRuntime ();
absoluteFile = absoluteFile.substring (0, absoluteFile.length () - 1);//2009-01-23
try
{
System.out.println (rt.exec ("attrib +H " + "\"" + absoluteFile + "\"").getInputStream ().toString ());
}
catch (IOException e)
{
e.printStackTrace ();
}
}
private String getDateTime ()
{
//2011-076-09, KC-format up to milliseconds to prevent duplicate PK in CDR table.
//return DateUtils.now ("yyyy/MM/dd HH:mm:ss");
return DateUtils.now ("yyyy/MM/dd HH:mm:ss:SSS");
//end 0609
}
private String getFilename ()
{
///return "CDR_" + port + ".dat";//2010-10-01
return port + ".dat";//2010-10-01
}
public void closePW ()
{
if (pw != null)
{
pw.close ();
}
}
You've created a FileOutputStream, but aren't closing that stream. Close that stream and try again. That might be causing the problem.
Messages are getting logged sometime because the garbage collector kicks in at some intervals and closes the FileOutStream. This then allows messages to be logged again. You're getting the unreachable error since you have a return statement in both the if & else blocks. You'll have to take the PrintWriter and FileOutStreamWriter out of the getPrintWriter put it where you usually call the getPrintWriter(). Then you'll be able to close the streams correctly. getPrintWriter should only ensure file exists, so rename it to ensureFileExistance
If you can use Apache Common IO, try this:
public synchronized void log(String connID, String hotline, String callerType,
String cli, String lastMenu, String lastInput,
String status, String reason) {
String absoluteFP = LOG_LOC + ls + this.getFilename();
File file = new File(absoluteFP);
String message = this.getDateTime() + "," + connID + "," + hotline + "," + callerType + "," + cli + "," + lastMenu + "," + lastInput + "," + status + "," + reason;
try {
// note that you must explicitly add new line character if you want the line to end with newline
FileUtils.write(file, message + "\n", "UTF-8", true);
} catch (IOException ex) {
ex.printStackTrace ();
}
}
In Common IO 2.1, you can append a file that you are writting to. You can now get rid of the closePW and getPrintwriter and since the log method is synchronized, the file can be written one at a time from the same object. However, if you try to write the same file from different object at the same time, you will end up having overwritting problem.
Also, Common IO create the missing parent folder for you automatically. There is no need to explicitly check and create the folder.