| 
1583
 | 
     1 package goodjava.mail;
 | 
| 
 | 
     2 
 | 
| 
 | 
     3 import java.util.Map;
 | 
| 
1584
 | 
     4 import java.util.Base64;
 | 
| 
1585
 | 
     5 import java.util.Random;
 | 
| 
1583
 | 
     6 import java.util.regex.Pattern;
 | 
| 
 | 
     7 import java.util.regex.Matcher;
 | 
| 
 | 
     8 import goodjava.util.GoodUtils;
 | 
| 
 | 
     9 
 | 
| 
 | 
    10 
 | 
| 
 | 
    11 public class Message {
 | 
| 
1585
 | 
    12 	final Map<String,String> headers;
 | 
| 
 | 
    13 	final Object content;
 | 
| 
1588
 | 
    14 	private static final Pattern line = Pattern.compile("(?m)^.*$");
 | 
| 
1583
 | 
    15 
 | 
| 
1587
 | 
    16 	public Message(Map<String,String> headers,String content) {
 | 
| 
 | 
    17 		this.headers = headers;
 | 
| 
 | 
    18 		this.content = content;
 | 
| 
 | 
    19 	}
 | 
| 
 | 
    20 
 | 
| 
 | 
    21 	public Message(Map<String,String> headers,byte[] content) {
 | 
| 
 | 
    22 		this.headers = headers;
 | 
| 
 | 
    23 		this.content = content;
 | 
| 
 | 
    24 	}
 | 
| 
 | 
    25 
 | 
| 
 | 
    26 	public Message(Map<String,String> headers,Message[] content) {
 | 
| 
1584
 | 
    27 		this.headers = headers;
 | 
| 
 | 
    28 		this.content = content;
 | 
| 
1583
 | 
    29 	}
 | 
| 
 | 
    30 
 | 
| 
1584
 | 
    31 	private static void addBase64(StringBuilder sb,byte[] a) {
 | 
| 
 | 
    32 		String s = Base64.getEncoder().encodeToString(a);
 | 
| 
 | 
    33 		int n = s.length() - 76;
 | 
| 
 | 
    34 		int i;
 | 
| 
 | 
    35 		for( i=0; i<n; i+=76 ) {
 | 
| 
 | 
    36 			sb.append(s.substring(i,i+76)).append("\r\n");
 | 
| 
 | 
    37 		}
 | 
| 
 | 
    38 		sb.append(s.substring(i)).append("\r\n");
 | 
| 
1583
 | 
    39 	}
 | 
| 
 | 
    40 
 | 
| 
1584
 | 
    41 	public String toText() throws MailException {
 | 
| 
1583
 | 
    42 		StringBuilder sb = new StringBuilder();
 | 
| 
1584
 | 
    43 		String contentType = null;
 | 
| 
1583
 | 
    44 		for( Map.Entry<String,String> entry : headers.entrySet() ) {
 | 
| 
 | 
    45 			String name = entry.getKey();
 | 
| 
1584
 | 
    46 			String value = entry.getValue();
 | 
| 
1583
 | 
    47 			if( name.equalsIgnoreCase("bcc") )
 | 
| 
 | 
    48 				continue;
 | 
| 
1584
 | 
    49 			if( name.equalsIgnoreCase("content-type") ) {
 | 
| 
 | 
    50 				contentType = value;
 | 
| 
 | 
    51 				continue;
 | 
| 
 | 
    52 			}
 | 
| 
1583
 | 
    53 			sb.append( name ).append( ": " ).append( value ).append( "\r\n" );
 | 
| 
 | 
    54 		}
 | 
| 
1584
 | 
    55 		if( content instanceof String ) {
 | 
| 
 | 
    56 			String s = (String)content;
 | 
| 
1587
 | 
    57 			if( contentType!=null )
 | 
| 
 | 
    58 				sb.append( "Content-Type: " ).append( contentType ).append( "\r\n" );
 | 
| 
1584
 | 
    59 			boolean isAscii = s.matches("\\p{ASCII}*");
 | 
| 
 | 
    60 			if( !isAscii )
 | 
| 
 | 
    61 				sb.append( "Content-Transfer-Encoding: base64\r\n" );
 | 
| 
 | 
    62 			sb.append( "\r\n" );
 | 
| 
 | 
    63 			if( isAscii ) {
 | 
| 
 | 
    64 				Matcher m = line.matcher(s);
 | 
| 
 | 
    65 				while( m.find() ) {
 | 
| 
 | 
    66 					sb.append(m.group()).append("\r\n");		
 | 
| 
 | 
    67 				}
 | 
| 
 | 
    68 			} else {
 | 
| 
 | 
    69 				addBase64( sb, GoodUtils.getBytes(s,"UTF-8") );
 | 
| 
1583
 | 
    70 			}
 | 
| 
1584
 | 
    71 		} else if( content instanceof byte[] ) {
 | 
| 
1587
 | 
    72 			if( contentType!=null )
 | 
| 
 | 
    73 				sb.append( "Content-Type: " ).append( contentType ).append( "\r\n" );
 | 
| 
1584
 | 
    74 			sb.append( "Content-Transfer-Encoding: base64\r\n" );
 | 
| 
 | 
    75 			sb.append( "\r\n" );
 | 
| 
 | 
    76 			addBase64( sb, (byte[])content );
 | 
| 
1585
 | 
    77 		} else if( content instanceof Message[] ) {
 | 
| 
1587
 | 
    78 			if( contentType==null )
 | 
| 
 | 
    79 				throw new MailException("Content-Type must be defined for multipart");
 | 
| 
1585
 | 
    80 			Message[] messages = (Message[])content;
 | 
| 
 | 
    81 			String[] texts = new String[messages.length];
 | 
| 
 | 
    82 			StringBuilder allTextSb = new StringBuilder();
 | 
| 
 | 
    83 			for( int i=0; i<messages.length; i++ ) {
 | 
| 
 | 
    84 				String text = messages[i].toText();
 | 
| 
 | 
    85 				texts[i] = text;
 | 
| 
 | 
    86 				allTextSb.append(text);
 | 
| 
 | 
    87 			}
 | 
| 
 | 
    88 			String allText = allTextSb.toString();
 | 
| 
 | 
    89 			String boundary;
 | 
| 
 | 
    90 			do {
 | 
| 
 | 
    91 				boundary = Long.toHexString(new Random().nextLong());
 | 
| 
 | 
    92 			} while( allText.contains(boundary) );
 | 
| 
 | 
    93 			sb.append( "Content-Type: " ).append( contentType )
 | 
| 
 | 
    94 				.append( "; boundary=\"" ).append( boundary ).append( "\"\r\n" );
 | 
| 
 | 
    95 			sb.append( "\r\n" );
 | 
| 
 | 
    96 			for( String text : texts ) {
 | 
| 
 | 
    97 				sb.append( "--" ).append( boundary ).append( "\r\n" );
 | 
| 
 | 
    98 				sb.append( text );
 | 
| 
 | 
    99 				sb.append( "\r\n" );
 | 
| 
 | 
   100 			}
 | 
| 
 | 
   101 			sb.append( "--" ).append( boundary ).append( "--\r\n" );
 | 
| 
1584
 | 
   102 		} else
 | 
| 
1587
 | 
   103 			throw new RuntimeException();
 | 
| 
1583
 | 
   104 		return sb.toString();
 | 
| 
 | 
   105 	}
 | 
| 
 | 
   106 }
 |