Javamail Getting one extra file On downloading attachments - java

I'm getting one extra file of type File on downloading attachments. I'm using MimeBodyPart.saveFile() here is my download attachment code
for (MimeBodyPart mbp : msgToDownload.getAttachmentList()) {
updateProgress(msgToDownload.getAttachmentList().indexOf(mbp),
msgToDownload.getAttachmentList().size());
mbp.saveFile(DOWNLOAD_LOCATION + mbp.getFileName());
}
here msgToDownload is a Class that take Message msg as parameter with some other parameters. And getAttachmentList() is a list of type MimeBodyPart defined as List<MimeBodyPart>
This is how I'm adding attachments to list
sb.setLength(0);
msgToRender.clearAttachments();
Message msg = msgToRender.getMsgRef();
try {
// String messageType = msg.getContentType();
sb.append(getText(msg));
if (hasAttachments(msg)) {
Multipart mp = (Multipart) msg.getContent();
for (int i = mp.getCount() - 1; i >= 0; i--) {
BodyPart bp = mp.getBodyPart(i);
MimeBodyPart mbp = (MimeBodyPart) bp;
msgToRender.addAttachment(mbp);
}
}
}catch(Exception e){
}
Extra file contain attributes of text part of the Mail. Content of extra file
-001a114fd0aa0b377d0546bb84a0 Content-Type: text/plain; charset=UTF-8 please find the attachments... --001a114fd0aa0b377d0546bb84a0 Content-Type: text/html; charset=UTF-8 please find the attachments... --001a114fd0aa0b377d0546bb84a0--

First, you should learn about the isMimeType method.
The problem is most likely that you're not handling multipart/alternative messages. See the sample code in the JavaMail FAQ.

Related

MimeBodyPart not set encoding UTF-8 for Asian languages

When I am receiving mail I am getting question mark for all the characters. I am confused where I am getting wrong. There are attachmnets which are displaying correctly only the charcters are getting displayed ???? like question mark. I have verified the body is correctly getting converted to all the asian language but before sending a mail when I again verified the message they were displaying ??.
public void addAttachmentsforMail(String text, MimeMessage message, List<File> attachments, MimeSubtype mimeSubtype) throws MessagingException {
MimeBodyPart mbpText = new MimeBodyPart();
mbpText.setHeader("Content-Type", "text/plain;charset=utf-8");
//I have verified till here the body is getting converted to respective asian languages
if(mimeSubtype.equals(MimeSubtype.HTML)) {
mbpText.setDataHandler(new DataHandler(new ByteArrayDataSource(body, "text/html")));
}
Multipart mp = new MimeMultipart();
mp.addBodyPart(mbpText);
MimeBodyPart mimeAttachment;
for (File file : attachment) {
mbpAttachment = new MimeBodyPart();
FileDataSource foo = new FileDataSource(file);
mimeAttachment.setDataHandler(new DataHandler(foo));
mimeAttachment.setHeader("Content-ID","<" + foo.getName() + ">");
mimeAttachment.setFileName(foo.getName());
mp.addBodyPart(mimeAttachment);
}
//But When I verify the message in log at here before sending the mail all the charcters were converted in to ???
message.setContent(mp);
transport.send(message)
}
This is the header of the mail
Message-ID: <-1251496143.10677.1468164058574.JavaMail.star#gmail.com>
Subject: =?UTF-8?B?5biQ5oi35Y+K5a+G56CB5o+Q6YaS?=
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_10649_-1456564573.1468164040753"
------=_Part_10649_-1456564573.1468164040753
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
The mbpText.setHeader call is having no effect because of the following mbpText.setDataHandler. If possible, use the setText methods that allow you to specify a charset. You might also want to set the System property "mail.mime.charset" to "utf-8".

How to get filename of all attachements of email?

