Issue in reading email via "GMAIL IMAP" using 'javax.mail.Message' - java

using java reading email via "GMAIL IMAP" using 'javax.mail.Message', if sender is using "mac" device then not able to get attachment's detail as name. Check below code written to fetch attached file name in email :
private void getAttachmentFileName(Message msg) throws MessagingException, IOException {
if (msg.getContent() != null) {
Object content = msg.getContent();
if (content instanceof Multipart) {
MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent();
int numberOfParts = mimeMultipart.getCount();
for (int partCount = 0; partCount < numberOfParts; partCount++) {
MimeBodyPart part = (MimeBodyPart) mimeMultipart.getBodyPart(partCount);
if (part.getFileName() != null) {
System.out.println("fileName :: " + part.getFileName());
}
}
}
}
}
Click here to find debug code where found that details are coming under "BODYSTRUCTURE" but this object is unable to read

Related

Reading Email Attachments Using JavaMail - Reading 'winmail.dat' Rather Than Actual Attachment

I am attempting to build a client that uses the javax.mail API to read email messages, including attachments. My initial thought was to use the Tika library. When that produced an unexpected result (please refer to code and details below), I tried using a variation of the code presented in this question.
My function for reading emails:
// Reference: https://www.tutorialspoint.com/javamail_api/javamail_api_checking_emails.htm
public class CheckingMails {
public static void check(String host, String storeType, String user, String password) {
try {
// create properties field
Properties properties = new Properties();
properties.put("mail.pop3.host", host);
properties.put("mail.pop3.port", "110");
Session emailSession = Session.getInstance(properties);
Store store = emailSession.getStore("pop3");
store.connect(host, user, password);
Folder emailFolder = store.getFolder("INBOX");
emailFolder.open(Folder.READ_WRITE);
// retrieve the messages from the folder in an array and print it
Message[] messages = emailFolder.getMessages();
System.out.println("messages.length---" + messages.length);
for (int i = 0, n = messages.length; i < n; i++) {
Message message = messages[i];
Object content = message.getContent();
if (content instanceof java.lang.String) {
System.out.println((String) content);
} else if (content instanceof Multipart) {
Multipart mp = (Multipart) content;
for (int j = 0; j < mp.getCount(); j++) {
Part part = mp.getBodyPart(j);
String disposition = part.getDisposition();
if (disposition == null) {
// Check if plain
MimeBodyPart mbp = (MimeBodyPart) part;
if (mbp.isMimeType("text/plain")) {
System.out.println("Mime type is plain");
System.out.println((String) mbp.getContent());
} else {
// Special non-attachment cases here of
// image/gif, text/html, ...
System.out.println("File name is " + part.getFileName());
}
} else if ((disposition != null)
&& (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE))) {
// Check if plain
MimeBodyPart mbp = (MimeBodyPart) part;
if (mbp.isMimeType("text/plain")) {
System.out.println("Mime type is plain");
System.out.println((String) mbp.getContent());
} else {
System.out.println("Save file " + part.getFileName());
}
}
}
}
System.out.println("Tika results " + parseMsg(message));
}
// close the store and folder objects
emailFolder.close(false);
store.close();
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
When I test the program by sending a test message with a simple CSV as an attachment, the Tika parser outputs the following (truncated for brevity):
------=_NextPart_000_0028_01D47C16.81FB45C0
Content-Type: application/ms-tnef;
name="winmail.dat"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="winmail.dat"
eJ8+IhUSAQaQCAAEAAAAAAABAAEAAQeQBgAIAAAA5AQAAAAAAADoAAEIgAcAGAAAAElQTS5NaWNy
b3NvZnQgTWFpbC5Ob3RlADEIAQOQBgCgDQAANgAAAAsAAgABAAAAAwAmAAAAAAALACkAAAAAAB4A
cAABAAAABQAAAFRlc3QAAAAAAgFxAAEAAAAWAAAAAdR8SMswwghurPF+SpeO8uRrTzrhCgAACwAB
DgAAAAACAQoOAQAAABg.....
------=_NextPart_000_0028_01D47C16.81FB45C0--
The other portion of the code (that checks for the message's disposition), outputs something similar to the following:
messages.length---1
Mime type is plain
Email Boday
Save file winmail.dat
Why is the application reading/recognizing winmail.dat and not the attachment that was actually sent with the message (a CSV file)?
Thanks for any help.

javax.mail: Get nested attachments in EML attachment

I have an existing code that downloads and processes some emails correctly.
The email to process must have one or more xml as attachment, now I'm migrating this process from the current standard mail account to a certified system that wrap that mail into a new email.
So, instead of a flat email with one xml attachment, I have to parse an email with an XML (the certified) and an EML (the message that I should process).
In short, my code is like the following:
private void processMessage(final Message message) {
try {
final String contentType = message.getContentType();
if (contentType.contains("multipart")) {
final Multipart multiPart = (Multipart) message.getContent();
for (int i = 0; i < multiPart.getCount(); i++) {
final MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i);
/**************************************************************
* HERE I CAN'T GET THE EML (and its attachments) FROM 'part' *
**************************************************************/
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
processAttachment(part);
}
}
}
} [...cutted...]
}
private void processAttachment(final MimeBodyPart part) throws IOException, MessagingException {
final InputStream input = getReusableInputStream(part);
if (part.getFileName() != null && isXmlType(part.getContentType())) {
processXml(input);
}
}
I should modify it, in order to parse the EML and get the attachments recursively, but I'm missing the big picture.
UPDATE: I've modified the processAttachment method (but it still doesn't work):
private void processAttachment(final Multipart multipart) {
try {
for (int i = 0; i < multipart.getCount(); i++) {
final BodyPart bodyPart = multipart.getBodyPart(i);
if (bodyPart.getContent() instanceof Multipart) {
// part-within-a-part, do some recursion...
extractAttachment((Multipart) bodyPart.getContent());
}
System.out.println("Filename: " + bodyPart.getFileName());
System.out.println("ct: " + bodyPart.getContentType());
final boolean isXml = bodyPart.getFileName() != null && isXmlType(bodyPart.getContentType());
if (isXml) {
final InputStream inputStream = getReusableInputStream(bodyPart);
processXMLAttachment(inputStream);
}
}
} [cutted]
}
The output is:
Filename: null
ct: TEXT/PLAIN; charset=iso-8859-1
Filename: null
ct: TEXT/HTML; charset=iso-8859-1
Filename: daticert.xml
ct: APPLICATION/XML; name=daticert.xml
Filename: postacert.eml
ct: MESSAGE/RFC822; name=postacert.eml
Filename: smime.p7s
ct: APPLICATION/X-PKCS7-SIGNATURE; name=smime.p7s
From the output, I can see that the system only scaned the first level attachments daticert.xml and postacert.eml but it didn't find the nested attachments.
More specifically, I have to read the content of:
Filename: postacert.eml
ct: MESSAGE/RFC822; name=postacert.eml
Any help, please?
Thanks
Well, I solved by checking the class of any MimePart, and I found that nested messages are type of IMAPNestedMessage, so on this kind of object I recursively call the main method processMessage:
private void processAttachment(final Multipart multipart) {
try {
for (int i = 0; i < multipart.getCount(); i++) {
final BodyPart bodyPart = multipart.getBodyPart(i);
// BEGIN - Added this part
System.out.println("CLASS bodyPart: " + bodyPart.getContent().getClass());
if (bodyPart.getContent() instanceof IMAPNestedMessage) {
processMessage((IMAPNestedMessage) bodyPart.getContent());
} else {
// END - Added this part
if (bodyPart.getContent() instanceof Multipart) {
processAttachment((Multipart) bodyPart.getContent());
} else {
final boolean isXml = bodyPart.getFileName() != null && isXmlType(bodyPart.getContentType());
if (isXml) {
final InputStream inputStream = getReusableInputStream(bodyPart);
processXMLAttachment(inputStream);
}
}
}
}
} catch (final Exception e) {
sendMailService.sendMailForImportINPSFailed("metodo processAttachment()", e);
e.printStackTrace();
}
}
And now it works fine.

