Skip to content

Package: MSMessage

MSMessage

nameinstructionbranchcomplexitylinemethod
MSMessage(Session, InputStream)
M: 7 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
MSMessage(Session, MimeMessage)
M: 39 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
getContentType()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getDisposition()
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getEncoding()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
isMSMessage(MimeMessage)
M: 19 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
parse(InputStream)
M: 134 C: 0
0%
M: 22 C: 0
0%
M: 12 C: 0
0%
M: 29 C: 0
0%
M: 1 C: 0
0%
toString(byte[], int, int)
M: 29 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Distribution License v. 1.0, which is available at
6: * http://www.eclipse.org/org/documents/edl-v10.php.
7: *
8: * SPDX-License-Identifier: BSD-3-Clause
9: */
10:
11: import java.io.*;
12: import jakarta.mail.*;
13: import jakarta.mail.internet.*;
14: import jakarta.mail.util.StreamProvider;
15: import jakarta.mail.util.StreamProvider.EncoderTypes;
16: import jakarta.activation.*;
17:
18: /**
19: * This class models a UUEncoded Message sent from MS Outlook etc. <p>
20: *
21: * The message structure looks like this :=
22: * [text body] [uuencoded attachment]*
23: * <p>
24: * i.e., an optional text/plain main-body, followed by zero or more
25: * UUENCODE-ed attachments.
26: *
27: * @author John Mani
28: * @author Bill Shannon
29: * @see jakarta.mail.internet.MimeMessage
30: */
31:
32: public class MSMessage extends MimeMessage {
33: private String type;
34:
35: /**
36: * Constructor that converts a MimeMessage object into a MSMessage.
37: *
38: * @exception MessagingException if the given MimeMessage
39: * is not a non-MIME MS message, or if an
40: * IOException occurs when accessing the given
41: * MimeMessage object
42: */
43: public MSMessage(Session session, MimeMessage msg)
44:                 throws MessagingException {
45:         super(session);
46:
47:•        if (!isMSMessage(msg)) // sanity check
48:          throw new MessagingException("Not an MS message");
49:
50:         class FastByteArrayOutputStream extends ByteArrayOutputStream {
51:          ByteArrayInputStream toByteArrayInputStream() {
52:                 return new ByteArrayInputStream(buf, 0, count);
53:          }
54:         }
55:
56:         // extract the bytes of the given message
57:         // ByteArrayOutputStream bos = new ByteArrayOutputStream();
58:         FastByteArrayOutputStream bos = new FastByteArrayOutputStream();
59:         try {
60:          msg.writeTo(bos);
61:         } catch (IOException ioex) {
62:          throw new MessagingException("IOException", ioex);
63:         } catch (Exception ex) {
64:          throw new MessagingException("Exception", ex);
65:         }
66:         //parse(new ByteArrayInputStream(bos.toByteArray()));
67:         parse(bos.toByteArrayInputStream());
68: }
69:
70: /**
71: * Constructor to create a MSMessage from the given InputStream.
72: */
73: public MSMessage(Session session, InputStream is)
74:                 throws MessagingException {
75:         super(session); // setup headerstore etc
76:         parse(is);
77: }
78:
79: // parse input stream
80: protected void parse(InputStream is) throws MessagingException {
81:         // Create a buffered input stream for efficiency
82:•        if (!(is instanceof ByteArrayInputStream) &&
83:          !(is instanceof BufferedInputStream))
84:          is = new BufferedInputStream(is);
85:
86:         // Load headerstore
87:         headers.load(is);
88:
89:         /*
90:          * Load the content into a byte[].
91:          * This byte[] is shared among the bodyparts.
92:          */
93:         try {
94:          ByteArrayOutputStream bos = new ByteArrayOutputStream();
95:          int b;
96:          // XXX - room for performance improvement
97:•         while ((b = is.read()) != -1)
98:                 bos.write(b);
99:          content = bos.toByteArray();
100:         } catch (IOException ioex) {
101:          throw new MessagingException("IOException", ioex);
102:         }
103:
104:         /*
105:          * Check whether this is multipart.
106:          */
107:         boolean isMulti = false;
108:         // check for presence of X-MS-Attachment header
109:         String[] att = getHeader("X-MS-Attachment");
110:•        if (att != null && att.length > 0)
111:          isMulti = true;
112:         else {
113:          /*
114:          * Fall back to scanning the content.
115:          * We scan the content until we find a sequence that looks
116:          * like the start of a uuencoded block, i.e., "<newline>begin".
117:          * If found, we claim that this is a multipart message.
118:          */
119:•         for (int i = 0; i < content.length; i++) {
120:                 int b = content[i] & 0xff; // mask higher byte
121:•                if (b == '\r' || b == '\n') {
122:                  // start of a new line
123:•                 if ((i + 5) < content.length) {
124:                         // can there be a "begin" now?
125:                         String s = toString(content, i+1, i+6);
126:•                        if (s.equalsIgnoreCase("begin")) {
127:                          isMulti= true;
128:                          break;
129:                         }
130:                  }
131:                 }
132:          }
133:         }
134:
135:•        if (isMulti) {
136:          type = "multipart/mixed";
137:          dh = new DataHandler(new MSMultipartDataSource(this, content));
138:         } else {
139:          type = "text/plain"; // charset = ?
140:          dh = new DataHandler(new MimePartDataSource(this));
141:         }
142:
143:         modified = false;
144: }
145:
146: /**
147: * Return content-type
148: */
149: public String getContentType() throws MessagingException {
150:         return type;
151: }
152:
153: /**
154: * Return content-disposition
155: */
156: public String getDisposition() throws MessagingException {
157:         return "inline";
158: }
159:
160: /**
161: * Return content-transfer-encoding
162: */
163: public String getEncoding() throws MessagingException {
164:         return EncoderTypes.BIT7_ENCODER.getEncoder();
165: }
166:
167: /**
168: * Check whether the given MimeMessage object represents a
169: * non-MIME message sent by Outlook. Such a message will
170: * have no MIME-Version header, may have an X-Mailer header
171: * that includes the word "Microsoft", and will have at least
172: * one X-MS-Attachment header.
173: */
174: public static boolean isMSMessage(MimeMessage msg)
175:                         throws MessagingException {
176:         // Check whether the MIME header is present
177:•        if (msg.getHeader("MIME-Version") != null)
178:          // MIME-Version header present, should be a MIME message
179:          return false;
180:
181:         /*
182:          * XXX - disabled X-Mailer check because many sample messages
183:          * I saw didn't have an X-Mailer header at all.
184:          */
185:         if (false) {
186:         // Check X-Mailer
187:         String mailer = msg.getHeader("X-mailer", null);
188:         if (mailer == null) // No X-mailer ?
189:          return false; // Oh well !
190:         if (mailer.indexOf("Microsoft") == -1) // Not MS stuff ?
191:          return false;
192:         }
193:
194:         // Check X-MS-Attachment header
195:         // XXX - not all such messages have this header
196:         String[] att = msg.getHeader("X-MS-Attachment");
197:•        if (att == null || att.length == 0)
198:          return false;
199:
200:         return true;
201: }
202:
203: // convert given byte array of ASCII characters to string
204: static String toString(byte[] b, int start, int end) {
205:         int size = end - start;
206:         char[] theChars = new char[size];
207:
208:•        for (int i = 0, j = start; i < size; )
209:          theChars[i++] = (char)b[j++];
210:         return new String(theChars);
211: }
212: }