views:

1907

answers:

9

How do I open the default mail program with a Subject and Body in a cross-platform way?

Unfortunately, this is for a a client app written in Java, not a website.

I would like this to work in a cross-platform way (which means Windows and Mac, sorry Linux). I am happy to execute a VBScript in Windows, or AppleScript in OS X. But I have no idea what those scripts should contain. I would love to execute the user's default program vs. just searching for Outlook or whatever.

In OS X, I have tried executing the command:

open mailto:?subject=MySubject&body=TheBody

URL escaping is needed to replace spaces with %20.

Updated On Windows, you have to play all sorts of games to get start to run correctly. Here is the proper Java incantation:

class Win32 extends OS {
    public void email(String subject, String body) throws Exception {
        String cmd = "cmd.exe /c start \"\" \"" + formatMailto(subject, body) + "\"";
        Runtime.getRuntime().exec(cmd);
    }
}
+1  A: 

Mailto isn't a bad route to go. But as you mentioned, you'll need to make sure it is encoded correctly.

The main problem with using mailto is with breaking lines. Use %0A for carriage returns, %20 for spaces.

Also, keep in mind that the mailto is considered the same as a URL of sorts and therefore will have the same limitations for length. See http://support.microsoft.com/kb/208427, note the maximum URL length of 2083 characters. This is confirmed for mailto as well in this article: http://support.microsoft.com/kb/279460/en-us. Also, some mail clients can also have a limit (I believe older versions of Outlook Express had a limit of something much smaller like 483 characters or something. If you expect to have a longer string than that then you'll need to look at alternatives.

BTW, you shouldn't have to resort to kicking out a script to do that as long as you can shell out a command from Java (I don't know if you can since I don't do Java).

Ryan Farley
+1  A: 

Check out Getting More From 'mailto'.
It has some good info on escape codes/characters.

Covers the following:
1. Add a Subject Line
2. Send to Multiple Recipients
3. Combining Code
4. Write the Email

Not sure about how it performs in OSX but worth a shot.

David HAust
A: 

I have implemented this, and it works well on OS X. (Ryan's mention of the max URL length has not been codified.)

public void email(String subject, String body) throws Exception {
    String cmd = "open mailto:";        
    cmd += "?subject=" + urlEncode(subject);
    cmd += "&body=" + urlEncode(body);
    Runtime.getRuntime().exec(cmd);
}

private static String urlEncode(String s) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        char ch = s.charAt(i);
        if (Character.isLetterOrDigit(ch)) {
            sb.append(ch);
        }
        else {
            sb.append(String.format("%%%02X", (int)ch));
        }
    }
    return sb.toString();
}

I had to re-implement URLencode because Java's would use + for space and Mail took those literally. Haven't tested on Windows yet.

Frank Krueger
+2  A: 

I had to re-implement URLencode because Java's would use + for space and Mail took those literally.

I don't know if Java has some built-in method for urlencoding the string, but this link http://www.permadi.com/tutorial/urlEncoding/ shows some of the most common chars to encode:

;       %3B
?       %3F
/       %2F
:       %3A
#       %23
&       %24
=       %3D
+       %2B
$       %26
,       %2C
space   %20 or +
%       %25
<       %3C
>       %3E
~       %7E
%       %25
Ryan Farley
+2  A: 

start works fine in Windows (see below). I would use Java's built in UrlEscape then just run a second replacement for '+' characters.

start mailto:"?subject=My%20Subject&body=The%20Body"
travis
+1  A: 

I don't know if Java has some built-in method for urlencoding the string, but this link http://www.permadi.com/tutorial/urlEncoding/ shows some of the most common chars to encode:

For percent-encoding mailto URI hnames and hvalues, I use the rules at http://shadow2531.com/opera/testcases/mailto/modern_mailto_uri_scheme.html#encoding. Under http://shadow2531.com/opera/testcases/mailto/modern_mailto_uri_scheme.html#implementations, there's a Java example that may help.

Basically, I use:

private String encodex(final String s) {
    try {
        return java.net.URLEncoder.encode(s, "utf-8").replaceAll("\\+", "%20").replaceAll("\\%0A", "%0D%0A");
    } catch (Throwable x) {
        return s;
    }
}

The string that's passed in should be a string with \r\n, and stray \r already normalized to \n.

Also note that just returning the original string on an exception like above is only safe if the mailto URI argument you're passing on the command-line is properly escaped and quoted.

On windows that means:

  1. Quote the argument.
  2. Escape any " inside the quotes with \.
  3. Escape any \ that precede a " or the end of the string with \.

Also, on windows, if you're dealing with UTF-16 strings like in Java, you might want to use ShellExecuteW to "open" the mailto URI. If you don't and return s on an exception (where some hvalue isn't completely percent-encoded, you could end up narrowing some wide characters and losing information. But, not all mail clients accept unicode arguments, so ideally, you want to pass a properly percent-encoded-utf8 ascii argument with ShellExecute.

Like 'start', ShellExecute with "open" should open the mailto URI in the default client.

Not sure about other OS's.

Shadow2531
+1  A: 

Never use Runtime.exec(String) on Mac OS X or any other operating system. If you do that, you'll have to figure out how to properly quote all argument strings and so on; it's a pain and very error-prone.

Instead, use Runtime.exec(String[]) which takes an array of already-separated arguments. This is much more appropriate for virtually all uses.

Chris Hanson
+5  A: 

In Java 1.6 you have a stardard way to open the default mailer of the platform: the Desktop.mail(URI) method.The URI can be used to set all the fields of the mail (sender, recipients, body, subject). You can check a full example of desktop integration in Java 1.6 on Using the Desktop API in Java SE 6

rotabla
+1  A: 

any solution that would work on linux? We expect to have some users on unix/linux platforms ... I tried the OS X version with open and it doesn't work ...

Did you try Desktop.mail() like the accepted answer said?
Michael Myers