Right now I have emails stored in a database, and I need to be able to retrieve them and download attachments If they have them. Currently, I am stumped on a way to convert the byte[] which I have stored the email as into a MailMessage or MimeMessage. I believe I have gotten to the byte[] into the Mimebody part but I am not sure how I would parse through it and pull out the attachment.
final byte[] mailMessageString = resultSet.getBytes(mailMessageIndex);
File file = new File("C:\\Users\\khurt\\Downloads\\op.txt");
List<File> attachments = new ArrayList<File>();
#SuppressWarnings("deprecation")
String mimeType = file.toURL().openConnection().getContentType();
MimeBodyPart att = new MimeBodyPart();
ByteArrayDataSource efe = new ByteArrayDataSource(mailMessageString, mimeType);
DataHandler dh = new DataHandler(efe);
att.setDataHandler(dh);
att.setFileName(bds.getName());
Multipart multipart = (Multipart) att.getContent();
multipart.addBodyPart(att);
for (int i = 0; i < multipart.getCount(); i++)
{
BodyPart bodyPart = multipart.getBodyPart(i);
if(!Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())
&& !StringUtils.isNotBlank(bodyPart.getFileName()))
{
InputStream is = bodyPart.getInputStream();
File f = new File("C:\\Users\\khurt\\Downloads\\"
+ bodyPart.getFileName());
FileOutputStream fos = new FileOutputStream(f);
byte[] buf = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buf)) != -1)
{
fos.write(buf, 0, bytesRead);
}
fos.close();
attachments.add(f);
}
else
{
System.out.println("there is nata");
}
}
There are no actual errors when it gets to the for - loop but I have not yet parsed the email to get any of the files. Is it possible to parse through a MimeBodyPart?
For Reference the emails will have the data about it then the email attachment starts with an empty line and then: (The email inst java, Stack Overflow wouldn't let me post it without formatting it, though. Also some emails don't have the header with the info about the attachment).
--_002_2733D716DEFD0D49BF462DE618263C07019302260BCVGEXCEMAIL01_
Content-Type: image/gif; name="image001.gif"
Content-Description: image001.gif
Content-Disposition: inline; filename="image001.gif"; size=1669;
creation-date="Tue, 14 Jun 2011 14:42:12 GMT";
modification-date="Tue, 14 Jun 2011 14:42:12 GMT"
Content-ID: <image001.gif#01CC2204.E828E6F0>
Content-Transfer-Encoding: base64
R0lGODlhiwA9ANUAAAAzZv/4+lvKwABVBzlstgY+q/wCBNebwwNN/l7H+ZsrHB0NuPkc/Z4kBm
jLEQFW+MqZ+yxQ8/b8wAANLb5NV/gu/y9eWwsl9/nzBZg8ZQU6+/z+/P0MFARPrv79BvcuCfobYg
JICZs+/39/Xf4NDZ47/M2ZGnvXCNqWGBoNaAgt6UlNBwcxFBcM7e5gAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAHAP8ALAAAAACLAD0AAAb/wIBw
SCwaj8ikcslsOp/QqHRKrVqv2Kx2y+16v+CweEwum8/otHrNtnoMcFBlTq9c4O189s2oaDoDgYKD
hIIPHR8XHnqMSgYMHx0PhYIhHZeYl5SDGiSNjRwMBQiElgUqIHhPcCoak4Ign2sGFYCCHacGHF0X
tg+esmS0tiEaKgbAYwWBDMFgJAyuxQwGi2kekyrOXBcfliqKjIAG21ceIAUFDLvBkuVV5+vvASEF
8/dVHAPJ+P1OBSz8CWxC4oG1gQiPnErIsEjBgw0ZAiQIp2K1iHpIDAg4hMOjWh1IbRKEoIMdjGhA
BDo0csChTJlErryAsoxKQ7hUULvYxEOv/0D8aoLxyM4cqRCphAr0oCLEoA6xlOLjU2ASAqkCOUzC
KjBECK6y3oAcRCoq2DbnNLjswELFsUcsNJxFWwEBiwtB5zK6wKLoPRMKMCgQkMBCAoYkIM5rcODA
AiELMgAQoZdRgxYAShQhQLlyngMAUhixECFABAcOFEhwIEBIAgwOBCsg0GCIhRYOhIhIDcEBAQUQ
WnhWYgIAgNJJjAvBAACF7slCTJgYEgHzYQEWAhTPHaBzCgDDi4gwPj05+AACAHAf37lICwWhiWwn
Use the MimeMessage constructor that takes an InputStream. Then access the attachments in the message in the normal fashion. See the msgshow.java sample program for example code.
Related
This question already has an answer here:
How do I read a message with an attachment and save the attachment from the content string?
(1 answer)
Closed 3 years ago.
I have a routine where I have to download an attachment from an e-mail that is multipart/ALTERNATIVE. The attachment come as string and I'm having trouble trying to save it correctly to my hard drive.
I'm able to download the e-mail content, but unable to open it, saying the archive is corrupted and it looks like there are parts missing.
When I print contentType and Encoding I get the following results:
content type of email: multipart/ALTERNATIVEboundary=000000000000b1955e0589a4192e
Content type of the part of message: TEXT/PLAIN; charset=UTF-8
Encode: QUOTED-PRINTABLE
Here's part of the e-mail I'm trying to get the attachment:
begin 600 INTFOCOA.ZIP
M4$L#!!0````(`-I[MTX#BC)`.UI$`(Y71``5````4$%$4D%/,#%?1D]#3RY4
M6%0N0U-"`%"`KW\Y[::&9%]=.4>H(KX):(05"[CW`%*7_+:QH
--------------------end
for (Message message : messages) {
Multipart multiPart = (Multipart) message.getContent();
MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(0);
String destFilePath = "C:\\Users\\fribeiro\\Desktop\\arquivo_santander\\testname";
FileOutputStream output = new FileOutputStream(destFilePath);
InputStream input = part.getInputStream();
byte[] buffer = new byte[4096];
int byteRead;
while ((byteRead = input.read(buffer)) != -1) {
output.write(buffer, 0, byteRead);
}
output.close();
}
I'm trying to get the INTFOCOA.ZIP file. thanks in advance.
The content of that part is uuencoding if a zip file.
You need to apply a uudecode algorithm on it to get the zip file.
E.g. see Does Java has any standard mechanism for uudecoding?
I need to copy the entire body content of an Internet mail to a new Notes document.
Object internetMsgBody = internetMsg.getContent();
MIMEEntity notesBodyItem = notesDocument.createMIMEEntity("Body");
Stream mimeStream = dominoSession.createStream();
...?...
notesBodyItem.setContentFromBytes(mimeStream, msgContentType,
MIMEEntity.ENC_NONE);
The internetMsgBody can be String, MimeMultiPart or InputStream (according to the documentation). I know how I can handle String :) but for the other Object types, I need some help. There is no need for any MIME or Parts content type handling.
Thanks!
In Notes, a multi-part MIME message is represented as a set of items of the same name (usually Body) each of which is TYPE_MIME. Think of a MIMEEntity instance as corresponding to a single one of these items. In other words, a MIMEEntity represents a single MIME part.
So if your input is a multi-part MIME message, you may have to parse the message into individual parts and create a MIMEEntity for each. Unfortunately, the Java back-end classes don't include a MIME parser. Of course, your question states that internetMsg.getContent() may return a MimeMultipart. If that's the case, it sounds like the MIME is already parsed for you.
Either way -- whether your input is a stream of many parts or a MimeMultipart -- I suggest you look at MimeMessageParser.java from the XPages Extension Library. It uses mime4j to parse an input stream. If there are multiple parts in the stream, it uses MIMEEntity to write each part as a separate item. Although the use of mime4j doesn't sound relevant, you may find some useful hints in that code. It implements a very similar use case.
Thanks Dave, you pointed me to the missing part. My solution (so far) is to create a parent Domino MIMEEntity which holds all MIME Parts as children.
Code excerpt:
MimeMultipart mimeMultiparts = (MimeMultipart) message.getContent();
int partCount = mimeMultiparts.getCount();
MIMEEntity dominoParentItem = mailDocument.createMIMEEntity("Body");
Stream dominoStream = dbGetSession().createStream();
for (int counter = 0; counter < partCount; counter++) {
MimeBodyPart mimeBodyPart = (MimeBodyPart) mimeMultiparts.getBodyPart(counter);
MIMEEntity dominoChildItem = dominoParentItem.createChildEntity();
InputStream input = mimeBodyPart.getRawInputStream();
byte[] buffer = new byte[4096];
int lengthTotal = 0;
int length = 0;
while (true) {
length = input.read(buffer);
if (length < 1)
break;
lengthTotal += length;
dominoStream.write(buffer);
}
String encodingType = mimeBodyPart.getEncoding();
int dominoEncoding = MIMEEntity.ENC_NONE;
if (encodingType != null) {
if (encodingType.toLowerCase().contains("base64"))
dominoEncoding = MIMEEntity.ENC_BASE64;
if (encodingType.toLowerCase().contains("7bit"))
dominoEncoding = MIMEEntity.ENC_IDENTITY_7BIT;
if (encodingType.toLowerCase().contains("8bit"))
dominoEncoding = MIMEEntity.ENC_IDENTITY_8BIT;
if (encodingType.toLowerCase().contains("binary"))
dominoEncoding = MIMEEntity.ENC_IDENTITY_BINARY;
if (encodingType.toLowerCase().contains("quoted-printable"))
dominoEncoding = MIMEEntity.ENC_QUOTED_PRINTABLE;
if (dominoEncoding == MIMEEntity.ENC_NONE)
dominoEncoding = MIMEEntity.ENC_EXTENSION;
}
dominoChildItem.setContentFromBytes(dominoStream, mimeBodyPart.getContentType(), dominoEncoding);
Just to follow up on this problem:
I came up with a much easier and more elegant solution. There is a writeTo() method which streams-out all the multipart data. This can then be streamed in again to a Domino stream which fills in the MIMEEntry body item.
case "javax.mail.internet.MimeMultipart": {
// Create input stream with content of MIME data
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
message.writeTo(outputStream);
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
outputStream.close();
// Create Domino stream and fill it with the MIME data
Stream dominoStream = dbGetSession().createStream();
byte[] buffer = new byte[4096];
int lengthTotal = 0;
int length = 0;
while (true) {
length = inputStream.read(buffer);
if (length < 1)
break;
lengthTotal += length;
dominoStream.write(buffer);
}
inputStream.close();
// Create Domino MIME "Body" item with content of MIME data
MIMEEntity dominoMIMEItem = mailDocument.createMIMEEntity("Body");
dominoMIMEItem.setContentFromBytes(dominoStream, "", MIMEEntity.ENC_NONE);
}
Currently I am attaching files (small) in mail as follows:
byte[] byteArray = IOUtils.toByteArray(new FileInputStream(file));
MimeBodyPart messageBodyPart = new PreencodedMimeBodyPart("base64");
String contentType = "application/octet-stream";
String base64Content = new String(Base64.encodeBase64(byteArray));
messageBodyPart.setContent(base64Content, contentType);
messageBodyPart.setFileName(MimeUtility.encodeText(attachment.getFileName(),
CharEncoding.UTF_8, null));
messageBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
multipart.addBodyPart(messageBodyPart);
But reading the file to a byte[] at a time won't work for large files. But at the end I want to put attachments in base64 encoded string in email. So how can I tackle large files in attachment here?
Use MimeBodyPart.attachFile:
messageBodyPart.attachFile(file, "application/octet-stream", "base64");
The file won't be read into memory, it will be encoded "on the fly" as the message is sent.
Well you can try with it to send whatever file you want. Also any number of files.
/**
Multi part message email
**/
Multipart multipart = new MimeMultipart();
//Add atachments
String[] attachments = new String[2];
attachments[0] = "your_complete_path.pdf";
attachments[1] = "your_complete_path.txt";
if(attachments != null && attachments.length > 0) {
for (String str : attachments) {
MimeBodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(str);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(source.getName());
multipart.addBodyPart(messageBodyPart);
}
}
message.setContent(multipart);
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();
I use range hader, but not create correct file.
if I send Range bytes=0-8999 file weighs 9000 bytes and correct work.
if I send Range bytes=0-8999,9000-9999 file weighs 10213 bytes and NOT correct work.
File type mp3.
What could be wrong?
HttpGet first = new HttpGet("http://cs4832.vkontakte.ru/u50184979/audio/ef64581d913c.mp3");
first.addHeader("Accept-Ranges", "bytes");
first.addHeader("Range", "bytes=0-8999,9000-9999");
//first.addHeader("Accept-Ranges", "bytes");
HttpResponse response = httpclient.execute(first, localContext);
InputStream instream = response.getEntity().getContent();
File f = new File("outFile1.mp3");
OutputStream out = new FileOutputStream(f);
byte buf[] = new byte[1024];
int len;
while ((len = instream.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
instream.close();
See RFC 2616, Section 14.16:
When an HTTP message includes the content of multiple ranges (for example, a response to a request for multiple non-overlapping ranges), these are transmitted as a multipart message. The multipart media type used for this purpose is "multipart/byteranges" as defined in Appendix 19.2. See Appendix 19.6.3 for a compatibility issue.