Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

using java in a cfc to parse emails 1

Status
Not open for further replies.

forumposters

Programmer
Aug 31, 2006
61
US
Here's some java code that does almost exactly what I want to do.
However, I want to use this java code in a cfc
I'm clueless how to put this java code into a cfc.
Any pointers or tips to help me get started would be very much appreciated.
 
It is very simple. The key part is using the full path to the java classes. In java you can call a static method of a core class simply using its name. Where System is the name of a core java class: java.lang.System

Code:
... System.getProperties();

In ColdFusion you must use createObject() to get a reference to the class, using the full package path:

Code:
... createObject("java", "java.lang.System").getProperties();

Watch out for ugly line wrapping..

Code:
	<cfscript>
		props = createObject("java", "java.lang.System").getProperties();

        props.put( javacast("string", "mail.host"), javacast("string", "smtp.dummydomain.com"));
        props.put( javacast("string", "mail.transport.protocol"),  javacast("string", "smtp"));
		
		mailSession = createObject("java", "javax.mail.Session").getDefaultInstance(
			props, 
			javacast("null", "")
		);
			
        pathToEmailFile = "c:\tmp\message.eml";
        source = createObject("java", "java.io.FileInputStream").init(pathToEmailFile);
        message = createObject("java", "javax.mail.internet.MimeMessage").init(mailSession, source);


        WriteOutput("Subject : "& message.getSubject() &"<br>");
		from = message.getFrom();
		// note unlike java arrays, ColdFusion arrays are 1-based, not 0-based
        WriteOutput("From : "& from[1] &"<br>");
        WriteOutput("--------------<br>");
        WriteOutput("Body : "&  message.getContent()&"<br>");
	</cfscript>

----------------------------------
 
Thanks, that was very helpful. One thing that is giving me trouble now is trying to figure out where all the data is stored in the message object. I can't use cfdump to see where everything is store and under what function. Instead, I have to keep guessing and checking. Right now for example, I'm trying to find where attachments are stored and I'm lost. Thanks again for you help, you're awesome!
 
Here's how I had to get the body of the email, and it seems to contain the attachments:

<cfset content = message.getContent()>
<cfset i = 0>
<cfset bodyPart = content.getBodyPart(javacast("int", i))>
<cfreturn bodyPart.getContent()>

But, now I want to get the attachments that are in bodyPart.getContent()
 
If you are doing more than just extracting the from and subject lines, that is going to be more involved. You will have to extract each part of the multipart messages, and process each type found. It is not a topic that can be covered in single forum post. Your best best bet is to start with this java guide. It has all of the fundamentals you will need.


You should also get familiar with the API's for the different classes. If you have not worked with java before they may seem foreign at first. But when it comes to working with java classes, they are really your best reference.


----------------------------------
 
Thanks for another helpful post. I am able to create a variable that is a byte array for each attachment. I can then use cffile with the readbinary action. I'm not sure what to do next though. Might I want to use cfcontent to display the attachments? Or, might there be a better way to display the attachments?
 
Using cfcontent to display or download the attachments is probably the simplest option. But I assume you want to save the files first, either to disk or to a db table? I usually prefer saving to disk, because it does not bloat the db. But I do not know what your requirements are.

To write the file to disk try the FileWrite() function for CF8. Off the top of my head, I do not remember whether MX 7 allows you to write binary content with cffile. If it does not try

Code:
<!--- save the byte array to a file --->
<cfscript>
	saveToFile = expandPath("./theFileName.fileExt");
	outStream = createObject("java", "java.io.FileOutputStream").init( saveToFile );
	outStream.write( theByteArray );
	outStream.flush();
	// always close the stream
	outStream.close();
</cfscript>

Then display the file with cfheader and cfcontent. Watch the line wrapping ..

Code:
<!--- example, download a pdf file --->
<cfheader name="Content-Disposition" value="attachment; filename=yourFileName.PDF"> 
<cfcontent file="#fullPathToYourFile#" type="application/pdf" deletefile="no">
...

<!--- example, display a pdf file in browser --->
<cfheader name="Content-Disposition" value="inline; filename=yourFileName.PDF"> 
<cfcontent file="#fullPathToYourFile#" type="application/pdf" deletefile="no">

