I'm trying to parse a mime message using the JavaMail API, I did some research but the steps I found doesn't work for me, one of them is what was answered here:
Java Email message Parser?
I'm doing it passing an InputStream as a ByteArrayInputStream came from the content I'm trying to parse.
When I do it, my message.getContent leads to an empty String.
I'm using Scala, btw.
I had this problem recently, so your research couldn't have been that good. When I say recently, I mean the last couple of days! :P
But this is what I did to read the emails (Or at least somewhat read the email. It returns a big chunk of HTML text, which isn't really always pretty in a JEditorPane
private void tableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableMouseReleased
final java.awt.event.MouseEvent e = evt;
Thread t = new Thread(new Runnable() {
#Override
public void run() {
if(table.getRowCount() == 0 || message == null || message.length == 0) {
// Do nothing
} else {
try {
int row = table.rowAtPoint(e.getPoint());
String subject = message[row].getSubject();
String from = InternetAddress.toString(message[row].getFrom());
StringBuilder body = new StringBuilder();
Multipart mp = (Multipart) message[row].getContent();
for(int i = 0; i < mp.getCount(); i++) {
BodyPart bp = mp.getBodyPart(i);
String disp = bp.getDisposition();
if(disp != null && (disp.equals(BodyPart.ATTACHMENT))) {
// Do something
} else {
body.append(bp.getContent());
}
}
EmailContent ec = new EmailContent(new JFrame(),true,from,subject,"<html>" + body.toString());
} catch (IOException ex) {
Logger.getLogger(MailPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (MessagingException ex) {
Logger.getLogger(MailPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
t.start();
}
I had to fill a table with messages and then when you click on a message in the table, it would show a new window with the message in it. The message array is just an array filled with Message objects. So you will obviously need a message to do this. But the part you are after is this:
StringBuilder body = new StringBuilder();
Multipart mp = (Multipart) message[row].getContent();
for(int i = 0; i < mp.getCount(); i++) {
BodyPart bp = mp.getBodyPart(i);
String disp = bp.getDisposition();
if(disp != null && (disp.equals(BodyPart.ATTACHMENT))) {
// Do something
} else {
body.append(bp.getContent());
}
}
It should work, so we'll need more details of what you're doing to figure out what's going wrong.
First, let's make sure the problem isn't with your code and the mail message is correctly formatted. Use the msgshow.java demo program that comes with JavaMail to display the message. Use the -m option and redirect stdin from the file containing the MIME message. What does it display?
If that works correctly, show us the code you're using to read the message.
Related
Please explain to me, what is the cause of distortion of JSON-String sent from JavaFX application to Tomcat server. Part of symbols is replaced by strange square symbols:
Conversation to JSON pass correctly – I checked it by printing JSON-String to console in JavaFX app after serializing. But after transfer to Tomcat-server by DoPost method JSON-String is distorted. And I tried to transfer XML too – it distorts by the same way.
After small investigation, I got some result: String sent by DoPost stays correct if it's length is 7782 symbols or less. Plus one symbol – and squares appears:
Both the JavaFX app and Tomcat server starts on local machine under Intellij IDEA, so it's not a network problem.
Very thanks to user Nick on ru.stackoverflow.com:
https://ru.stackoverflow.com/users/216863/nick
He gave exact cause – length of inputStream. GZIP gives not correct value of inputStream length to Servlet.
And when I replaced this code:
`public String getInputString(HttpServletRequest req) {
String receivedString = "";
int len = req.getContentLength();
byte[] input = new byte[len];
try {
ServletInputStream sin = req.getInputStream();
int c = 0;
int count = 0;
while ((c = sin.read(input, count, (input.length - count))) > 0) {
count += 1;
}
sin.close();
} catch (IOException e) {
}
receivedString = new String(input);
return receivedString;
}`[PasteBin-1][1]
by this:
`public String getInputString(HttpServletRequest req) {
String receivedString = "";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream()))) {
StringBuilder sb = new StringBuilder("");
while (reader.ready()) {
sb.append(reader.readLine());
}
if (sb.length() > 0) {
receivedString = sb.toString();
}
} catch (IOException e) {
}
return receivedString;
}`[PasteBin-2][2]
everything started to work correctly.
This is same question thread on russian:
answer on ru.stackoverflow.com
I am having an odd issue reading in the following JSON formatted API - Trivia API (this URL is passed in through the Async). I will explain in more detail below, but basically my code appears to be not properly reading in a JSON file, which results in me being unable to loop through it and set my question objects accordingly.
Logs revealed that the reading of the input stream at IOUtils seems to not finish reading the entire JSON file, often stopping by the 11th question object within the file.
I think this has to do with a Log limit, as when I add more to the Log (such as "This is the json String -") it prints less, but this does not explain why it is not properly looping through the question objects and setting them accordingly. Other logs revealed that it does not even loop through the questions, it only goes through one time and only sets the title.
I am clueless as to what is happening as I have parsed other JSON files literally the exact same way as this.
#Override
protected ArrayList<Question> doInBackground(String... strings) {
HttpURLConnection connection = null;
ArrayList<Question> result = new ArrayList<>();
try {
URL url = new URL(strings[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
String json = IOUtils.toString(connection.getInputStream(), "UTF-8");
Log.d("demo", "This is the json String - " + json);
JSONObject root = new JSONObject(json);
JSONArray questions = root.getJSONArray("questions");
for (int i = 0; i < questions.length(); i++) {
JSONObject questionsJSONObject = questions.getJSONObject(i);
Question question = new Question();
question.setText(questionsJSONObject.getString("text"));
//Choice array
JSONObject choicesObject = questionsJSONObject.getJSONObject("choices");
String[] temp = new String[choicesObject.getJSONArray("choice").length()];
for (int j = 0; j < choicesObject.getJSONArray("choice").length(); j++) {
temp[j] = choicesObject.getJSONArray("choice").getJSONObject(j).toString();
}
question.setChoices(temp);
//End of Choice array
question.setAnswer(questionsJSONObject.getInt("answer");
question.setUrlToImage(questionsJSONObject.getString("image"));
result.add(question);
}
}
} catch (Exception e) {
//Handle Exceptions
} finally {
//Close the connections
}
Log.d("demo", "toString - " + result.toString());
return result;
}
I'm creating an app that sends and receive data with an arduino via bluetooth. Sending works fine, however when receiving data I don't get the first few characters of the string sent. I always don't get the first character, the second I sometimes get it, the third I almost always get it, etc.
So for example if the arduino sends "OK 1" I receive "K 1" or " 1" or "1", but never the complete string. An easy fix would be to add a few dummy characters, but that's a shit fix.
Here's the method which listens to incoming connections, directly copy/pasted from Android sample bluetooth code to send a simple string via bluetooth (though with a few fixes):
void beginListenForData()
{
final Handler handler = new Handler();
final byte delimiter = 10; //This is the ASCII code for a newline character
final boolean stopWorker = false;
final int readBufferPosition = 0;
final byte[]readBuffer = new byte[1024];
Thread workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = inStream.available();
int readBufferPosition2 = readBufferPosition;
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
inStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
if(b == delimiter)
{
byte[] encodedBytes = new byte[readBufferPosition2];
System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
final String data = new String(encodedBytes);
readBufferPosition2 = 0;
handler.post(new Runnable()
{
public void run()
{
result.setText(data);
}
});
}
else
{
readBuffer[readBufferPosition2++] = b;
}
}
}
}
catch (IOException ex)
{
}
}
}
});
workerThread.start();
}
Here's all my code in case you want to test it (warning: lots of dummy and outdated code):
MainActivity.java http://pastebin.com/cdjW4Y1V
XML layout file http://pastebin.com/Ruf5euPP
Click on the first button to connect to the arduino and click on the second button to send a string and to begin receiving data.
So yep, I have absolutely no idea why it doesn't work. It works fine with TerminalBT so it's not a problem with the arduino, it's a problem with my app, but why do I receive characters randomly?
one thing i noticed is that you should not use 10 for the delimiter.
I have encountered this error before if you use 10 then some times it does not get recognized properly.
you should use standard Java Function to parse the delimiter.
System.getProperty("line.separator");
//OR
System.lineSeparator();
I'm looking at the RTI DDS add-in for Excel, and I'm trying to rewrite the Hello_simple HelloPublisher.java example that comes with it to publish a string, and get Excel to pick it up.
Everything works, apart from displaying the value of the string I feed it. (It picks up the time the message was sent, and all the other meta-data just fine)
My code looks something like this:
public class Publish {
public static void main(final String[] args){
// Create the DDS Domain participant on domain ID 123
final DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant(
123, //Domain ID
DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT,
null, // Listener
StatusKind.STATUS_MASK_NONE);
if (participant == null) {
System.err.println("Unable to create domain participant");
return;
}
// Create the topic "Message" for the String type
final Topic topic = participant.create_topic(
"Message",
StringTypeSupport.get_type_name(),
DomainParticipant.TOPIC_QOS_DEFAULT,
null, // listener
StatusKind.STATUS_MASK_NONE);
if (topic == null) {
System.err.println("Unable to create topic.");
return;
}
// Create the data writer using the default publisher
final StringDataWriter dataWriter =
(StringDataWriter) participant.create_datawriter(
topic,
Publisher.DATAWRITER_QOS_DEFAULT,
null, // listener
StatusKind.STATUS_MASK_NONE);
if (dataWriter == null) {
System.err.println("Unable to create data writer\n");
return;
}
System.out.println("Ready to write data.");
System.out.println("When the subscriber is ready, you can start writing.");
System.out.print("Press CTRL+C to terminate or enter an empty line to do a clean shutdown.\n\n");
final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
while (true) {
System.out.print("Please type a message> ");
final String value = reader.readLine();
if (value == null) {break;}
dataWriter.write(value, InstanceHandle_t.HANDLE_NIL);
if (value.equals("")) { break; }
}
} catch (final IOException e) {e.printStackTrace();
} catch (final RETCODE_ERROR e) {e.printStackTrace();}
System.out.println("Exiting...");
participant.delete_contained_entities();
DomainParticipantFactory.get_instance().delete_participant(participant);
}
}
The call I make in Excel to display the value is
=RTD("dds2excel.connect",,"TYPE:DDS::String","TYPENAME:DDS::String","TOPIC:Message","FIELD:value")
(Auto-generated by the RTI add-in)
I'm not very familiar with RTI and DDS yet, but I have a feeling Excel doesn't want to pick up the actual contents of this data because it thinks it doesn't belong to it? Hence why it only acknowledges the meta-data for the domain that it's listening to.
Any pointers would be greatly appreciated.
If I have a servlet running JVM1.4.2, and it is receiving a POST request with form data fields. I use req.getParameterNames() to get, what I would expect, all the query string and form data. However, all I ever get are the querystring parameters.
Literature I am reading from various sources says that getParameterNames() and getParameterValues(String) should be the way to get all query string and posted form data sent by the browser for JDK 1.4. Here is the method I use to extract all the parameters, which I expect would include posted form data :
public Map getParameterMap(HttpServletRequest req) {
Map params= new HashMap();
String name = null;
System.out.println("<< Getting Parameter Map.>>");
Enumeration enumParams = req.getParameterNames();
for (; enumParams.hasMoreElements(); ) {
// Get the name of the request parameter
name = (String)enumParams.nextElement();
// Get the value of the request parameters
// If the request parameter can appear more than once
// in the query string, get all values
String[] values = req.getParameterValues(name);
params.put(name, values);
String sValues = "";
for(int i=0;i<values.length;i++){
if(0<i) {
sValues+=",";
}
sValues +=values[i];
}
System.out.println("Param " + name + ": " + sValues);
}
System.out.println("<< END >>");
return params;
}
This question also agrees with my expectations, but the servlet is not picking up the form data. Obviously I am missing something....
Update: The post data is very straight forward and is not a Multipart form or rich media. Just plain'ol text submitted via an AJAX POST that looks like this in post body
c1=Value%20A&c2=Value%20B&c3=Value%20C
I managed to identify the problem. Because there is so much chatter from JDK 1.5+ and talk of getParameterMaps() method for 1.5, info on how 1.4 handles form post data was scarce and ambiguous. (Please post a comment if you find something that is specific for 1.4).
Pre-1.5 you have to manually get the form data via getInputStream, and then parse it out. I found this method, (posted below), from the java sun site that does a nice job using a Hashtable. I had to make a minor mod for deprecated methods. But seems to work quite robustly, "out of the box", so you should able to just cut-n-paste. I know it's "old tech" but I thought it worthwhile for those who may be in the same situation as me who are stuck on solving (what seems to be) straight forward problems.
public Hashtable parsePostData(int length, ServletInputStream instream) {
String valArray[] = null;
int inputLen, offset;
byte[] postedBytes = null;
boolean dataRemaining=true;
String postedBody;
Hashtable ht = new Hashtable();
//Vector paramOrder = new Vector(10);
StringBuffer sb = new StringBuffer();
if (length <=0) {
return null;
}
postedBytes = new byte[length];
try {
offset = 0;
while(dataRemaining) {
inputLen = instream.read (postedBytes, offset, length - offset);
if (inputLen <= 0) {
throw new IOException ("read error");
}
offset += inputLen;
if((length-offset) ==0) {
dataRemaining=false;
}
}
} catch (IOException e) {
System.out.println("Exception ="+e);
return null;
}
postedBody = new String (postedBytes);
StringTokenizer st = new StringTokenizer(postedBody, "&");
String key=null;
String val=null;
while (st.hasMoreTokens()) {
String pair = (String)st.nextToken();
int pos = pair.indexOf('=');
if (pos == -1) {
throw new IllegalArgumentException();
}
try {
key = URLDecoder.decode(pair.substring(0, pos),"UTF8");
val = java.net.URLDecoder.decode(pair.substring(pos+1,pair.length()),"UTF8");
} catch (Exception e) {
throw new IllegalArgumentException();
}
if (ht.containsKey(key)) {
String oldVals[] = (String []) ht.get(key);
valArray = new String[oldVals.length + 1];
for (int i = 0; i < oldVals.length; i++) {
valArray[i] = oldVals[i];
}
valArray[oldVals.length] = val;
} else {
valArray = new String[1];
valArray[0] = val;
}
ht.put(key, valArray);
String sValues = "";
for(int i=0;i<valArray.length;i++) {
if (0<i) {
sValues+=",";
}
sValues = valArray[i];
}
System.out.println("Form data field " + key + ":" +sValues);
//paramOrder.addElement(key);
}
return ht;
}
That's true. The getParameterNames(), getParameterValues(), and getParameter() methods are the way to access form data unless it's a multipart form, in which case you'll have to use something like Commons Fileupload to parse the multipart request before all the parameters are accessible to you.
Edit: You're probably not encoding the POST data properly in your AJAX call. POST data must carry a Content-Type of application/x-www-form-urlencoded or else multipart/form-data. If you're sending it as something else, it doesn't qualify as a request parameter, and I expect you'd see the behavior you're describing. The solution you've engineered essentially consists of setting up custom parsing of custom content.