I am trying to get the filename of all the attachements of emails using java and imap.My code is:
MimeMessage msg = (MimeMessage) messages[i];
String fileName = msg.getFileName();
System.out.println("The file name of this attachment is " + fileName);
but it prints null always even if email contain attachment..I have seen different codes on SO but none worked...and I don't know what to do if attachment is more than one .
PS:I only want to get the filename and don't want to download attachments.
First, to determine if a message may contain attachments using the following code:
// suppose 'message' is an object of type Message
String contentType = message.getContentType();
if (contentType.contains("multipart")) {
// this message may contain attachment
}
Then we must iterate through each part in the multipart to identify which part contains the attachment, as follows:
Multipart multiPart = (Multipart) message.getContent();
for (int i = 0; i < multiPart.getCount(); i++) {
MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(i);
if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
// this part is attachment
// code to save attachment...
}
}
And to save the file, you could do:
part.saveFile("D:/Attachment/" + part.getFileName());
Source
there is an easier way with apache commons mail:
final MimeMessageParser mimeParser = new MimeMessageParser(mimeMessage).parse();
final List<DataSource> attachmentList = mimeParser.getAttachmentList();
for (DataSource dataSource: attachmentList) {
final String fileName = dataSource.getName();
System.out.println("filename: " + fileName);
}
I was facing the same issue when the email contained another email as an attachment. The content-disposition of such an attachment does not contain fileName.
String contentType = message.getContentType();
List<String> attachmentFiles = new ArrayList<String>();
if(contentType.contains("multipart"))
{
Multipart multiPart = (Multipart)message.getContent();
int numberOfParts = multiPart.getCount();
for(int partCount = 0; partCount < numberOfParts; partCount++)
{
MimeBodyPart part = (MimeBodyPart)multiPart.getBodyPart(partCount);
if(Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
String fileName = part.getFileName();
String extension = FilenameUtils.getExtension(fileName);
//If the attachment is an email, fileName will be null.
if ("message/rfc822".equalsIgnoreCase(part.getContentType())) {
MimeMessage tempMessage = new MimeMessage(null, part.getInputStream());
fileName = tempMessage.getSubject()+".eml"; //all the email attachments will be converted to .eml format.
extension = "eml";
}
File tempEmailFile = File.createTempFile(messageId + "_" + partCount , "." + extension);
part.saveFile(tempEmailFile);
attachmentFiles.add(fileName);
attachmentFiles.add(tempEmailFile.getAbsolutePath());
}
}
}
Reference: javamail also extract attachments of encapsulated message Content-Type: message/rfc822

Javamail Parsing Email Body with 7BIT Content-Transfer-Encoding

I've been implementing an feature to read email file. If the file have attachment, return attachment name.
Now I'm using Javamail library to parse email file. Here is my code.
public static void parse(File file) throws Exception {
InputStream source = new FileInputStream(file);
MimeMessage message = new MimeMessage(null, source);
Multipart multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
String disposition = bodyPart.getDisposition();
if (disposition != null
&& disposition.equalsIgnoreCase(Part.ATTACHMENT)) {
System.out.println("FileName:"
+ MimeUtility.decodeText(bodyPart.getFileName()));
}
}
}
It works fine but when email file have 7bit Content-Transfer-Encoding, bodyPart.getFileName() make NullPointerException.
Is there any way to get attachement name when email is 7bit Content-Transfer-Encoding?
Sorry for my poor English.
Edited: Here is some info about my test file.
(X-Mailer: Mew version 2.2 on Emacs 21.3 / Mule 5.0 (SAKAKI)); (Mime-Version:1.0):(Content-Type: Multipart/Mixed); (Content-Transfer-Encoding: 7bit)
If my answer does not work, show the stack trace.
Use a Session, as that probably is the only thing being null.
Properties properties = new Properties();
Session session = Session.getDefaultInstance(properties);
MimeMessage message = new MimeMessage(session, source);
Not all attachments have a filename. You need to handle that case.
And you don't need to decode the filename.
You can handle the case of "attachments not having a name" in this way:
String fileName = (bodyPart.getFileName() == null) ? "your_filename"
: bodyPart.getFileName();

Attachment Id of emails in java

