| 68 | 1 /* | 
|  | 2 Copyright (c) 2008  Franklin Schmidt <fschmidt@gmail.com> | 
|  | 3 | 
|  | 4 Permission is hereby granted, free of charge, to any person obtaining a copy | 
|  | 5 of this software and associated documentation files (the "Software"), to deal | 
|  | 6 in the Software without restriction, including without limitation the rights | 
|  | 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
|  | 8 copies of the Software, and to permit persons to whom the Software is | 
|  | 9 furnished to do so, subject to the following conditions: | 
|  | 10 | 
|  | 11 The above copyright notice and this permission notice shall be included in | 
|  | 12 all copies or substantial portions of the Software. | 
|  | 13 | 
|  | 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
|  | 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
|  | 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
|  | 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
|  | 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
|  | 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
|  | 20 THE SOFTWARE. | 
|  | 21 */ | 
|  | 22 | 
|  | 23 package fschmidt.util.mail.javamail; | 
|  | 24 | 
|  | 25 import fschmidt.util.java.IoUtils; | 
|  | 26 import fschmidt.util.mail.AlternativeMultipartContent; | 
|  | 27 import fschmidt.util.mail.Content; | 
|  | 28 import fschmidt.util.mail.FileAttachmentContent; | 
|  | 29 import fschmidt.util.mail.HtmlTextContent; | 
|  | 30 import fschmidt.util.mail.Mail; | 
|  | 31 import fschmidt.util.mail.MailAddress; | 
|  | 32 import fschmidt.util.mail.MailAddressException; | 
|  | 33 import fschmidt.util.mail.MailEncodingException; | 
|  | 34 import fschmidt.util.mail.MailException; | 
|  | 35 import fschmidt.util.mail.MailParseException; | 
|  | 36 import fschmidt.util.mail.MixedMultipartContent; | 
|  | 37 import fschmidt.util.mail.MultipartContent; | 
|  | 38 import fschmidt.util.mail.PlainTextContent; | 
|  | 39 import fschmidt.util.mail.TextAttachmentContent; | 
|  | 40 import fschmidt.util.mail.TextContent; | 
|  | 41 import fschmidt.util.mail.UnsupportedContent; | 
|  | 42 | 
|  | 43 import javax.activation.CommandMap; | 
|  | 44 import javax.activation.MailcapCommandMap; | 
|  | 45 import javax.mail.Address; | 
|  | 46 import javax.mail.Message; | 
|  | 47 import javax.mail.MessagingException; | 
|  | 48 import javax.mail.Part; | 
|  | 49 import javax.mail.Session; | 
|  | 50 import javax.mail.internet.AddressException; | 
|  | 51 import javax.mail.internet.ContentType; | 
|  | 52 import javax.mail.internet.HeaderTokenizer; | 
|  | 53 import javax.mail.internet.InternetAddress; | 
|  | 54 import javax.mail.internet.MimeBodyPart; | 
|  | 55 import javax.mail.internet.MimeMessage; | 
|  | 56 import javax.mail.internet.MimeMultipart; | 
|  | 57 import javax.mail.internet.MimePart; | 
|  | 58 import javax.mail.internet.MimeUtility; | 
|  | 59 import javax.mail.internet.ParseException; | 
|  | 60 import java.io.ByteArrayInputStream; | 
|  | 61 import java.io.ByteArrayOutputStream; | 
|  | 62 import java.io.IOException; | 
|  | 63 import java.io.InputStream; | 
|  | 64 import java.io.InputStreamReader; | 
|  | 65 import java.io.UnsupportedEncodingException; | 
|  | 66 import java.util.Date; | 
|  | 67 import java.util.Enumeration; | 
|  | 68 | 
|  | 69 | 
|  | 70 public class MailImpl implements Mail { | 
|  | 71 	private static final Session nullSession = null; | 
|  | 72 | 
|  | 73 	class MyMimeMessage extends MimeMessage { | 
|  | 74 		MyMimeMessage() { | 
|  | 75 			super(nullSession); | 
|  | 76 		} | 
|  | 77 | 
|  | 78 		MyMimeMessage(InputStream is) throws MessagingException { | 
|  | 79 			super(nullSession,is); | 
|  | 80 		} | 
|  | 81 | 
|  | 82 		MyMimeMessage(MimeMessage msg) throws MessagingException { | 
|  | 83 			super(msg); | 
|  | 84 		} | 
|  | 85 | 
|  | 86 		void setSession(Session session) { | 
|  | 87 			this.session = session; | 
|  | 88 		} | 
|  | 89 | 
|  | 90 		protected void updateHeaders() | 
|  | 91 			throws MessagingException | 
|  | 92 		{ | 
|  | 93 			super.updateHeaders(); | 
|  | 94 			if( messageID != null ) | 
|  | 95 				setHeader( "Message-ID", messageID ); | 
|  | 96 		} | 
|  | 97 	} | 
|  | 98 | 
|  | 99 	final MyMimeMessage msg; | 
|  | 100 	private String messageID = null; | 
|  | 101 | 
|  | 102 	public MailImpl() { | 
|  | 103 		this.msg = new MyMimeMessage(); | 
|  | 104 	} | 
|  | 105 | 
|  | 106 	public MailImpl(String rawInput) { | 
|  | 107 		try { | 
|  | 108 			this.msg = new MyMimeMessage(new ByteArrayInputStream(rawInput.getBytes("ISO-8859-1"))); | 
|  | 109 		} catch (UnsupportedEncodingException e) { | 
|  | 110 			throw new RuntimeException(e); | 
|  | 111 		} catch(MessagingException e) { | 
|  | 112 			throw MailImpl.e(e); | 
|  | 113 		} | 
|  | 114 	} | 
|  | 115 | 
|  | 116 	MailImpl(MimeMessage msg) throws MessagingException { | 
|  | 117 		this.msg = new MyMimeMessage(msg); | 
|  | 118 	} | 
|  | 119 | 
|  | 120 	public String getType() { | 
|  | 121 		return "message"; | 
|  | 122 	} | 
|  | 123 | 
|  | 124 	public String getSubtype() { | 
|  | 125 		return "rfc822"; | 
|  | 126 	} | 
|  | 127 | 
|  | 128 	public Content getContent() throws MailException { | 
|  | 129 		try { | 
|  | 130             return getPart(msg); | 
|  | 131 		} catch(MessagingException e) { | 
|  | 132 			throw MailImpl.e(e); | 
|  | 133 		} catch(IOException e) { | 
|  | 134 			throw MailImpl.e(e); | 
|  | 135 		} | 
|  | 136 	} | 
|  | 137 | 
|  | 138 	private static Content getPart(Part part) throws MessagingException, IOException { | 
|  | 139 		String ct = part.getContentType().toLowerCase(); | 
|  | 140 		int end = ct.indexOf(';'); | 
|  | 141 		if( end != -1 ) | 
|  | 142 			ct = ct.substring(0,end); | 
|  | 143 		String[] a = ct.split("/"); | 
|  | 144 		if (a.length==0) | 
|  | 145 			return new UnsupportedContent(part.getInputStream(), null, null); | 
|  | 146 		String type = a[0]; | 
|  | 147 		String subtype = a.length>1 ? a[1]:""; | 
|  | 148 		if( type.equals("text") ) { | 
|  | 149 		    String text = null; | 
|  | 150 		    Object obj; | 
|  | 151 			try { | 
|  | 152 				obj = part.getContent(); | 
|  | 153 			} catch (UnsupportedEncodingException e) { | 
|  | 154 				obj = IoUtils.readAll(new InputStreamReader(part.getInputStream(), "ISO-8859-1")); | 
|  | 155 				if (!isAllAscii((String)obj)) | 
|  | 156 					return new UnsupportedContent(obj, type, subtype); | 
|  | 157 			} | 
|  | 158 			if( Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition()) ) | 
|  | 159 		    	return new FileAttachmentContentImpl((MimePart)part, type, subtype); | 
|  | 160 		    if( obj instanceof String ) { | 
|  | 161 		    	text = (String)obj; | 
|  | 162 		    } else if( obj instanceof InputStream ) { | 
|  | 163 		    	try { | 
|  | 164 		    		String charset = null; | 
|  | 165 		    		String filename = null; | 
|  | 166 		    		try { | 
|  | 167 		    			ContentType contentType = new ContentType(part.getContentType()); | 
|  | 168 		    			charset = MimeUtility.javaCharset(contentType.getParameter("charset")); | 
|  | 169 		    			filename = contentType.getParameter("name"); | 
|  | 170 		    		} catch (ParseException e) {} | 
|  | 171 		    		text = IoUtils.readAll(new InputStreamReader((InputStream)obj,charset!=null?charset:"ISO-8859-1")); | 
|  | 172 		    	} catch (IOException e) { | 
|  | 173 		    		return new UnsupportedContent(part.getInputStream(), type, subtype); | 
|  | 174 		    	} catch (MessagingException e) { | 
|  | 175 		    		return new UnsupportedContent(part.getInputStream(), type, subtype); | 
|  | 176 		    	} | 
|  | 177 		    } else { | 
|  | 178 		    	return new FileAttachmentContentImpl((MimePart)part, type, subtype); | 
|  | 179 		    } | 
|  | 180 			if( subtype.equals("plain") || subtype.equals("")) | 
|  | 181 				return new PlainTextContent(text); | 
|  | 182 			if( subtype.equals("html") ) | 
|  | 183 				return new HtmlTextContent(text); | 
|  | 184 			return new TextContent(subtype,text); | 
|  | 185 		} | 
|  | 186 		if( type.equals("multipart") && part.getContent() instanceof MimeMultipart) { | 
|  | 187 			Content[] parts = getParts( (MimeMultipart)part.getContent() ); | 
|  | 188 			if( subtype.equals("alternative") ) | 
|  | 189 				return new AlternativeMultipartContent(parts); | 
|  | 190 			if( subtype.equals("mixed") ) | 
|  | 191 				return new MixedMultipartContent(parts); | 
|  | 192 			if( subtype.equals("signed") ) | 
|  | 193 				return new MixedMultipartContent(parts); | 
|  | 194 			return new MultipartContent(subtype,parts); | 
|  | 195 		} | 
|  | 196 		if( type.equals("message") && subtype.equals("rfc822") && part.getContent() instanceof MimeMessage) { | 
|  | 197 			MimeMessage mm = (MimeMessage)part.getContent(); | 
|  | 198 			return new MailImpl(mm); | 
|  | 199 		} | 
|  | 200 		/* | 
|  | 201 		if( type.equals("application") ) { | 
|  | 202 			if( subtype.equals("pgp-signature") ) | 
|  | 203 				return new PlainTextContent((String)obj); | 
|  | 204 				} | 
|  | 205 		*/ | 
|  | 206 		return new FileAttachmentContentImpl((MimePart)part, type, subtype); | 
|  | 207 	} | 
|  | 208 | 
|  | 209 	private static Content[] getParts(MimeMultipart mp) throws MessagingException, IOException { | 
|  | 210 		Content[] parts = new Content[mp.getCount()]; | 
|  | 211 		for( int i=0; i<parts.length; i++ ) { | 
|  | 212 			parts[i] = getPart(mp.getBodyPart(i)); | 
|  | 213 		} | 
|  | 214 		return parts; | 
|  | 215 	} | 
|  | 216 | 
|  | 217 	private static boolean isAllAscii(String s) { | 
|  | 218 		for (int i=0;i<s.length();i++) | 
|  | 219 			if (nonascii((int)s.charAt(i))) return false; | 
|  | 220 		return true; | 
|  | 221 	} | 
|  | 222 | 
|  | 223 	// copied from javamail | 
|  | 224 	private static boolean nonascii(int b) { | 
|  | 225     	return b >= 0177 || (b < 040 && b != '\r' && b != '\n' && b != '\t'); | 
|  | 226     } | 
|  | 227 | 
|  | 228 	public void setContent(Content content) throws MailException { | 
|  | 229 		try { | 
|  | 230 			setPart(msg,content); | 
|  | 231 		} catch(MessagingException e) { | 
|  | 232 			throw MailImpl.e(e); | 
|  | 233 		} | 
|  | 234 	} | 
|  | 235 | 
|  | 236 	private final static String defaultCharset = MimeUtility.quote( | 
|  | 237 			MimeUtility.mimeCharset(MimeUtility.getDefaultJavaCharset()), | 
|  | 238 			HeaderTokenizer.MIME); | 
|  | 239 | 
|  | 240 	private static void setPart(Part part,Content content) throws MessagingException { | 
|  | 241 		if( content instanceof PlainTextContent ) { | 
|  | 242 			TextContent textContent = (TextContent)content; | 
|  | 243 			// Using part.setContent breaks the encoding of non-ascii email | 
|  | 244 			// because com.sun.mail.handlers.text_plain assumes us-ascii charset | 
|  | 245 			// if charset is not specified. Part.setText handles this correctly. | 
|  | 246 			part.setText( textContent.getText() ); | 
|  | 247 			return; | 
|  | 248 		} | 
|  | 249 		if( content instanceof TextAttachmentContent ) { | 
|  | 250 			TextAttachmentContent textContent = (TextAttachmentContent)content; | 
|  | 251 			// Use same logic as javamail MimeBodyPart.setText() to determine charset | 
|  | 252 			String charset = isAllAscii(textContent.getText())?"us-ascii":defaultCharset; | 
|  | 253 			part.setContent( textContent.getText(), content.getType()+'/'+content.getSubtype()+"; charset="+charset); | 
|  | 254 			part.setFileName( textContent.getFilename() ); | 
|  | 255 			return; | 
|  | 256 		} | 
|  | 257 		if( content instanceof FileAttachmentContent ) { | 
|  | 258 			FileAttachmentContent fileContent = (FileAttachmentContent)content; | 
|  | 259 			byte[] contents = new byte[0]; | 
|  | 260 			InputStream is = fileContent.getInputStream(); | 
|  | 261 			try { | 
|  | 262 				contents = IoUtils.readAll(is); | 
|  | 263 			} catch (IOException e) { | 
|  | 264 				throw new RuntimeException(e); | 
|  | 265 			} finally { | 
|  | 266 				try { | 
|  | 267 					is.close(); | 
|  | 268 				} catch (IOException e) { | 
|  | 269 					throw new RuntimeException(e); | 
|  | 270 				} | 
|  | 271 			} | 
|  | 272 			part.setContent( contents, content.getType()+'/'+content.getSubtype()); | 
|  | 273 			part.setFileName( fileContent.getFileName() ); | 
|  | 274 			return; | 
|  | 275 		} | 
|  | 276 		if( content instanceof TextContent ) { | 
|  | 277 			TextContent textContent = (TextContent)content; | 
|  | 278 			// Use same logic as javamail MimeBodyPart.setText() to determine charset | 
|  | 279 			String charset = isAllAscii(textContent.getText())?"us-ascii":defaultCharset; | 
|  | 280 			part.setContent( textContent.getText(), content.getType()+'/'+content.getSubtype()+"; charset="+charset); | 
|  | 281 			return; | 
|  | 282 		} | 
|  | 283 		if( content instanceof MultipartContent ) { | 
|  | 284 			part.setContent( makeMimeMultipart((MultipartContent)content) ); | 
|  | 285 			return; | 
|  | 286 		} | 
|  | 287 		if( content instanceof MailImpl ) { | 
|  | 288 			MailImpl mail = (MailImpl)content; | 
|  | 289 			part.setContent( mail.msg, "message/rfc822" ); | 
|  | 290 			part.setDisposition(Part.ATTACHMENT); | 
|  | 291 			return; | 
|  | 292 		} | 
|  | 293 		throw new UnsupportedOperationException("content class "+content.getClass()); | 
|  | 294 	} | 
|  | 295 | 
|  | 296 	private static MimeMultipart makeMimeMultipart(MultipartContent mc) throws MessagingException { | 
|  | 297 		MimeMultipart mp = new MimeMultipart(mc.getSubtype()); | 
|  | 298 		Content[] parts = mc.getParts(); | 
|  | 299 		for( int i=0; i<parts.length; i++ ) { | 
|  | 300 			MimeBodyPart mbp = new MimeBodyPart(); | 
|  | 301 			setPart(mbp,parts[i]); | 
|  | 302 			mp.addBodyPart(mbp); | 
|  | 303 		} | 
|  | 304 		return mp; | 
|  | 305 	} | 
|  | 306 | 
|  | 307 	public String getSubject() throws MailException { | 
|  | 308 		try { | 
|  | 309 			return msg.getSubject(); | 
|  | 310 		} catch(MessagingException e) { | 
|  | 311 			throw MailImpl.e(e); | 
|  | 312 		} | 
|  | 313 	} | 
|  | 314 | 
|  | 315 	public void setSubject(String subject) throws MailException { | 
|  | 316 		try { | 
|  | 317 			msg.setSubject(subject); | 
|  | 318 		} catch(MessagingException e) { | 
|  | 319 			throw MailImpl.e(e); | 
|  | 320 		} | 
|  | 321 	} | 
|  | 322 | 
|  | 323 	static InternetAddress addr(MailAddress addr) | 
|  | 324 		throws MessagingException, UnsupportedEncodingException | 
|  | 325 	{ | 
|  | 326 		return addr.getDisplayName() == null | 
|  | 327 			? new InternetAddress(addr.getAddrSpec()) | 
|  | 328 			: new InternetAddress(addr.getAddrSpec(),addr.getDisplayName()) | 
|  | 329 		; | 
|  | 330 	} | 
|  | 331 | 
|  | 332 	static InternetAddress[] addr(MailAddress[] addrs) | 
|  | 333 		throws MessagingException, UnsupportedEncodingException | 
|  | 334 	{ | 
|  | 335 		InternetAddress[] a = new InternetAddress[addrs.length]; | 
|  | 336 		for( int i=0; i<addrs.length; i++ ) { | 
|  | 337 			a[i] = addr(addrs[i]); | 
|  | 338 		} | 
|  | 339 		return a; | 
|  | 340 	} | 
|  | 341 | 
|  | 342 	static MailAddress addr(Address a) { | 
|  | 343 		if( a==null ) | 
|  | 344 			return null; | 
|  | 345 		InternetAddress addr = (InternetAddress)a; | 
|  | 346 		return addr.getPersonal() == null | 
|  | 347 			? new MailAddress(addr.getAddress()) | 
|  | 348 			: new MailAddress(addr.getAddress(),addr.getPersonal()) | 
|  | 349 		; | 
|  | 350 	} | 
|  | 351 | 
|  | 352 	private static MailAddress[] addr(Address[] a) { | 
|  | 353 		if( a==null ) | 
|  | 354 			return new MailAddress[0]; | 
|  | 355 		MailAddress[] ma = new MailAddress[a.length]; | 
|  | 356 		for( int i=0; i<a.length; i++ ) { | 
|  | 357 			ma[i] = addr(a[i]); | 
|  | 358 		} | 
|  | 359 		return ma; | 
|  | 360 	} | 
|  | 361 | 
|  | 362 	public MailAddress getFrom() throws MailException { | 
|  | 363 		try { | 
|  | 364 			Address[] addrs = msg.getFrom(); | 
|  | 365 			if( addrs==null || addrs.length==0 ) | 
|  | 366 				throw new MailAddressException("number of from addresses is 0"); | 
|  | 367 			//if( addrs.length > 1 ) | 
|  | 368 			//	log.warn("number of from addresses is "+addrs.length); | 
|  | 369 			return addr(addrs[0]); | 
|  | 370 		} catch(MessagingException e) { | 
|  | 371 			throw MailImpl.e(e); | 
|  | 372 		} | 
|  | 373 	} | 
|  | 374 | 
|  | 375 	public void setFrom(MailAddress address) throws MailException { | 
|  | 376 		try { | 
|  | 377 			msg.setFrom(addr(address)); | 
|  | 378 		} catch(MessagingException e) { | 
|  | 379 			throw MailImpl.e(e); | 
|  | 380 		} catch(UnsupportedEncodingException e) { | 
|  | 381 			throw new MailException(e); | 
|  | 382 		} | 
|  | 383 	} | 
|  | 384 | 
|  | 385 	public MailAddress getSender() throws MailException { | 
|  | 386 		try { | 
|  | 387 			return addr(msg.getSender()); | 
|  | 388 		} catch(MessagingException e) { | 
|  | 389 			throw MailImpl.e(e); | 
|  | 390 		} | 
|  | 391 	} | 
|  | 392 | 
|  | 393 	public void setSender(MailAddress address) throws MailException { | 
|  | 394 		try { | 
|  | 395 			msg.setSender(addr(address)); | 
|  | 396 		} catch(MessagingException e) { | 
|  | 397 			throw MailImpl.e(e); | 
|  | 398 		} catch(UnsupportedEncodingException e) { | 
|  | 399 			throw new MailException(e); | 
|  | 400 		} | 
|  | 401 	} | 
|  | 402 | 
|  | 403 	public MailAddress[] getReplyTo() throws MailException { | 
|  | 404 		try { | 
|  | 405 			String replyTo = msg.getHeader("Reply-To", ","); | 
|  | 406 			return (replyTo == null) ? null : addr(InternetAddress.parse(replyTo)); | 
|  | 407 		} catch(MessagingException e) { | 
|  | 408 			throw MailImpl.e(e); | 
|  | 409 		} | 
|  | 410 	} | 
|  | 411 | 
|  | 412 	public void setReplyTo(MailAddress... addresses) throws MailException { | 
|  | 413 		try { | 
|  | 414 			msg.setReplyTo(addr(addresses)); | 
|  | 415 		} catch(MessagingException e) { | 
|  | 416 			throw MailImpl.e(e); | 
|  | 417 		} catch(UnsupportedEncodingException e) { | 
|  | 418 			throw new MailException(e); | 
|  | 419 		} | 
|  | 420 	} | 
|  | 421 | 
|  | 422 	public MailAddress[] getTo() throws MailException { | 
|  | 423 		try { | 
|  | 424 			return addr(msg.getRecipients(Message.RecipientType.TO)); | 
|  | 425 		} catch(MessagingException e) { | 
|  | 426 			throw MailImpl.e(e); | 
|  | 427 		} | 
|  | 428 	} | 
|  | 429 | 
|  | 430 	public MailAddress[] getCc() throws MailException { | 
|  | 431 		try { | 
|  | 432 			return addr(msg.getRecipients(Message.RecipientType.CC)); | 
|  | 433 		} catch(MessagingException e) { | 
|  | 434 			throw MailImpl.e(e); | 
|  | 435 		} | 
|  | 436 	} | 
|  | 437 | 
|  | 438 	public MailAddress[] getBcc() throws MailException { | 
|  | 439 		try { | 
|  | 440 			return addr(msg.getRecipients(Message.RecipientType.BCC)); | 
|  | 441 		} catch(MessagingException e) { | 
|  | 442 			throw MailImpl.e(e); | 
|  | 443 		} | 
|  | 444 	} | 
|  | 445 | 
|  | 446 	public void setTo(MailAddress... addresses) throws MailException { | 
|  | 447 		try { | 
|  | 448 			msg.setRecipients(Message.RecipientType.TO,addr(addresses)); | 
|  | 449 		} catch(MessagingException e) { | 
|  | 450 			throw MailImpl.e(e); | 
|  | 451 		} catch(UnsupportedEncodingException e) { | 
|  | 452 			throw new MailException(e); | 
|  | 453 		} | 
|  | 454 	} | 
|  | 455 | 
|  | 456 	public void setCc(MailAddress... addresses) throws MailException { | 
|  | 457 		try { | 
|  | 458 			msg.setRecipients(Message.RecipientType.CC,addr(addresses)); | 
|  | 459 		} catch(MessagingException e) { | 
|  | 460 			throw MailImpl.e(e); | 
|  | 461 		} catch(UnsupportedEncodingException e) { | 
|  | 462 			throw new MailException(e); | 
|  | 463 		} | 
|  | 464 	} | 
|  | 465 | 
|  | 466 	public void setBcc(MailAddress... addresses) throws MailException { | 
|  | 467 		try { | 
|  | 468 			msg.setRecipients(Message.RecipientType.BCC,addr(addresses)); | 
|  | 469 		} catch(MessagingException e) { | 
|  | 470 			throw MailImpl.e(e); | 
|  | 471 		} catch(UnsupportedEncodingException e) { | 
|  | 472 			throw new MailException(e); | 
|  | 473 		} | 
|  | 474 	} | 
|  | 475 | 
|  | 476 	public String[] getHeader(String name) throws MailException { | 
|  | 477 		try { | 
|  | 478 			return msg.getHeader(name); | 
|  | 479 		} catch(MessagingException e) { | 
|  | 480 			throw MailImpl.e(e); | 
|  | 481 		} | 
|  | 482 	} | 
|  | 483 | 
|  | 484 	public void setHeader(String name,String... values) throws MailException { | 
|  | 485 		try { | 
|  | 486 			if( values==null ) { | 
|  | 487 				msg.removeHeader(name); | 
|  | 488 			} else { | 
|  | 489 				msg.setHeader(name,values[0]); | 
|  | 490 				for( int i=1; i<values.length; i++ ) { | 
|  | 491 					msg.addHeader(name,values[i]); | 
|  | 492 				} | 
|  | 493 			} | 
|  | 494 		} catch(MessagingException e) { | 
|  | 495 			throw MailImpl.e(e); | 
|  | 496 		} | 
|  | 497 	} | 
|  | 498 | 
|  | 499 	public void setHeader(String name, MailAddress address) throws MailException { | 
|  | 500 		try { | 
|  | 501 			msg.setHeader(name, addr(address).toString()); | 
|  | 502 		} catch(MessagingException e) { | 
|  | 503 			throw MailImpl.e(e); | 
|  | 504 		} catch(UnsupportedEncodingException e) { | 
|  | 505 			throw new MailException(e); | 
|  | 506 		} | 
|  | 507 	} | 
|  | 508 | 
|  | 509 	public String getMessageID() throws MailException { | 
|  | 510 		try { | 
|  | 511 			if( messageID != null ) | 
|  | 512 				return messageID; | 
|  | 513 			return msg.getMessageID(); | 
|  | 514 		} catch(MessagingException e) { | 
|  | 515 			throw MailImpl.e(e); | 
|  | 516 		} | 
|  | 517 	} | 
|  | 518 | 
|  | 519 	public void setMessageID(String messageID) throws MailException { | 
|  | 520 		this.messageID = messageID; | 
|  | 521 	} | 
|  | 522 | 
|  | 523 	public Date getSentDate() throws MailException { | 
|  | 524 		try { | 
|  | 525 			return msg.getSentDate(); | 
|  | 526 		} catch(MessagingException e) { | 
|  | 527 			throw MailImpl.e(e); | 
|  | 528 		} | 
|  | 529 	} | 
|  | 530 | 
|  | 531 	public void setSentDate(Date sentDate) throws MailException { | 
|  | 532 		try { | 
|  | 533 			msg.setSentDate(sentDate); | 
|  | 534 		} catch(MessagingException e) { | 
|  | 535 			throw MailImpl.e(e); | 
|  | 536 		} | 
|  | 537 	} | 
|  | 538 | 
|  | 539 	public String getRawInput() throws MailException { | 
|  | 540 		try { | 
|  | 541 			ByteArrayOutputStream out = new ByteArrayOutputStream(); | 
|  | 542 			msg.writeTo(out); | 
|  | 543 			return out.toString("ISO-8859-1"); | 
|  | 544 		} catch(MessagingException e) { | 
|  | 545 			throw MailImpl.e(e); | 
|  | 546 		} catch(IOException e) { | 
|  | 547 			throw new MailException(e); | 
|  | 548 		} | 
|  | 549 	} | 
|  | 550 | 
|  | 551 	public String toString() { | 
|  | 552 		try { | 
|  | 553 			StringBuilder buf = new StringBuilder(); | 
|  | 554 			for( Enumeration en=msg.getAllHeaderLines(); en.hasMoreElements(); ) { | 
|  | 555 				String header = (String)en.nextElement(); | 
|  | 556 				buf.append(header).append("\n"); | 
|  | 557 			} | 
|  | 558 			buf.append("\n"); | 
|  | 559 			buf.append(getContent()); | 
|  | 560 			return buf.toString(); | 
|  | 561 		} catch(MessagingException e) { | 
|  | 562 			throw new RuntimeException(e); | 
|  | 563 		} | 
|  | 564 	} | 
|  | 565 | 
|  | 566 | 
|  | 567 	// exception handling | 
|  | 568 | 
|  | 569 	static MailException e(MessagingException e) { | 
|  | 570 		return e(e.getMessage(),e); | 
|  | 571 	} | 
|  | 572 | 
|  | 573 	static MailException e(String msg,AddressException e) { | 
|  | 574 		return new MailAddressException(msg,e); | 
|  | 575 	} | 
|  | 576 | 
|  | 577 	static MailException e(String msg,MessagingException e) { | 
|  | 578 		if( e instanceof AddressException ) | 
|  | 579 			return e(msg,(AddressException)e); | 
|  | 580 		else if(e instanceof ParseException ) | 
|  | 581 			return e(msg,(ParseException)e); | 
|  | 582 		if (msg!=null && msg.startsWith("Missing start boundary")) | 
|  | 583 			return new MailParseException(msg,e); | 
|  | 584 		Exception e2 = e.getNextException(); | 
|  | 585 		return e2==null ? new MailException(msg,e) : e(msg,e2); | 
|  | 586 	} | 
|  | 587 | 
|  | 588 	static MailException e(String msg,Exception e) { | 
|  | 589 		if( e instanceof MessagingException ) | 
|  | 590 			return e(msg,(MessagingException)e); | 
|  | 591 		return new MailException(msg,e); | 
|  | 592 	} | 
|  | 593 | 
|  | 594 	static MailException e(String msg,ParseException e) { | 
|  | 595 		return new MailParseException(msg,e); | 
|  | 596 	} | 
|  | 597 | 
|  | 598 	static MailException e(IOException e) { | 
|  | 599 		return e(e.getMessage(),e); | 
|  | 600 	} | 
|  | 601 | 
|  | 602 	static MailException e(String msg,IOException e) { | 
|  | 603 		if ( e instanceof UnsupportedEncodingException ) | 
|  | 604 			return e(msg,(UnsupportedEncodingException)e); | 
|  | 605 		if (msg!=null && msg.startsWith("Unknown encoding")) | 
|  | 606 			return new MailEncodingException(msg,e); | 
|  | 607 		return new MailException(msg,e); | 
|  | 608 	} | 
|  | 609 | 
|  | 610 	static MailException e(String msg,UnsupportedEncodingException e) { | 
|  | 611 		return new MailEncodingException(msg,e); | 
|  | 612 	} | 
|  | 613 | 
|  | 614 	static { | 
|  | 615 		MailcapCommandMap mcm = (MailcapCommandMap)CommandMap.getDefaultCommandMap(); | 
|  | 616 		mcm.addMailcap("text/x-aol; ; x-java-content-handler=com.sun.mail.handlers.text_plain"); | 
|  | 617 	} | 
|  | 618 } |