Get attachment as string from multipart/ALTERNATIVE message [duplicate] - java

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?

Related

How to convert byte[] to message with javax.mail library

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.

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

GZIP decompression code throwing exception

Trying to decompress a gzip encoded http response. Passing the following to the decompressor:
gd.decompressGZIP(response.split("\r\n\r\n")[1].getBytes());
This code splits the response and sends the latter part(gzip encoded content) to the decompressGZIP function. The "response" variable is a String which contains the full htpp response. The decompresser code is as follows.
String decompressGZIP(byte[] gzip) throws IOException {
java.io.ByteArrayInputStream bytein = new java.io.ByteArrayInputStream(gzip);
java.util.zip.GZIPInputStream gzin = new java.util.zip.GZIPInputStream(bytein);
java.io.ByteArrayOutputStream byteout = new java.io.ByteArrayOutputStream();
int res = 0;
byte buf[] = new byte[1024];
while (res >= 0) {
res = gzin.read(buf, 0, buf.length);
if (res > 0) {
byteout.write(buf, 0, res);
}
}
return (new String(byteout.toByteArray()));
}
However, I am getting an exception as follows:
Sep 03, 2013 9:19:04 PM ownproxy.ProxyThread2 run
SEVERE: null
java.util.zip.ZipException: Not in GZIP format
at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:164)
at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:78)
at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:90)
at ownproxy.GZIPDecompress.decompressGZIP(GZIPDecompress.java:18)
at ownproxy.ProxyThread2.run(InterceptionProxy2.java:84)
The data seems not to be in gzip format. Can anyone tell me what I'm doing wrong?
You are trying to decompress text converted to bytes as a GZIP compressed stream and it is not. When you encoded binary as text, it is usually mangled and information is lost which cannot be recovered.
A GZIP stream has a specific header and a CRC32 check sum at the end. Without these it is not a valid format.
Can anyone tell me what I'm doing wrong?
When you convert binary to text and back again, you don't get what you started with. Don't do this. You must keep the binary as binary and not convert it to text.

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.

Send e-mail in Pdf attachment as stream

I want to send a Pdf as an e-mail attachment (I am using the JavaMail API ). I have the Pdf (generated by jasper) as an byte[].
public InputStream exportPdfToInputStream(User user) throws ParseErrorException, MethodInvocationException, ResourceNotFoundException, JRException, IOException{
JasperPrint jasperPrint = createJasperPrintObject(user);
byte[] pdfByteArray = JasperExportManager.exportReportToPdf(jasperPrint);
return new ByteArrayInputStream(pdfByteArray);
}
Here is the code that I am using to construct the MimeBodyPart that will be the attachment:
if (arrayInputStream != null && arrayInputStream instanceof ByteArrayInputStream) {
MimeBodyPart attachment = new MimeBodyPart(arrayInputStream);
attachment.setHeader("Content-Type", "application/pdf");
mimeMultipart.addBodyPart(attachment);
}
This code gives me this error:
javax.mail.MessagingException: IOException while sending message;
nested exception is:
java.io.IOException: Error in encoded stream: needed at least 2 valid base64 characters, but only got 1 before padding character (=), the 10 most recent characters were: "\24\163\193\n\185\194\216#\208="
I have found a solution as suggested in this thread. It seems that there is a DataSource class created just for this purpose. Hope this example will help others also.
if (arrayInputStream != null && arrayInputStream instanceof ByteArrayInputStream) {
// create the second message part with the attachment from a OutputStrean
MimeBodyPart attachment= new MimeBodyPart();
ByteArrayDataSource ds = new ByteArrayDataSource(arrayInputStream, "application/pdf");
attachment.setDataHandler(new DataHandler(ds));
attachment.setFileName("Report.pdf");
mimeMultipart.addBodyPart(attachment);
}
The constructor you used is for parsing a mime part from the transport.
Your second example should work out right. You may consider
not to convert to InputStream and back, this will make unnecessary copies
add a disposition ( e.g. bp.setDisposition(Part.ATTACHMENT); )

Categories