1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
package com.atlassian.mail; |
9 |
|
|
10 |
|
import com.atlassian.core.user.UserUtils; |
11 |
|
import com.opensymphony.user.EntityNotFoundException; |
12 |
|
import com.opensymphony.user.User; |
13 |
|
import org.apache.commons.io.IOUtils; |
14 |
|
import org.apache.commons.lang.StringUtils; |
15 |
|
import org.apache.commons.lang.Validate; |
16 |
|
import org.apache.log4j.Logger; |
17 |
|
|
18 |
|
import java.io.BufferedReader; |
19 |
|
import java.io.ByteArrayOutputStream; |
20 |
|
import java.io.File; |
21 |
|
import java.io.FileInputStream; |
22 |
|
import java.io.FileNotFoundException; |
23 |
|
import java.io.FileOutputStream; |
24 |
|
import java.io.IOException; |
25 |
|
import java.io.InputStream; |
26 |
|
import java.io.InputStreamReader; |
27 |
|
import java.io.Reader; |
28 |
|
import java.io.StringWriter; |
29 |
|
import java.io.UnsupportedEncodingException; |
30 |
|
import java.util.ArrayList; |
31 |
|
import java.util.List; |
32 |
|
import java.util.Locale; |
33 |
|
import java.util.StringTokenizer; |
34 |
|
import java.util.zip.ZipEntry; |
35 |
|
import java.util.zip.ZipOutputStream; |
36 |
|
import javax.activation.DataHandler; |
37 |
|
import javax.activation.DataSource; |
38 |
|
import javax.activation.FileDataSource; |
39 |
|
import javax.mail.Address; |
40 |
|
import javax.mail.BodyPart; |
41 |
|
import javax.mail.Message; |
42 |
|
import javax.mail.MessagingException; |
43 |
|
import javax.mail.Multipart; |
44 |
|
import javax.mail.Part; |
45 |
|
import javax.mail.internet.AddressException; |
46 |
|
import javax.mail.internet.InternetAddress; |
47 |
|
import javax.mail.internet.MimeBodyPart; |
48 |
|
import javax.mail.internet.MimeUtility; |
49 |
|
|
50 |
|
|
51 |
|
|
52 |
|
|
53 |
|
|
54 |
|
|
|
|
| 82.6% |
Uncovered Elements: 65 (374) |
Complexity: 101 |
Complexity Density: 0.43 |
|
55 |
|
public class MailUtils |
56 |
|
{ |
57 |
|
private static final String DEFAULT_ENCODING = "ISO-8859-1"; |
58 |
|
|
59 |
|
static final int BUFFER_SIZE = 64 * 1024; |
60 |
|
static final String MULTIPART_ALTERNATE_CONTENT_TYPE = "multipart/alternative"; |
61 |
|
static final String MULTIPART_RELATED_CONTENT_TYPE = "multipart/related"; |
62 |
|
static final String TEXT_CONTENT_TYPE = "text/plain"; |
63 |
|
static final String MESSAGE_CONTENT_TYPE = "message/rfc822"; |
64 |
|
static final String HTML_CONTENT_TYPE = "text/html"; |
65 |
|
static final String CONTENT_TYPE_X_PKCS7 = "application/x-pkcs7-signature"; |
66 |
|
static final String CONTENT_TYPE_PKCS7 = "application/pkcs7-signature"; |
67 |
|
|
68 |
|
private static final HtmlToTextConverter htmlConverter = new HtmlToTextConverter(); |
69 |
|
private static final Logger log = Logger.getLogger(MailUtils.class); |
70 |
|
|
71 |
|
|
72 |
|
|
73 |
|
|
74 |
|
private static final String CONTENT_TRANSFER_ENCODING_HEADER = "Content-Transfer-Encoding"; |
75 |
|
|
76 |
|
|
77 |
|
|
78 |
|
|
79 |
|
private static final String CONTENT_ID_HEADER = "Content-ID"; |
80 |
|
|
81 |
|
|
82 |
|
|
83 |
|
|
84 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (10) |
Complexity: 4 |
Complexity Density: 0.67 |
|
85 |
|
public static class Attachment { |
86 |
|
private final String contentType; |
87 |
|
private final String fileName; |
88 |
|
private final byte[] contents; |
89 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
90 |
2
|
public Attachment(String contentType, String fileName, byte[] contents)... |
91 |
|
{ |
92 |
2
|
this.contentType = contentType; |
93 |
2
|
this.fileName = fileName; |
94 |
2
|
this.contents = contents; |
95 |
|
} |
96 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
97 |
2
|
public String getContentType()... |
98 |
|
{ |
99 |
2
|
return contentType; |
100 |
|
} |
101 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
102 |
2
|
public byte[] getContents()... |
103 |
|
{ |
104 |
2
|
return contents; |
105 |
|
} |
106 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
107 |
2
|
public String getFilename()... |
108 |
|
{ |
109 |
2
|
return fileName; |
110 |
|
} |
111 |
|
} |
112 |
|
|
113 |
|
|
114 |
|
|
115 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 2 |
Complexity Density: 0.33 |
|
116 |
10
|
public static InternetAddress[] parseAddresses(String addresses) throws AddressException... |
117 |
|
{ |
118 |
10
|
List list = new ArrayList(); |
119 |
10
|
list.clear(); |
120 |
10
|
StringTokenizer st = new StringTokenizer(addresses, ", "); |
121 |
22
|
while (st.hasMoreTokens()) |
122 |
|
{ |
123 |
12
|
list.add(new InternetAddress(st.nextToken())); |
124 |
|
} |
125 |
10
|
return (InternetAddress[]) list.toArray(new InternetAddress[list.size()]); |
126 |
|
} |
127 |
|
|
128 |
|
|
129 |
|
|
130 |
|
|
131 |
|
|
132 |
|
|
133 |
|
|
134 |
|
|
135 |
|
|
136 |
|
|
137 |
|
|
138 |
|
|
139 |
|
|
140 |
|
|
141 |
|
|
142 |
|
|
143 |
|
|
144 |
|
|
145 |
|
@param |
146 |
|
@return |
147 |
|
@throws |
148 |
|
|
|
|
| 72.2% |
Uncovered Elements: 5 (18) |
Complexity: 6 |
Complexity Density: 0.5 |
|
149 |
12
|
public static String getBody(Message message) throws MessagingException... |
150 |
|
{ |
151 |
12
|
try |
152 |
|
{ |
153 |
12
|
String content = extractTextFromPart(message); |
154 |
|
|
155 |
11
|
if (content == null) |
156 |
|
{ |
157 |
7
|
if (message.getContent() instanceof Multipart) |
158 |
|
{ |
159 |
7
|
content = getBodyFromMultipart((Multipart) message.getContent()); |
160 |
|
} |
161 |
|
} |
162 |
|
|
163 |
11
|
if (content == null) |
164 |
|
{ |
165 |
|
|
166 |
0
|
log.info("Could not find any body to extract from the message"); |
167 |
|
} |
168 |
|
|
169 |
11
|
return content; |
170 |
|
} |
171 |
|
catch (ClassCastException cce) |
172 |
|
{ |
173 |
1
|
log.info("Exception getting the content type of message - probably not of type 'String': " + cce.getMessage()); |
174 |
1
|
return null; |
175 |
|
} |
176 |
|
catch (IOException e) |
177 |
|
{ |
178 |
0
|
log.info("IOException whilst getting message content " + e.getMessage()); |
179 |
0
|
return null; |
180 |
|
} |
181 |
|
} |
182 |
|
|
183 |
|
|
184 |
|
|
185 |
|
|
186 |
|
@param |
187 |
|
@return |
188 |
|
|
|
|
| 83.3% |
Uncovered Elements: 1 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
189 |
3
|
public static Attachment[] getAttachments(Message message) throws MessagingException, IOException... |
190 |
|
{ |
191 |
3
|
List attachments = new ArrayList(); |
192 |
|
|
193 |
3
|
if (message.getContent() instanceof Multipart) |
194 |
|
{ |
195 |
3
|
addAttachments(attachments, (Multipart)message.getContent()); |
196 |
|
} |
197 |
|
|
198 |
3
|
return (Attachment[]) attachments.toArray(new Attachment[attachments.size()]); |
199 |
|
} |
200 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (16) |
Complexity: 5 |
Complexity Density: 0.5 |
|
201 |
4
|
private static void addAttachments(List attachments, Multipart parts) throws MessagingException, IOException... |
202 |
|
{ |
203 |
13
|
for (int i = 0, n = parts.getCount(); i < n; i++) |
204 |
|
{ |
205 |
9
|
BodyPart part = parts.getBodyPart(i); |
206 |
|
|
207 |
9
|
if (isAttachment(part)) |
208 |
|
{ |
209 |
2
|
InputStream content = part.getInputStream(); |
210 |
2
|
String contentType = part.getContentType(); |
211 |
|
|
212 |
2
|
attachments.add(new Attachment(contentType, part.getFileName(), toByteArray(content))); |
213 |
|
} |
214 |
|
else |
215 |
|
{ |
216 |
7
|
try |
217 |
|
{ |
218 |
6
|
if (part.getContent() instanceof Multipart) |
219 |
|
{ |
220 |
1
|
addAttachments(attachments, (Multipart) part.getContent()); |
221 |
|
} |
222 |
|
} |
223 |
|
catch (UnsupportedEncodingException e) |
224 |
|
{ |
225 |
|
|
226 |
|
|
227 |
1
|
log.warn("Unsupported encoding found for part while trying to discover attachments. " |
228 |
|
+ "Attachment will be ignored.", e); |
229 |
|
} |
230 |
|
} |
231 |
|
} |
232 |
|
} |
233 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
234 |
9
|
private static boolean isAttachment(BodyPart part)... |
235 |
|
throws MessagingException |
236 |
|
{ |
237 |
9
|
return Part.ATTACHMENT.equals(part.getDisposition()) || (Part.INLINE.equals(part.getDisposition())); |
238 |
|
} |
239 |
|
|
240 |
|
|
241 |
|
|
242 |
|
|
243 |
|
@param |
244 |
|
@return |
245 |
|
|
|
|
| 77.8% |
Uncovered Elements: 2 (9) |
Complexity: 2 |
Complexity Density: 0.29 |
|
246 |
2
|
private static byte[] toByteArray(InputStream in) throws IOException... |
247 |
|
{ |
248 |
2
|
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
249 |
2
|
byte[] buf = new byte[512]; |
250 |
2
|
int count; |
251 |
?
|
while ((count = in.read(buf)) != -1) |
252 |
|
{ |
253 |
2
|
out.write(buf, 0, count); |
254 |
|
} |
255 |
|
|
256 |
2
|
out.close(); |
257 |
2
|
return out.toByteArray(); |
258 |
|
} |
259 |
|
|
260 |
|
|
261 |
|
|
262 |
|
|
263 |
|
|
264 |
|
@param |
265 |
|
@return |
266 |
|
@throws |
267 |
|
@deprecated |
268 |
|
|
269 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
270 |
4
|
public static User getAuthorFromSender(Message message) throws MessagingException... |
271 |
|
{ |
272 |
4
|
return getFirstValidUser(message.getFrom()); |
273 |
|
} |
274 |
|
|
275 |
|
|
276 |
|
|
277 |
|
|
278 |
|
@param |
279 |
|
@return |
280 |
|
@deprecated |
281 |
|
|
282 |
|
|
|
|
| 93.3% |
Uncovered Elements: 1 (15) |
Complexity: 6 |
Complexity Density: 0.67 |
|
283 |
8
|
public static User getFirstValidUser(Address[] addresses)... |
284 |
|
{ |
285 |
8
|
if (addresses == null || addresses.length == 0) |
286 |
2
|
return null; |
287 |
|
|
288 |
11
|
for (int i = 0; i < addresses.length; i++) |
289 |
|
{ |
290 |
9
|
if (addresses[i] instanceof InternetAddress) |
291 |
|
{ |
292 |
9
|
InternetAddress email = (InternetAddress) addresses[i]; |
293 |
|
|
294 |
9
|
try |
295 |
|
{ |
296 |
9
|
User validUser = UserUtils.getUserByEmail(email.getAddress()); |
297 |
4
|
return validUser; |
298 |
|
} |
299 |
|
catch (EntityNotFoundException e) |
300 |
|
{ |
301 |
|
|
302 |
|
} |
303 |
|
} |
304 |
|
} |
305 |
|
|
306 |
2
|
return null; |
307 |
|
} |
308 |
|
|
309 |
|
|
310 |
|
@return |
311 |
|
|
|
|
| 78.6% |
Uncovered Elements: 3 (14) |
Complexity: 5 |
Complexity Density: 0.62 |
|
312 |
2
|
public static boolean hasRecipient(String matchEmail, Message message) throws MessagingException... |
313 |
|
{ |
314 |
2
|
Address[] addresses = message.getAllRecipients(); |
315 |
|
|
316 |
2
|
if (addresses == null || addresses.length == 0) |
317 |
1
|
return false; |
318 |
|
|
319 |
1
|
for (int i = 0; i < addresses.length; i++) |
320 |
|
{ |
321 |
1
|
InternetAddress email = (InternetAddress) addresses[i]; |
322 |
|
|
323 |
1
|
if (matchEmail.compareToIgnoreCase(email.getAddress()) == 0) |
324 |
1
|
return true; |
325 |
|
} |
326 |
|
|
327 |
0
|
return false; |
328 |
|
} |
329 |
|
|
330 |
|
|
331 |
|
|
332 |
|
|
333 |
|
|
334 |
|
@param |
335 |
|
@return |
336 |
|
@throws |
337 |
|
|
|
|
| 88.9% |
Uncovered Elements: 2 (18) |
Complexity: 5 |
Complexity Density: 0.5 |
|
338 |
4
|
public static List getSenders(Message message) throws MessagingException... |
339 |
|
{ |
340 |
|
|
341 |
4
|
ArrayList senders = new ArrayList(); |
342 |
4
|
Address[] addresses = message.getFrom(); |
343 |
4
|
if (addresses != null) |
344 |
|
{ |
345 |
12
|
for (int i = 0; i < addresses.length; i++) |
346 |
|
{ |
347 |
8
|
if (addresses[i] instanceof InternetAddress) |
348 |
|
{ |
349 |
3
|
InternetAddress addr = (InternetAddress) addresses[i]; |
350 |
|
|
351 |
3
|
String emailAddress = StringUtils.trimToNull(addr.getAddress()); |
352 |
3
|
if (emailAddress != null) |
353 |
|
{ |
354 |
3
|
senders.add(emailAddress); |
355 |
|
} |
356 |
|
} |
357 |
|
} |
358 |
|
} |
359 |
4
|
return senders; |
360 |
|
} |
361 |
|
|
362 |
|
|
363 |
|
|
364 |
|
|
365 |
|
|
366 |
|
@param |
367 |
|
@return |
368 |
|
@throws |
369 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 1 |
Complexity Density: 0.17 |
|
370 |
4
|
public static MimeBodyPart createAttachmentMimeBodyPart(String path) throws MessagingException... |
371 |
|
{ |
372 |
4
|
MimeBodyPart attachmentPart = new MimeBodyPart(); |
373 |
4
|
DataSource source = new FileDataSource(path); |
374 |
4
|
attachmentPart.setDataHandler(new DataHandler(source)); |
375 |
|
|
376 |
4
|
String fileName = extractFilenameFromPath(path); |
377 |
|
|
378 |
4
|
attachmentPart.setFileName(fileName); |
379 |
4
|
return attachmentPart; |
380 |
|
} |
381 |
|
|
|
|
| 81.8% |
Uncovered Elements: 2 (11) |
Complexity: 3 |
Complexity Density: 0.43 |
|
382 |
4
|
private static String extractFilenameFromPath(String path) {... |
383 |
0
|
if (path == null) return null; |
384 |
4
|
StringTokenizer st = new StringTokenizer(path, "\\/"); |
385 |
|
|
386 |
4
|
String fileName; |
387 |
4
|
do |
388 |
|
{ |
389 |
14
|
fileName = st.nextToken(); |
390 |
|
} |
391 |
14
|
while (st.hasMoreTokens()); |
392 |
4
|
return fileName; |
393 |
|
} |
394 |
|
|
|
|
| 0% |
Uncovered Elements: 33 (33) |
Complexity: 4 |
Complexity Density: 0.13 |
|
395 |
0
|
public static MimeBodyPart createZippedAttachmentMimeBodyPart(String path) throws MessagingException... |
396 |
|
{ |
397 |
0
|
File tmpFile = null; |
398 |
0
|
String fileName = extractFilenameFromPath(path); |
399 |
|
|
400 |
0
|
try { |
401 |
0
|
tmpFile = File.createTempFile("atlassian", null); |
402 |
0
|
FileOutputStream fout = new FileOutputStream(tmpFile); |
403 |
0
|
ZipOutputStream zout = new ZipOutputStream(fout); |
404 |
0
|
zout.putNextEntry(new ZipEntry(fileName)); |
405 |
|
|
406 |
0
|
InputStream in = new FileInputStream(path); |
407 |
0
|
final byte[] buffer = new byte[ BUFFER_SIZE ]; |
408 |
0
|
int n = 0; |
409 |
0
|
while ( -1 != (n = in.read(buffer)) ) { |
410 |
0
|
zout.write(buffer, 0, n); |
411 |
|
} |
412 |
0
|
zout.close(); |
413 |
0
|
in.close(); |
414 |
0
|
log.debug("Wrote temporary zip of attachment to " + tmpFile); |
415 |
|
} catch (FileNotFoundException e) { |
416 |
0
|
String err = "Couldn't find file '"+path+"' on server: "+e; |
417 |
0
|
log.error(err, e); |
418 |
0
|
MimeBodyPart mimeBodyPart = new MimeBodyPart(); |
419 |
0
|
mimeBodyPart.setText(err); |
420 |
0
|
return mimeBodyPart; |
421 |
|
} catch (IOException e) { |
422 |
0
|
String err = "Error zipping log file '"+path+"' on server: "+e; |
423 |
0
|
log.error(err, e); |
424 |
0
|
MimeBodyPart mimeBodyPart = new MimeBodyPart(); |
425 |
0
|
mimeBodyPart.setText(err); |
426 |
0
|
return mimeBodyPart; |
427 |
|
} |
428 |
0
|
MimeBodyPart attachmentPart = new MimeBodyPart(); |
429 |
0
|
DataSource source = new FileDataSource(tmpFile); |
430 |
0
|
attachmentPart.setDataHandler(new DataHandler(source)); |
431 |
0
|
attachmentPart.setFileName(fileName+".zip"); |
432 |
0
|
attachmentPart.setHeader("Content-Type", "application/zip"); |
433 |
0
|
return attachmentPart; |
434 |
|
} |
435 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
436 |
7
|
private static String getBodyFromMultipart(Multipart multipart) throws MessagingException, IOException... |
437 |
|
{ |
438 |
7
|
StringBuffer sb = new StringBuffer(); |
439 |
7
|
getBodyFromMultipart(multipart, sb); |
440 |
7
|
return sb.toString(); |
441 |
|
} |
442 |
|
|
|
|
| 96.6% |
Uncovered Elements: 1 (29) |
Complexity: 9 |
Complexity Density: 0.53 |
|
443 |
9
|
private static void getBodyFromMultipart(Multipart multipart, StringBuffer sb) throws MessagingException, IOException... |
444 |
|
{ |
445 |
9
|
String multipartType = multipart.getContentType(); |
446 |
|
|
447 |
|
|
448 |
9
|
if(multipartType != null && compareContentType(multipartType, MULTIPART_ALTERNATE_CONTENT_TYPE)) |
449 |
|
{ |
450 |
7
|
BodyPart part = getFirstInlinePartWithMimeType(multipart, TEXT_CONTENT_TYPE); |
451 |
7
|
if(part != null) |
452 |
|
{ |
453 |
5
|
appendMultipartText(extractTextFromPart(part), sb); |
454 |
|
} |
455 |
|
else |
456 |
|
{ |
457 |
2
|
part = getFirstInlinePartWithMimeType(multipart, HTML_CONTENT_TYPE); |
458 |
2
|
appendMultipartText(extractTextFromPart(part), sb); |
459 |
|
} |
460 |
7
|
return; |
461 |
|
} |
462 |
|
|
463 |
|
|
464 |
8
|
for (int i = 0, n = multipart.getCount(); i < n; i++) |
465 |
|
{ |
466 |
6
|
BodyPart part = multipart.getBodyPart(i); |
467 |
6
|
String contentType = part.getContentType(); |
468 |
|
|
469 |
6
|
if (!Part.ATTACHMENT.equals(part.getDisposition()) && contentType != null) |
470 |
|
{ |
471 |
4
|
String content = extractTextFromPart(part); |
472 |
4
|
if (content != null) |
473 |
|
{ |
474 |
2
|
appendMultipartText(content, sb); |
475 |
|
} |
476 |
2
|
else if(part.getContent() instanceof Multipart) |
477 |
|
{ |
478 |
2
|
getBodyFromMultipart((Multipart) part.getContent(), sb); |
479 |
|
} |
480 |
|
} |
481 |
|
} |
482 |
|
} |
483 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 3 |
Complexity Density: 0.75 |
|
484 |
9
|
private static void appendMultipartText(String content, StringBuffer sb) throws IOException, MessagingException... |
485 |
|
{ |
486 |
9
|
if (content != null) |
487 |
|
{ |
488 |
8
|
if(sb.length() > 0) sb.append("\n"); |
489 |
8
|
sb.append(content); |
490 |
|
} |
491 |
|
} |
492 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (21) |
Complexity: 6 |
Complexity Density: 0.46 |
|
493 |
23
|
private static String extractTextFromPart(Part part) throws IOException, MessagingException,... |
494 |
|
UnsupportedEncodingException |
495 |
|
{ |
496 |
23
|
if (part == null) |
497 |
1
|
return null; |
498 |
|
|
499 |
22
|
String content = null; |
500 |
|
|
501 |
22
|
if (isPartPlainText(part)) |
502 |
|
{ |
503 |
10
|
try |
504 |
|
{ |
505 |
10
|
content = (String) part.getContent(); |
506 |
|
} |
507 |
|
catch (UnsupportedEncodingException e) |
508 |
|
{ |
509 |
|
|
510 |
2
|
log.warn("Found unsupported encoding '" + e.getMessage() + "'. Reading content with " |
511 |
|
+ DEFAULT_ENCODING + " encoding."); |
512 |
2
|
content = getBody(part, DEFAULT_ENCODING); |
513 |
|
} |
514 |
|
} |
515 |
12
|
else if (isPartHtml(part)) |
516 |
|
{ |
517 |
3
|
content = htmlConverter.convert((String) part.getContent()); |
518 |
|
} |
519 |
|
|
520 |
21
|
if (content == null) |
521 |
|
{ |
522 |
9
|
log.warn("Unable to extract text from MIME part with Content-Type '" + part.getContentType()); |
523 |
|
} |
524 |
|
|
525 |
21
|
return content; |
526 |
|
} |
527 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (9) |
Complexity: 1 |
Complexity Density: 0.11 |
|
528 |
2
|
private static String getBody(Part part, String charsetName) throws UnsupportedEncodingException,... |
529 |
|
IOException, MessagingException |
530 |
|
{ |
531 |
2
|
Reader input = null; |
532 |
2
|
StringWriter output = null; |
533 |
2
|
try |
534 |
|
{ |
535 |
2
|
input = new BufferedReader(new InputStreamReader(part.getInputStream(), charsetName)); |
536 |
2
|
output = new StringWriter(); |
537 |
2
|
IOUtils.copy(input, output); |
538 |
2
|
return output.getBuffer().toString(); |
539 |
|
} |
540 |
|
finally |
541 |
|
{ |
542 |
2
|
IOUtils.closeQuietly(input); |
543 |
2
|
IOUtils.closeQuietly(output); |
544 |
|
} |
545 |
|
} |
546 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (10) |
Complexity: 5 |
Complexity Density: 0.83 |
|
547 |
9
|
private static BodyPart getFirstInlinePartWithMimeType(Multipart multipart, String mimeType) throws MessagingException... |
548 |
|
{ |
549 |
20
|
for (int i = 0, n = multipart.getCount(); i < n; i++) |
550 |
|
{ |
551 |
17
|
BodyPart part = multipart.getBodyPart(i); |
552 |
17
|
String contentType = part.getContentType(); |
553 |
17
|
if (!Part.ATTACHMENT.equals(part.getDisposition()) && contentType != null && compareContentType(contentType, mimeType)) |
554 |
|
{ |
555 |
6
|
return part; |
556 |
|
} |
557 |
|
} |
558 |
3
|
return null; |
559 |
|
} |
560 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
561 |
25
|
private static boolean compareContentType(String contentType, String mimeType)... |
562 |
|
{ |
563 |
25
|
return contentType.toLowerCase().startsWith(mimeType); |
564 |
|
} |
565 |
|
|
566 |
|
|
567 |
|
|
568 |
|
|
569 |
|
|
570 |
|
@param |
571 |
|
@return |
572 |
|
@throws |
573 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
574 |
22
|
static public boolean isPartHtml(final Part part) throws MessagingException... |
575 |
|
{ |
576 |
22
|
return HTML_CONTENT_TYPE.equals(MailUtils.getContentType(part)); |
577 |
|
} |
578 |
|
|
579 |
|
|
580 |
|
|
581 |
|
|
582 |
|
@param |
583 |
|
@return |
584 |
|
@throws |
585 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
586 |
38
|
static public boolean isPartPlainText(final Part part) throws MessagingException... |
587 |
|
{ |
588 |
38
|
return TEXT_CONTENT_TYPE.equals(MailUtils.getContentType(part)); |
589 |
|
} |
590 |
|
|
591 |
|
|
592 |
|
|
593 |
|
|
594 |
|
@param |
595 |
|
@return |
596 |
|
@throws |
597 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
598 |
0
|
static public boolean isPartMessageType(final Part part) throws MessagingException... |
599 |
|
{ |
600 |
|
|
601 |
0
|
return MESSAGE_CONTENT_TYPE.equals(getContentType(part)); |
602 |
|
} |
603 |
|
|
604 |
|
|
605 |
|
|
606 |
|
|
607 |
|
@param |
608 |
|
@return |
609 |
|
@throws |
610 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
611 |
2
|
static public boolean isPartRelated(final Part part) throws MessagingException... |
612 |
|
{ |
613 |
2
|
return MULTIPART_RELATED_CONTENT_TYPE.equals(getContentType(part)); |
614 |
|
} |
615 |
|
|
616 |
|
|
617 |
|
|
618 |
|
|
619 |
|
|
620 |
|
@param |
621 |
|
@return |
622 |
|
@throws |
623 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
624 |
64
|
static public String getContentType(final Part part) throws MessagingException... |
625 |
|
{ |
626 |
64
|
checkPartNotNull(part); |
627 |
|
|
628 |
64
|
final String contentType = part.getContentType(); |
629 |
64
|
return getContentType(contentType); |
630 |
|
} |
631 |
|
|
632 |
|
|
633 |
|
|
634 |
|
|
635 |
|
@param |
636 |
|
@return |
637 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 2 |
Complexity Density: 0.33 |
|
638 |
66
|
static public String getContentType(final String headerValue)... |
639 |
|
{ |
640 |
66
|
checkHeaderValue(headerValue); |
641 |
|
|
642 |
66
|
String out = headerValue; |
643 |
|
|
644 |
66
|
final int semiColon = headerValue.indexOf(';'); |
645 |
66
|
if (-1 != semiColon) |
646 |
|
{ |
647 |
59
|
out = headerValue.substring(0, semiColon); |
648 |
|
} |
649 |
|
|
650 |
66
|
return out.trim(); |
651 |
|
} |
652 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
653 |
66
|
static private void checkHeaderValue(final String headerValue)... |
654 |
|
{ |
655 |
66
|
Validate.notEmpty(headerValue); |
656 |
|
} |
657 |
|
|
658 |
|
|
659 |
|
|
660 |
|
|
661 |
|
|
662 |
|
|
663 |
|
|
664 |
|
|
665 |
|
|
666 |
|
|
667 |
|
|
668 |
|
|
669 |
|
@param |
670 |
|
@return |
671 |
|
@throws |
672 |
|
@throws |
673 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (21) |
Complexity: 4 |
Complexity Density: 0.27 |
|
674 |
9
|
static public boolean isContentEmpty(final Part part) throws MessagingException, IOException... |
675 |
|
{ |
676 |
9
|
checkPartNotNull(part); |
677 |
|
|
678 |
9
|
boolean definitelyEmpty = false; |
679 |
9
|
final Object content = part.getContent(); |
680 |
9
|
if (null == content) |
681 |
|
{ |
682 |
1
|
definitelyEmpty = true; |
683 |
|
} |
684 |
|
else |
685 |
|
{ |
686 |
8
|
if (content instanceof String) |
687 |
|
{ |
688 |
2
|
final String stringContent = (String) content; |
689 |
2
|
definitelyEmpty = StringUtils.isBlank(stringContent); |
690 |
|
} |
691 |
|
|
692 |
8
|
if (content instanceof InputStream) |
693 |
|
{ |
694 |
6
|
final InputStream inputStream = (InputStream) content; |
695 |
6
|
try |
696 |
|
{ |
697 |
|
|
698 |
|
|
699 |
6
|
final int firstByte = inputStream.read(); |
700 |
6
|
definitelyEmpty = -1 == firstByte; |
701 |
|
|
702 |
|
} |
703 |
|
finally |
704 |
|
{ |
705 |
6
|
IOUtils.closeQuietly(inputStream); |
706 |
|
} |
707 |
|
} |
708 |
|
} |
709 |
|
|
710 |
9
|
return definitelyEmpty; |
711 |
|
} |
712 |
|
|
713 |
|
|
714 |
|
|
715 |
|
|
716 |
|
@param |
717 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
718 |
97
|
static private void checkPartNotNull(final Part part)... |
719 |
|
{ |
720 |
97
|
Validate.notNull(part, "part should not be null."); |
721 |
|
} |
722 |
|
|
723 |
|
|
724 |
|
|
725 |
|
|
726 |
|
|
727 |
|
|
728 |
|
|
729 |
|
|
730 |
|
|
731 |
|
@param |
732 |
|
@return |
733 |
|
@throws |
734 |
|
|
|
|
| 95.7% |
Uncovered Elements: 1 (23) |
Complexity: 5 |
Complexity Density: 0.33 |
|
735 |
12
|
static public boolean isPartInline(final Part part) throws MessagingException... |
736 |
|
{ |
737 |
12
|
checkPartNotNull(part); |
738 |
|
|
739 |
12
|
boolean inline = false; |
740 |
|
|
741 |
|
|
742 |
12
|
final String disposition = part.getDisposition(); |
743 |
12
|
if (Part.INLINE.equalsIgnoreCase(disposition)) |
744 |
|
{ |
745 |
1
|
final String file = part.getFileName(); |
746 |
1
|
if(!StringUtils.isBlank(file)) |
747 |
|
{ |
748 |
1
|
inline = true; |
749 |
|
} |
750 |
1
|
return inline; |
751 |
|
} |
752 |
|
|
753 |
11
|
final boolean gotContentId = MailUtils.hasContentId(part); |
754 |
11
|
if (!gotContentId) |
755 |
|
{ |
756 |
9
|
return false; |
757 |
|
} |
758 |
2
|
final boolean gotBase64 = MailUtils.isContentBase64Encoded(part); |
759 |
2
|
if (!gotBase64) |
760 |
|
{ |
761 |
1
|
return false; |
762 |
|
} |
763 |
|
|
764 |
1
|
return true; |
765 |
|
} |
766 |
|
|
|
|
| 86.7% |
Uncovered Elements: 2 (15) |
Complexity: 5 |
Complexity Density: 0.56 |
|
767 |
11
|
static private boolean hasContentId(final Part part) throws MessagingException... |
768 |
|
{ |
769 |
11
|
boolean gotContentId = false; |
770 |
11
|
final String[] contentIds = part.getHeader(MailUtils.CONTENT_ID_HEADER); |
771 |
11
|
if (null != contentIds) |
772 |
|
{ |
773 |
2
|
for (int i = 0; i < contentIds.length; i++) |
774 |
|
{ |
775 |
2
|
final String contentId = contentIds[i]; |
776 |
2
|
if (contentId != null && contentId.length() > 0) |
777 |
|
{ |
778 |
2
|
gotContentId = true; |
779 |
2
|
break; |
780 |
|
} |
781 |
|
} |
782 |
|
} |
783 |
11
|
return gotContentId; |
784 |
|
} |
785 |
|
|
786 |
|
|
787 |
|
|
788 |
|
|
789 |
|
@param |
790 |
|
@return |
791 |
|
@throws |
792 |
|
|
|
|
| 86.7% |
Uncovered Elements: 2 (15) |
Complexity: 4 |
Complexity Density: 0.44 |
|
793 |
2
|
static private boolean isContentBase64Encoded(final Part part) throws MessagingException... |
794 |
|
{ |
795 |
2
|
boolean gotBase64 = false; |
796 |
2
|
final String[] contentTransferEncodings = part.getHeader(CONTENT_TRANSFER_ENCODING_HEADER); |
797 |
2
|
if (null != contentTransferEncodings) |
798 |
|
{ |
799 |
1
|
for (int i = 0; i < contentTransferEncodings.length; i++) |
800 |
|
{ |
801 |
1
|
final String contentTransferEncoding = contentTransferEncodings[i]; |
802 |
1
|
if ("base64".equals(contentTransferEncoding)) |
803 |
|
{ |
804 |
1
|
gotBase64 = true; |
805 |
1
|
break; |
806 |
|
} |
807 |
|
} |
808 |
|
} |
809 |
|
|
810 |
2
|
return gotBase64; |
811 |
|
} |
812 |
|
|
813 |
|
|
814 |
|
|
815 |
|
|
816 |
|
|
817 |
|
@param |
818 |
|
@throws |
819 |
|
|
820 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
821 |
10
|
static public boolean isPartAttachment(final Part part) throws MessagingException... |
822 |
|
{ |
823 |
10
|
checkPartNotNull(part); |
824 |
10
|
return Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()); |
825 |
|
} |
826 |
|
|
827 |
|
|
828 |
|
|
829 |
|
|
830 |
|
|
831 |
|
|
832 |
|
|
833 |
|
@param |
834 |
|
@return |
835 |
|
@throws@see |
836 |
|
|
|
|
| 0% |
Uncovered Elements: 6 (6) |
Complexity: 3 |
Complexity Density: 0.75 |
|
837 |
0
|
static public String fixMimeEncodedFilename(final String filename) throws IOException... |
838 |
|
{ |
839 |
0
|
String newFilename = filename; |
840 |
0
|
if (filename.startsWith("=?") || filename.endsWith("?=")) |
841 |
|
{ |
842 |
0
|
newFilename = MimeUtility.decodeText(filename); |
843 |
|
} |
844 |
0
|
return newFilename; |
845 |
|
} |
846 |
|
|
847 |
|
|
848 |
|
|
849 |
|
|
850 |
|
|
851 |
|
@param |
852 |
|
@return |
853 |
|
@throws |
854 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (3) |
Complexity: 1 |
Complexity Density: 0.33 |
|
855 |
2
|
static public boolean isPartSignaturePKCS7(final Part part) throws MessagingException... |
856 |
|
{ |
857 |
2
|
MailUtils.checkPartNotNull(part); |
858 |
2
|
final String contentType = MailUtils.getContentType(part).toLowerCase(Locale.getDefault()); |
859 |
2
|
return contentType.startsWith(CONTENT_TYPE_PKCS7) || contentType.startsWith(CONTENT_TYPE_X_PKCS7); |
860 |
|
} |
861 |
|
} |