Download attachments using Java Mail - java

Now that I`ve downloaded all the messages, and store them to
Message[] temp;
How do I get the list of attachments for each of those messages to
List<File> attachments;
Note: no thirdparty libs, please, just JavaMail.

Without exception handling, but here goes:
List<File> attachments = new ArrayList<File>();
for (Message message : temp) {
Multipart multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()) &&
StringUtils.isBlank(bodyPart.getFileName())) {
continue; // dealing with attachments only
}
InputStream is = bodyPart.getInputStream();
// -- EDIT -- SECURITY ISSUE --
// do not do this in production code -- a malicious email can easily contain this filename: "../etc/passwd", or any other path: They can overwrite _ANY_ file on the system that this code has write access to!
// File f = new File("/tmp/" + bodyPart.getFileName());
FileOutputStream fos = new FileOutputStream(f);
byte[] buf = new byte[4096];
int bytesRead;
while((bytesRead = is.read(buf))!=-1) {
fos.write(buf, 0, bytesRead);
}
fos.close();
attachments.add(f);
}
}

Question is very old, but maybe it will help someone. I would like to expand David Rabinowitz`s answer.
if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition()))
should not return all atachments as you expect, because you can have mail where mixed part is without defined disposition.
----boundary_328630_1e15ac03-e817-4763-af99-d4b23cfdb600
Content-Type: application/octet-stream;
name="00000000009661222736_236225959_20130731-7.txt"
Content-Transfer-Encoding: base64
so in this case, you can also check for filename. Like this:
if (!Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) && StringUtils.isBlank(part.getFileName())) {...}
EDIT
there is whole working code using condition descibed above.. Because each part can encapsulate another parts and attachment should be nested in, recursion is used to traverse through all parts
public List<InputStream> getAttachments(Message message) throws Exception {
Object content = message.getContent();
if (content instanceof String)
return null;
if (content instanceof Multipart) {
Multipart multipart = (Multipart) content;
List<InputStream> result = new ArrayList<InputStream>();
for (int i = 0; i < multipart.getCount(); i++) {
result.addAll(getAttachments(multipart.getBodyPart(i)));
}
return result;
}
return null;
}
private List<InputStream> getAttachments(BodyPart part) throws Exception {
List<InputStream> result = new ArrayList<InputStream>();
Object content = part.getContent();
if (content instanceof InputStream || content instanceof String) {
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) || StringUtils.isNotBlank(part.getFileName())) {
result.add(part.getInputStream());
return result;
} else {
return new ArrayList<InputStream>();
}
}
if (content instanceof Multipart) {
Multipart multipart = (Multipart) content;
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
result.addAll(getAttachments(bodyPart));
}
}
return result;
}

Some time saver for the code where you save the attachment file :
with javax mail version 1.4 and after , you can say
// SECURITY LEAK - do not do this! Do not trust the 'getFileName' input. Imagine it is: "../etc/passwd", for example.
// bodyPart.saveFile("/tmp/" + bodyPart.getFileName());
instead of
InputStream is = bodyPart.getInputStream();
File f = new File("/tmp/" + bodyPart.getFileName());
FileOutputStream fos = new FileOutputStream(f);
byte[] buf = new byte[4096];
int bytesRead;
while((bytesRead = is.read(buf))!=-1) {
fos.write(buf, 0, bytesRead);
}
fos.close();

You can simply use Apache Commons Mail API MimeMessageParser - getAttachmentList() along Commons IO and Commons Lang.
MimeMessageParser parser = ....
parser.parse();
for(DataSource dataSource : parser.getAttachmentList()) {
if (StringUtils.isNotBlank(dataSource.getName())) {}
//use apache commons IOUtils to save attachments
IOUtils.copy(dataSource.getInputStream(), ..dataSource.getName()...)
} else {
//handle how you would want attachments without file names
//ex. mails within emails have no file name
}
}

Returns list of body parts with attachments.
#Throws(Exception::class)
fun getAttachments(message: Message): List<BodyPart>{
val content = message.content
if (content is String) return ArrayList<BodyPart>()
if (content is Multipart) {
val result: MutableList<BodyPart> = ArrayList<BodyPart>()
for (i in 0 until content.count) {
result.addAll(getAttachments(content.getBodyPart(i)))
}
return result
}
return ArrayList<BodyPart>()
}
#Throws(Exception::class)
private fun getAttachments(part: BodyPart): List<BodyPart> {
val result: MutableList<BodyPart> = ArrayList<BodyPart>()
if (Part.ATTACHMENT == part.disposition && !part.fileName.isNullOrBlank()){
result.add(part)
}
val content = part.content
if (content is Multipart) {
for (i in 0 until (content ).count) {
val bodyPart = content.getBodyPart(i)
result.addAll(getAttachments(bodyPart)!!)
}
}
return result
}