I am currently working with java mail api . I need to list the attachment details also wants remove the attachment from some emails and forward it to others. So i'm trying to find out the Attachment ID. How can i do it? Any suggestion will be appreciate!!!
Does this help?
private void getAttachments(Part p, File inputFolder, List<String> fileNames) throws Exception{
String disp = p.getDisposition();
if (!p.isMimeType("multipart/*") ) {
if (disp == null || (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE)))) {
String fileName = p.getFileName();
File opFile = new File(inputFolder, fileName);
((MimeBodyPart) p).saveFile(opFile);
fileNames.add(fileName);
}
}
}else{
Multipart mp = (Multipart) p.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++){
getAttachments(mp.getBodyPart(i),inputFolder, fileNames);
}
}
}
There ain't anything as an attachment ID. What your mail client displays as a message with attached contents, is really a MIME Multipart and looks like this (sample source):
From: John Doe <example#example.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="XXXXboundary text"
This is a multipart message in MIME format.
--XXXXboundary text
Content-Type: text/plain
this is the body text
--XXXXboundary text
Content-Type: text/plain;
Content-Disposition: attachment; filename="test.txt"
this is the attachment text
--XXXXboundary text--
Important things to note:
Every part in a multipart has a Content-Type
Optionally, there can be a Content-Disposition header
Single parts can be themselves multipart
Note that there is indeed a Content-ID header, but I don't think it's what you are looking for: for example, it is used in multipart/related messages to embed image/*s and text from a text/html in the same email message. You have to understand how it works and if it's used in your input.
I think your best option is to examine the Content-Disposition and the Content-Type header. The rest is guesswork, and without actual requirement one can't help with the code.
Try using the Apache Commons Email package which has a MimeMessageParser class. With the parser you can get the content id (which could be used to identify the attachment) and attachments from the email message like so:
Session session = Session.getInstance(new Properties());
ByteArrayInputStream is = new ByteArrayInputStream(rawEmail.getBytes());
MimeMessage message = new MimeMessage(session, is);
MimeMessageParser parser = new MimeMessageParser(message);
// Once you have the parser, get the content ids and attachments:
List<DataSource> attachments = parser.getContentIds.stream
.map(id -> parser.findAttachmentByCid(id))
.filter(att -> att != null)
.collect(Collectors.toList());
I have created a list here for the sake of brevity, but instead, you could create a map with the contentId as the key and the DataSource as the value.
Take a look at some more examples for using the parser in java here, or some code I wrote for a scala project here.

Reading mails sent from GMail

I am using JavaMail to read mail in my Android app. I have tried to cover all combinations i.e Mail sent/received on/from Custom Server/Gmail ID/Live ID.
The problem occurs with SOME of the mails sent from GMail WITH Attachment. I am able to receive the attachment, but the content returns javax.mail.internet.MimeMultipart#44f2e698
Here's the code used to receive and read messages:
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imap");
try {
/* Create the session and get the store for read the mail. */
Session session = Session.getInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", Username, Password);
/* Mention the folder name which you want to read. */
Folder inbox = store.getFolder("INBOX");
System.out.println("No of Unread Messages : " + inbox.getUnreadMessageCount());
/* Open the inbox using store. */
inbox.open(Folder.READ_ONLY);
Message messages[] = inbox.getMessages();
Log.d("Inbox", "Message Count: "+inbox.getMessageCount());
for (int i = messages.length - 1 ; i > 0; --i) {
Log.i("ContentType", "ContentType: "+messages[i].getContentType());
Object msgContent = messages[i].getContent();
String content = "";
/* Check if content is pure text/html or in parts */
if (msgContent instanceof Multipart) {
Multipart multipart = (Multipart) msgContent;
Log.e("BodyPart", "MultiPartCount: "+multipart.getCount());
for (int j = 0; j < multipart.getCount(); j++) {
BodyPart bodyPart = multipart.getBodyPart(j);
String disposition = bodyPart.getDisposition();
if (disposition != null && (disposition.equalsIgnoreCase("ATTACHMENT"))) { // BodyPart.ATTACHMENT doesn't work for gmail
System.out.println("Mail have some attachment");
DataHandler handler = bodyPart.getDataHandler();
System.out.println("file name : " + handler.getName());
}
else {
System.out.println("Content: "+bodyPart.getContent());
content= bodyPart.getContent().toString();
}
}
}
else
content= messages[i].getContent().toString();
What I know about the problematic mails:
getFrom also return the name i.e it comes in this format FirstName LastName &ltemailID#gmail.com&gt
MultiPart contains 2 BodyParts:
BodyPart 1 returns the content as javax.mail.internet.MimeMultipart#44f2e698
BodyPart 2 returns the correct name for attachment
BodyPart 1 returns the content as
javax.mail.internet.MimeMultipart#44f2e698
Try calling getBodyPart on the MimeMultiPart
That probably returns a MimeBodyPart you can call getContent() on
http://docs.oracle.com/javaee/5/api/javax/mail/internet/MimeBodyPart.html#content
You're probably only handling the simplest case of a text message with attachments. MIME allows much more. You need to learn about the difference between multipart/mixed, multipart/alternative, multipart/related, and multipart/signed. The JavaMail FAQ has more information on handling attachments and the msgshow.java demo program included with the JavaMail download bundle shows how to process messages with nested multiparts.

Categories