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

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.

Related

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

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

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.

How to click on a Particular email from gmail inbox in Selenium?

I hv to click on a particular email, in that case what should I do? I seen there is a Webtable with multiple indexes, I hv to select 1 & click on it. does anyone have code how to handle webTables in WebDriver? See exact situation in below screen-
http://screencast.com/t/XRbXQVygNkN6
I was trying with below code -Plz suggest me for rest of the action.
After gmail Login-
1st Ihv clicked on inbox link--->>then Promotions--->>then I hv to click on particular email
WebElement PromotionsSection =driver.findElement(By.xpath("//div[contains(#id,':2y')]"));
PromotionsSection.click();
WebElement email=driver.findElement(By.xpath(".//*[#id=':1g4']/b"));
email.click();
think that u r in page after login. Now use the below code:
List<WebElement> email = driver.findElements(By.cssSelector("div.xT>div.y6>span>b"));
for(WebElement emailsub : email){
if(emailsub.getText().equals("Your Subject Here") == true){
emailsub.click();
break;
}
}
this will just click on ur mail if it matches the subject string.
Do log in in gmail
// open ff and go to gmail login page
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://accounts.google.com/ServiceLogin?sacu=1&scc=1&continue=https%3A%2F%2Fmail.google.com%2Fmail%2F&osid=1&service=mail&ss=1&ltmpl=default&rm=false#identifier");
// log in in to the gmail
driver.findElement(By.xpath("//*[#id='Email']")).sendKeys("ur id");
driver.findElement(By.xpath("//*[#id='next']")).click();
driver.findElement(By.xpath("//*[#id='Passwd']")).sendKeys("ur password");
driver.findElement(By.xpath("//*[#id='signIn']")).click();
now click on the email (first) or of ur choice
List<WebElement> a = driver.findElements(By.xpath("//*[#class='yW']/span"));
System.out.println(a.size());
for(int i=0;i<a.size();i++){
System.out.println(a.get(i).getText());
if(a.get(i).getText().equals("Gmail Team")){ // if u want to click on the specific mail then here u can pass it
a.get(i).click();
}
}
Don't login to Gmail with selenium which is sceurity illegal asper google . Use Java mail.ogin to Gmail with smtp server deatails. Which is fast . This API provides a lot methods to get deiffirenttype of emails
Working solution for your problem. It uses JAVAX MAIL API and JAVA
public GmailUtils(String username, String password, String server, EmailFolder
emailFolder) throws Exception {
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imap");
props.setProperty("mail.imaps.partialfetch", "false");
props.put("mail.imap.ssl.enable", "true");
props.put("mail.mime.base64.ignoreerrors", "true");
Session session = Session.getDefaultInstance(props, null);
Store store = session.getStore("imap");
store.connect("imap.gmail.com", 993, "<your email>", "<your password>");
Folder folder = store.getFolder(emailFolder.getText());
folder.open(Folder.READ_WRITE);
System.out.println("Total Messages:" + folder.getMessageCount());
System.out.println("Unread Messages:" + folder.getUnreadMessageCount());
messages = folder.getMessages();
for (Message mail : messages) {
if (!mail.isSet(Flags.Flag.SEEN)) {
System.out.println("***************************************************");
System.out.println("MESSAGE : \n");
System.out.println("Subject: " + mail.getSubject());
System.out.println("From: " + mail.getFrom()[0]);
System.out.println("To: " + mail.getAllRecipients()[0]);
System.out.println("Date: " + mail.getReceivedDate());
System.out.println("Size: " + mail.getSize());
System.out.println("Flags: " + mail.getFlags());
System.out.println("ContentType: " + mail.getContentType());
System.out.println("Body: \n" + getEmailBody(mail));
System.out.println("Has Attachments: " + hasAttachments(mail));
}
}
}
public boolean hasAttachments(Message email) throws Exception {
// suppose 'message' is an object of type Message
String contentType = email.getContentType();
System.out.println(contentType);
if (contentType.toLowerCase().contains("multipart/mixed")) {
// this message must contain attachment
Multipart multiPart = (Multipart) email.getContent();
for (int i = 0; i < multiPart.getCount(); i++) {
MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i);
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
System.out.println("Attached filename is:" + part.getFileName());
MimeBodyPart mimeBodyPart = (MimeBodyPart) part;
String fileName = mimeBodyPart.getFileName();
String destFilePath = System.getProperty("user.dir") + "\\Resources\\";
File fileToSave = new File(fileName);
mimeBodyPart.saveFile(destFilePath + fileToSave);
// download the pdf file in the resource folder to be read by PDFUTIL api.
PDFUtil pdfUtil = new PDFUtil();
String pdfContent = pdfUtil.getText(destFilePath + fileToSave);
System.out.println("******---------------********");
System.out.println("\n");
System.out.println("Started reading the pdfContent of the attachment:==");
System.out.println(pdfContent);
System.out.println("\n");
System.out.println("******---------------********");
Path fileToDeletePath = Paths.get(destFilePath + fileToSave);
Files.delete(fileToDeletePath);
}
}
return true;
}
return false;
}
public String getEmailBody(Message email) throws IOException, MessagingException {
String line, emailContentEncoded;
StringBuffer bufferEmailContentEncoded = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(email.getInputStream()));
while ((line = reader.readLine()) != null) {
bufferEmailContentEncoded.append(line);
}
System.out.println("**************************************************");
System.out.println(bufferEmailContentEncoded);
System.out.println("**************************************************");
emailContentEncoded = bufferEmailContentEncoded.toString();
if (email.getContentType().toLowerCase().contains("multipart/related")) {
emailContentEncoded = emailContentEncoded.substring(emailContentEncoded.indexOf("base64") + 6);
emailContentEncoded = emailContentEncoded.substring(0, emailContentEncoded.indexOf("Content-Type") - 1);
System.out.println(emailContentEncoded);
String emailContentDecoded = new String(new Base64().decode(emailContentEncoded.toString().getBytes()));
return emailContentDecoded;
}
return emailContentEncoded;
}
if you want to select a part of email title, try this
List<WebElement> gmails = driver.findElements(By.cssSelector("div.xT>div.y6>span>b"));
for(WebElement gmail : gmails){
if(gmail.getText().indexOf("Your title email") != -1){
gmail.click();
break;
}
}

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();
}
}

Categories

Resources