Related

Send Mail With Multiple Attachments (Size < 4 MB) Using Graph API Version 2.3.2

I'm trying to send mail with multiple attachments (Sum of size is < 4MB) using Graph API version 2.3.2. Please find the following code snippet for the same.
public static void main(String[] a){
try {
TestBase testBase = new TestBase();
Message message = getMessage();
message.hasAttachments = true;
AttachmentCollectionResponse response = new AttachmentCollectionResponse();
response.value = Arrays.asList(
getFileAttachment("/home/user/Downloads/3MBPDF.pdf"),
getFileAttachment("/home/user/Downloads/20KBPDF.pdf"));
message.attachments = new AttachmentCollectionPage(response, null);
testBase.graphClient.me().sendMail(message, true).buildRequest().post();
}catch (Exception e){
e.printStackTrace();
}
}
private static Message getMessage() {
Message message = new Message();
java.util.List<String> emails = Arrays.asList("vivektest#gmail.com");
java.util.List<Recipient> listReceipient = new ArrayList<>();
for(String email : emails) {
EmailAddress emailAddress = new EmailAddress();
emailAddress.address = email;
Recipient recipient = new Recipient();
recipient.emailAddress = emailAddress;
listReceipient.add(recipient);
}
message.body = getItemBody();
message.toRecipients = listReceipient;
message.subject = "Test Message";
message.id = "1234";
return message;
}
private static ItemBody getItemBody() {
ItemBody itemBody = new ItemBody();
itemBody.content = "<html><head></head><body> test body </body></html>";
itemBody.contentType = BodyType.HTML;
return itemBody;
}
private static FileAttachment getFileAttachment(String path) throws Exception{
FileAttachment fileAttachment = new FileAttachment();
File pdfFile = new File(path);
InputStream fileStream = new FileInputStream(pdfFile);
fileAttachment.name = pdfFile.getName();
fileAttachment.contentBytes = getByteArray(fileStream);
fileAttachment.oDataType = "#microsoft.graph.fileAttachment";
fileAttachment.size = Math.toIntExact((pdfFile.length() / 1024) / 1024);
System.out.println("FileSize::: "+fileAttachment.size);
fileAttachment.id="521";
return fileAttachment;
}
public static byte[] getByteArray(InputStream in) {
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return buffer.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I've double check the size of the files.
3MBPDF.pdf = 3.6 MB
20KBPDF.pdf = 20 KB
Total size is not greater then 4 MB but still its returning following error
SEVERE: Throwable detail:
com.microsoft.graph.http.GraphServiceException: Error code: BadRequest
Error message: The maximum request length supported is 4MB.
POST https://graph.microsoft.com/v1.0/me/microsoft.graph.sendMail
SdkVersion : graph-java/v2.3.2 Authorization : [PII_REDACTED]
{"saveToSentItems":true,"message":{"body":{"conten[...]
413 : Request Entity Too Large [...]
The above code snippet I've captured from the test case of msgraph-sdk-java repo.
Please help me to send email with size less then 4 MB.
Thanks
Your request is exceeding the maximum 4MB limit for Graph requests as:
1st pdf :3.6MB
space usage increase for 1st PDF due to base64 encoding : 2.2MB
2nd pdf: 20kB
space usage increase for 2nd PDF: 7kB
JSON payload: probably a few kBs
the total being well over the 4MB limit. You need to use large attachment uploads for that PDF.

Apache Camel - exchange.getIn().getBody(ZipFile.class) returns NULL but exchange.getOut().setBody(zipfile) works fine

I'm trying to zip a message (String) into a zip file, and then set it as the body of the exchange object in Apache Camel, so that one of the downstream services (also using Apache Camel) is able to extract the zip file using the exchange.getIn().getBody() method.
The first part is good, I'm able to set a zip file to the body, but when I try to retrieve this on the other side of the queue (Active MQ), the exchange.getIn().getBody(ZipFile.class) returns null. In fact, the body itself is null.
Why would that be?
I have tried sending a normal String in the body, and that worked fine. The File (ZipFile) doesn't set, wonder why.
Here are snippets of the code -
Route -
from(some_route)
.bean(SomeClass.class, "zipAndSend")
.to("activemq:queue:" + somequeue)
To zip a file -
public void zipAndSend(Exchange exchange) throws Exception {
String incomingMessage;
try {
incomingMessage = exchange.getIn().getBody().toString();
File file = ZipUtil.createFile(incomingMessage);
String zipFilePath = file.getPath().replace(".xml", ".zip");
ZipFile zipFile = ZipUtil.zipFile(file.getPath(), zipFilePath);
exchange.getOut().setHeader("Compressed", "Y");
exchange.getOut().setHeader("ZipFilePath", zipFilePath);
exchange.getOut().setBody(zipFile);
//the body is set correctly here, so far so good
} catch (Exception e) {
e.printStackTrace(); //other operations
}
}
public static File createFile(String incomingMessaage) {
String fileName = "C:\\Project\\ZipUnzipTest\\incoming.xml";
File file = new File(fileName);
try {
FileUtils.writeStringToFile(file, incomingMessaage);
} catch (Exception e) {
//log.error("Error in Writing Message into file " + fileName, e);
String errorFile = fileName.replace("work", "error");
}
return file;
}
Over in the other service (end of the queue), I am overriding the process() method like below, to be able to extract the message (String) back from the file inside the zipped file.
public void process(Exchange exchange) throws WorkflowDBException,
Exception {
try {
ZipFile zipFile = exchange.getIn().getBody(ZipFile.class); //NPE as body is null
String zipFilePath = exchange.getIn().getHeader("ZipFilePath").toString();
File inFile = ZipUtil.unzipFile(zipFile, "C:\\Project\\ZipUnzipTest\\Output\\WF", true);
String incomingMessage;
incomingMessage = FileUtils.readFileToString(inFile, "UTF-8");
} catch (Exception e) {e.printStackTrace();}
}
Dependencies -
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
I expect the content of the body to be same in the in and out space. Alas, it isn't.
It turns out, Camel (amongst other frameworks) handles bytes[] rather well. I converted the ZipFile into a byte array, and used it to set the body of the exchange object.
incomingMessage = exchange.getIn().getBody().toString();
File file = ZipUtil.createFile(incomingMessage);
String zipFilePath = file.getPath().replace(".xml", ".zip");
ZipFile zipFile = ZipUtil.zipFile(file.getPath(), zipFilePath);
messageData = FileUtils.readFileToByteArray(new File(zipFilePath));
exchange.getOut().setHeader("Compressed", "Y");
exchange.getOut().setHeader("ZipFilePath", zipFilePath);
exchange.getOut().setBody(messageData);
And while reading it, I used the ZipInputStream to get the Zip Entry from the ByteArrayInputStream.
byte [] bytes = exchange.getIn().getBody(byte[].class);
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(bytes));
try {
StringBuilder s = new StringBuilder();
StringBuilder temp = new StringBuilder();
byte[] buffer = new byte[1024];
int read = 0;
ZipEntry entry;
while ((entry = zipStream.getNextEntry())!= null) {
while ((read = zipStream.read(buffer, 0, 1024)) >= 0) {
s.append(new String(buffer, 0, read));
}
temp = temp.append(s);
s.setLength(0);
}
return temp.toString();
} catch (Exception e) {
e.printStackTrace();
}
Yes, that's it.
Still open to other ways to solve this :)

Deflate in Java - Inflate in Javascript

I'm sending compressed data from a java app via nodejs to a webpage. The data is compressed with the java deflater and base64 encoded. On the webpage I'm trying to inflate the data with https://github.com/dankogai/js-deflate, but it does not work (empty result). Am I missing something?
Java side:
private String compress(String s) {
DeflaterOutputStream def = null;
String compressed = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
// create deflater without header
def = new DeflaterOutputStream(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
def.write(s.getBytes());
def.close();
compressed = Base64.encodeBase64String(out.toByteArray());
System.out.println(compressed);
} catch(Exception e) {
Log.c(TAG, "could not compress data: " + e);
}
return compressed;
}
Javascript side:
var data = RawDeflate.inflate(Base64.fromBase64(compressed));
Try this:
public static String compressAndEncodeString(String str) {
DeflaterOutputStream def = null;
String compressed = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
// create deflater without header
def = new DeflaterOutputStream(out, new Deflater(Deflater.BEST_COMPRESSION, true));
def.write(str.getBytes());
def.close();
compressed = Base64.encodeToString(out.toByteArray(), Base64.DEFAULT);
} catch(Exception e) {
Log.e(TAG, "could not compress data: " + e);
}
return compressed;
}
I ran into the same problem. The js-deflate project inflater appears broken. I found it would work on a short input but fail on a long input (e.g., lorem ipsum as test data).
A better option turned out to be zlib.js.
Here is how I'm using it to inflate in Javascript a JSON object that is generated, compressed, and base64 encoded on the server:
var base64toBinary = function (base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array( len );
for (var i = 0; i < len; i++) {
var ascii = binary_string.charCodeAt(i);
bytes[i] = ascii;
}
return bytes.buffer;
}
var utf8ToString = function (uintArray) {
var encodedString = String.fromCharCode.apply(null, uintArray),
decodedString = decodeURIComponent(escape(encodedString));
return decodedString;
}
var object = JSON.parse(utf8ToString(
new Zlib.RawInflate(base64toBinary(base64StringFromServer)).decompress()));
(FYI, the helper functions are derived from other stackoverflow answers).

Best view to display images and html content in android

*I am working on an application which can read emails. I am using textview / edittext to display the mails. Right now I am able to fetch the email content as string and display it.
But Which is the best view to display emails with html content and images??
Please help me out.
Thank you :)
Edited:
I used webview as suggested by S.O. friends(thanks to #Andro Selva, #CFlex).
But I am facing a problem, Its displaying the email's body twice! :(
Once as a text/plain and again as a Text/html.
I have tried following codes to load webview.
webViewBody.loadData(details[3], "text/html", "UTF-8");
//webViewBody.loadDataWithBaseURL(null, details[3] , "text/html", "utf-8", null);
here details[3] is the email content.
What am i missing here!? :( Please help me out.
EDITED:
I have Added codes I have Used to get the message contents for displaying email content below.
public void getContent(Message msg)
{
try
{
Object o = msg.getContent();
if (o instanceof String)
{
if(((String) o).equalsIgnoreCase(""))
{
}
else
{
messageBody = (String)o+"STRING!!";
}
}
else if (o instanceof Multipart)
{
Multipart mp = (Multipart)o;
int count3 = mp.getCount();
for (int j = 0; j < count3-1; j++)
{
// Part are numbered starting at 0
BodyPart b = mp.getBodyPart(j);
Object o2 = b.getContent();
if (o2 instanceof String)
{
if(((String) o).equalsIgnoreCase(""))
{
}
else
{
messageBody = (String)o2+"MULTIPART!!";
}
}
} //End of for
}
else if (o instanceof InputStream)
{
//System.out.println("**This is an InputStream message**");
InputStream is = (InputStream)o;
// Assumes character content (not binary images)
//messageBody = convertStreamToString(is)+"INPUT STREAM!!";
int c;
while ((c = is.read()) != -1)
{
messageBody = convertToString(is)+"INPUT STREAM!!";
System.out.println(messageBody);
}
}
}
catch (Exception ex)
{
System.out.println("Exception arise at get Content");
ex.printStackTrace();
}
//TODO TEST CODES
try
{
String contentType = msg.getContentType();
// System.out.println("Content Type : " + contentType);
Multipart mp = (Multipart) msg.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
{
dumpPart(mp.getBodyPart(i));
}
}
catch (Exception ex)
{
System.out.println("Exception arise at get Content");
ex.printStackTrace();
}
}
public String convertToString(InputStream inputStream)
{
StringBuffer string = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
try
{
while ((line = reader.readLine()) != null)
{
string.append(line + "\n");
}
}
catch (IOException e)
{
}
return string.toString();
}
The control is always going to "else if (o instanceof InputStream)" condition. so its streaming email always and displaying complete email content. What am I missing here?
I think you will need to implement a WebView, because it can format the html AND display images.
AFAIK, A textView with html can format the content but cannot display the images.
Edit:
The following should work:
webViewBody.loadData(details[3], "text/html", null);
Probably you are displaying all the email content that can be composed by html and plain text content in the same email.
This is caused because this kind of email is multipart content and u need to split-it, you also need to separate attachments and images (embedded)
see if your "details" is not returning a multipart content body.
The detail gets displayed twice just because of two times you have written:
webViewBody.loadData(details[3], "text/html", "UTF-8");
webViewBody.loadDataWithBaseURL(null, details[3] , "text/html", "utf-8", null);
Probable Solution: Use either loadData() or loadDataWithBaseURL().
adding these lines solved the problem!
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
Thanks to everyone who helped me to solve this. :)

JavaMail - Parsing email content, can't seem to get it to work! (Message.getContent())

For a few weeks I have been developing a email client for android, I have been ignoring parsing email content for a while as I have never been able to get it to work. Thus, the time has come to ask for help!
I have been looking around and I have come across a few methods I have tried but never had much success with! Currently my closest attempt would have to be:
private String parseContent(Message m) throws Exception
{
//Multipart mp = (Multipart)c;
//int j = mp.getCount();
/*for (int i = 0; i < mp.getCount(); i++)
{
Part part = mp.getBodyPart(i);
System.out.println(((MimeMessage)m).getContent());
content = content + part.toString();
//System.out.println((String)part.getContent());
}*/
Object content = m.getContent();
String contentReturn = null;
if (content instanceof String)
{
contentReturn = (String) content;
}
else if (content instanceof Multipart)
{
Multipart multipart = (Multipart) content;
BodyPart part = multipart.getBodyPart(0);
part.toString();
contentReturn = part.getContent().toString();
}
return contentReturn;
}
But it does not work and I get gibberish such as "javax.mail.internet.MimeMultipart#44f12450".
Can anyone see where I am going wrong?
Thanks,
Rhys
None of the above suggestions is valid. You don't need to do anything complex here. Mimemessage has got message.writeTo(outputStream);
All you need to print the message is:
message.writeTo(System.out);
The above code will print the actual mime message to the console (or you can use any logger).
Save the content to .eml and you can open it in outlook. Simple as that!
Multipart multipart = (Multipart) content;
BodyPart part = multipart.getBodyPart(0);
part.toString();
contentReturn = part.getContent().toString();
When you have BodyPart part, you should keep testing
if(part.getContent() instanceof String){
...
}
I had the same issues while parsing Message of javax mail. In my workaround i found a weird thing. Listing mail from POP3 was not giving me Mail body content. So used IMAP which worked for me. Now i'm able to parse Text/plain as well as Text/Html and read the body. To parse the same i used following method.
public String printMessage(Message message) {
String myMail = "";
try {
// Get the header information
String from = ((InternetAddress) message.getFrom()[0])
.getPersonal();
if (from == null)
from = ((InternetAddress) message.getFrom()[0]).getAddress();
System.out.println("FROM: " + from);
String subject = message.getSubject();
System.out.println("SUBJECT: " + subject);
// -- Get the message part (i.e. the message itself) --
Part messagePart = message;
Object content = messagePart.getContent();
// -- or its first body part if it is a multipart message --
if (content instanceof Multipart) {
messagePart = ((Multipart) content).getBodyPart(0);
System.out.println("[ Multipart Message ]");
}
// -- Get the content type --
String contentType = messagePart.getContentType();
// -- If the content is plain text, we can print it --
System.out.println("CONTENT:" + contentType);
if (contentType.startsWith("TEXT/PLAIN")
|| contentType.startsWith("TEXT/HTML")) {
InputStream is = messagePart.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
String thisLine = reader.readLine();
while (thisLine != null) {
System.out.println(thisLine);
myMail = myMail + thisLine;
thisLine = reader.readLine();
}
}
System.out.println("-----------------------------");
} catch (Exception ex) {
ex.printStackTrace();
}
return myMail;
}
Hope it helps someone.
I also got the same error any tried almost every thing, but the solution worked for me is
private String getFinalContent(Part p) throws MessagingException,
IOException {
String finalContents = "";
if (p.getContent() instanceof String) {
finalContents = (String) p.getContent();
} else {
Multipart mp = (Multipart) p.getContent();
if (mp.getCount() > 0) {
Part bp = mp.getBodyPart(0);
try {
finalContents = dumpPart(bp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return finalContents.trim();
}
private String dumpPart(Part p) throws Exception {
InputStream is = p.getInputStream();
// If "is" is not already buffered, wrap a BufferedInputStream
// around it.
if (!(is instanceof BufferedInputStream)) {
is = new BufferedInputStream(is);
}
return getStringFromInputStream(is);
}
private String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
Hope this will help someone.
Not entirely sure, but what it sounds like is you want to convert a MimeMessage into a String. Strictly speaking, there is no "standard" translation for MimeMessage to String, but here is a chunk of code that I wrote a couple of years back that attempts to generate one such translation. Only tested on English messages, so i18n will have to be something you think about yourself.
Unfortunately SO's stupid filter seems to think that my code sample is an image and won't let me post it: take a look at the class at http://pastebin.com/pi9u5Egq : the code is doing a bunch of otherwise unnecessary things (it was spitting it out into HTML that was rendered using flying saucer), and also requires Jakarta Commons Lang, javamail and activation libraries, but it works for me. You would invoke it like this:
fetchText(message, null, false, false);
To get a text string. Try that out for size.

Categories