Call a java Rest webservice on email event

I have a webservice x exposed.If I get a mail in my email containing attachment I want to call
this webservice.I am not asking for code.I am asking your suggestion in high level how this can be done?
You need REST. So - you cant use org.apache.http.client library. (Other way, if you'll have web service you can use wsimport to create WebService java-client.)
Use javax.mail library to open mailbox and iterate letters.
Process letters. Mark or delete processed letters.
Add crontab/sheduler task to run your app. (As for me, It's better, than create a thread app). Dont forget to use run-one option to prevent double execution.
Here some code example that reads "*.xls" files from mailbox messages:
public void processEmail() throws MessagingException {
Store emailStore = null;
Folder emailFolder = null;
try {
// connecting
Properties properties = new Properties();
properties.setProperty("mail.store.protocol", "imaps");
Session emailSession = Session.getDefaultInstance(properties);
Main.getLog().debug("CONNECT TO : " + config.mailServer + " ["
+ config.mailUser + "] DEBUG: "+config.debug);
// check mailbox
emailStore = emailSession.getStore("imaps");
emailStore.connect(config.mailServer, config.mailUser,
config.mailPassword);
Main.getLog().debug("CONNECT DONE");
emailFolder = emailStore.getFolder("INBOX");
emailFolder.open(Folder.READ_WRITE);
Message[] messages = emailFolder.getMessages();
Main.getLog().debug("RECEIVED " + messages.length + " MESSAGSES");
// for each letter
for (Message message : messages) {
try {
Main.getLog().debug("\nPROCESS LETTER : "
+ message.getSubject());
if (message.getFlags().contains(Flags.Flag.DELETED)) {
continue; // don't process such letters
}
if (message.getFlags().contains(Flags.Flag.SEEN)) {
continue; // don't process such letters
}
//
Map<String, String> parseResult = new HashMap<String, String>();
String auditId = "";
// get file
if (message.getContent() instanceof Multipart) {
Multipart multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if (!Part.ATTACHMENT.equalsIgnoreCase(bodyPart
.getDisposition())) {
continue;
}
// Process file
if (bodyPart.getFileName().contains(".xls")) {
auditId = maintainExcelFile(bodyPart.getInputStream());
}
}
} else if (message.getContent() instanceof BASE64DecoderStream) {
// Process file
if (message.getFileName().contains(".xls")) {
auditId = maintainExcelFile(((BASE64DecoderStream) message
.getContent()));
}
}
if (!config.debug && auditId!=null && !auditId.equals("")) {
message.setFlag(Flags.Flag.SEEN, true);
}
if (!config.debug) {
sendAcceptMail(message, auditId);
}
} catch (Exception e) {
// Process errors
if (!config.debug) {
message.setFlag(Flags.Flag.SEEN, true);
sendErrorMail(message, e);
}
Main.getLog().error(e.getMessage(), e);
throw new Exception(e);
}
}
} catch (Exception e) {
Main.getLog().error(e.getMessage(), e);
} finally {
emailFolder.close(true);
emailStore.close();
}
}

Can't get email attachments without extension from javax.mail.message

Help please to solve my problem.
I have a function that find email content and attachments:
public void setContentAndAttachmentsList(GMailEmail gMailEmail, Part message) throws MessagingException, IOException {
if (message.isMimeType("text/*") && StringUtils.isEmpty(message.getFileName())) {
gMailEmail.setContent(message.getContent().toString());
log.debug("Found text data. Set as body: " + message.getContent().toString());
} else if (message.isMimeType(MULTIPART_MIME_TYPE)) {
Multipart multipartMessage = (Multipart) message.getContent();
for (int i = 0; i < multipartMessage.getCount(); i++) {
BodyPart messagePart = multipartMessage.getBodyPart(i);
setContentAndAttachmentsList(gMailEmail, messagePart);
}
} else if (StringUtils.isNotBlank(message.getFileName())) {
MailAttachment attachment = new MailAttachment();
attachment.setContentType(message.getContentType());
log.debug("Attachment content type: " + message.getContentType());
attachment.setName(message.getFileName());
log.debug("Attachment file name: " + message.getFileName());
if (message.getContent() instanceof InputStream) {
attachment.setInputStream((InputStream) message.getContent());
} else {
attachment.setInputStream(IOUtils.toInputStream(message.getContent().toString(), UTF_8));
}
List<MailAttachment> attachmentsList = gMailEmail.getAttachmentsList();
attachmentsList.add(attachment);
gMailEmail.setAttachmentsList(attachmentsList);
log.debug("Found attachment" + message.getFileName());
}
}
GMailEmail is POJO.
If email has attachments that have extensions it works perfectly. But when attachments have no extensions, message.getFileName() simply returns null.
I solved this problem.
It must be
StringUtils.isBlank(message.getFileName())
instead of
StringUtils.isEmpty(message.getFileName())
in second line.

Gmail JavaMail message retrevial problem

I am working on a project using JavaMail. I want to access my Gmail inbox and get the messages. I look for a specific message by checking the subject. This message has an attachment which i save.The program works fine on the first run. The problem is that once I run the program, any subsequent runs can not see the message. It does not appear as a part of the folder's messages. If I go to the gmail account and set "Enable POP for all mail (even mail that's already been downloaded)" (whihc was the setting from the beginning) I can see the message once more before it again stops appearing in the folder. I dont understand, any help would be great.
Here is my code that gets the messages:
Session session2 = Session.getDefaultInstance(props2, null);
Store store = session2.getStore("pop3s");
store.connect(getHost, username, password);
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
System.out.println(folder.getMessageCount());
Message messages[] = folder.getMessages();
for (Message message : messages) {
System.out.println(message.getSubject());
if (message.getSubject().equalsIgnoreCase("Input File")) {
if (message.getContent() instanceof Multipart) {
Multipart multipart = (Multipart) message.getContent();
for (int i = 0, n = multipart.getCount(); i < n; i++) {
Part part = multipart.getBodyPart(i);
String disposition = part.getDisposition();
if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE))))) {
File f = saveFile(part.getFileName(), part.getInputStream());
System.out.println(f.getPath());
}
}
}
}
}
folder.close(false);
store.close();
}
The saveFile method:
public static File saveFile(String filename, InputStream input) throws FileNotFoundException, IOException {
File file = new File(filename);
for (int i = 0; file.exists(); i++) {
file = new File(filename + i);
}
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
BufferedInputStream bis = new BufferedInputStream(input);
int aByte;
while ((aByte = bis.read()) != -1) {
bos.write(aByte);
}
bos.flush();
bos.close();
bis.close();
return file;
}
I tried switching my code to using imap and now it seems to be working. I guess my problem has something to do with pop3 and gmail.
The code is almost correct and it helped me very much. The Part.Attachment ="attachment" but the String disposition = "ATTACHMENT"
Only replace the part
if ((disposition != null) && ((disposition.equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE))))) {
File f = saveFile(part.getFileName(), part.getInputStream());
System.out.println(f.getPath());
}
with
if ((disposition != null) && ((disposition.toLowaerCase().equals(Part.ATTACHMENT) || (disposition.equals(Part.INLINE))))) {
File f = saveFile(part.getFileName(), part.getInputStream());
System.out.println(f.getPath());
}

Categories

Resources