----------------------------------
 
Actually, I wasn't thinking of saving it to disk nor too a database. Can't I use the variable attribute of cfcontent instead of the file attribute?
 
this seems to work for images. i'm actually using jQuery to write create an iframe for each attachment like this:

$('.attachDisplay').html("<iframe width='500' height='200' src='showFile.cfm?emailFilename=#url.file#&attachFilename="+$(this).attr('attachFilename')+"'></iframe>");

And, then in showFile.cfm I call my functions that return the byte data for each attachment and then cfcontent to display it. For some reason this works great for images. But, when i try to display a .rtf document, it does not work right. It prompts me to download the file instead of showing it in the iframe. Maybe there's a better way to do this? You can only have 1 cfcontent tag on a page though and that's what makes this difficult.
 
Well, if the browser is not configured to open rtfs inside the browser window, you cannot display them in an iframe anyway. It will always prompt to download. Being a client controlled setting, there is not much you can do about that.

I do not know of any way around the 1 content-type limitation, other than using frames or iframes. I think the idea of using multiple iframes to display files is interesting, but it has the downside mentioned above. I am also thinking that it could look a bit too "busy" depending on the number of files ;)


----------------------------------
 
many thanks for your helpful replies... very much appreciated. you got me thinking when you explained that the browsers is not configured to open rtf files... i did some googling on this issue and found a plugin for firefox that allows me to configure this terrific browser to open rtf files automagically. if anyone else is wondering what this plugin is called, it is "MIME Edit 0.60". problem solved. thanks again cfsearching!
 
I am glad you got it worked out. Thanks for the follow up.

Yes, I did not know you were referring to your browser settings only. Those you obviously can configure ;-) You just cannot control the browser settings of other users from your CF page.

----------------------------------
 
forumposters... how did you assign the byte array to a cf variable without just getting the string that indicates it is a byte array?
 
Here is the code I'm using.

Code:
<cfscript>
	props = createObject("java", "java.lang.System").getProperties();

	props.put( javacast("string", "mail.host"), javacast("string", "smtp.dummydomain.com"));
	props.put( javacast("string", "mail.transport.protocol"),  javacast("string", "smtp"));
	
	mailSession = createObject("java", "javax.mail.Session").getDefaultInstance(props, javacast("null", ""));
		
	pathToEmailFile = "c:\test.eml";
	source = createObject("java", "java.io.FileInputStream").init(pathToEmailFile);
	message = createObject("java", "javax.mail.internet.MimeMessage").init(mailSession, source);
	
	mp = message.getContent();
	for(i=0;i<mp.getCount();i++) {
		part = mp.getBodyPart(javacast("int",i));
		disp = part.getDisposition();
		
		if(( isDefined("disp") ) && (UCase(disp)=="ATTACHMENT" || UCase(disp)=="INLINE") ) {
			FileWrite("C:\" & part.getFileName(),part.getInputStream() );
		}
	}
</cfscript>

The result is a file is:
Code:
com.sun.mail.util.BASE64DecoderStream@58924a
 
You are not actually passing a byte array to FileWrite(). The second value is an InputStream. Copy the bytes from the InputStream to a ByteArrayOutputStream. Then use toByteArray() to pass the bytes to FileWrite. You may also wish to add handling to make the file names unique to avoid overwriting.

Code:
</cfscript>
  //... other code

   saveToFileName = "C:\" & part.getFileName();
   inputStream = part.getInputStream();
   outStream = createObject("java","java.io.ByteArrayOutputStream").init();

   // create byte array. read up to the first
   // 1024 bytes (or however many) into the array 
   byteClass = createObject("java", "java.lang.Byte").TYPE;
   byteArray = createObject("java","java.lang.reflect.Array").newInstance(byteClass, javacast("int", 1024));
   length = inputStream.read(byteArray);

   // if there is any data to read
   offset = 0;
   while ( length GT 0) {
      outStream.write( byteArray, offset, length );
      length = inputStream.read( byteArray );
   }
   
   outStream.close();
   inputStream.close();
   
   FileWrite( saveToFileName, outStream.toByteArray() );
</cfscript>

----------------------------------
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top