view src/goodjava/mail/Message.java @ 1698:2dbcc8360a3e

backup security
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 27 Jun 2022 20:51:49 -0600
parents 0b904d30721f
children
line wrap: on
line source

package goodjava.mail;

import java.util.Map;
import java.util.Base64;
import java.util.Random;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import goodjava.util.GoodUtils;


public class Message {
	final Map<String,String> headers;
	final Object content;
	private static final Pattern line = Pattern.compile("(?m)^.*$");

	public Message(Map<String,String> headers,String content) {
		this.headers = headers;
		this.content = content;
	}

	public Message(Map<String,String> headers,byte[] content) {
		this.headers = headers;
		this.content = content;
	}

	public Message(Map<String,String> headers,Message[] content) {
		this.headers = headers;
		this.content = content;
	}

	private static void addBase64(StringBuilder sb,byte[] a) {
		String s = Base64.getEncoder().encodeToString(a);
		int n = s.length() - 76;
		int i;
		for( i=0; i<n; i+=76 ) {
			sb.append(s.substring(i,i+76)).append("\r\n");
		}
		sb.append(s.substring(i)).append("\r\n");
	}

	public String toText() throws MailException {
		StringBuilder sb = new StringBuilder();
		String contentType = null;
		for( Map.Entry<String,String> entry : headers.entrySet() ) {
			String name = entry.getKey();
			String value = entry.getValue();
			if( name.equalsIgnoreCase("bcc") )
				continue;
			if( name.equalsIgnoreCase("content-type") ) {
				contentType = value;
				continue;
			}
			sb.append( name ).append( ": " ).append( value ).append( "\r\n" );
		}
		if( content instanceof String ) {
			String s = (String)content;
			if( contentType!=null )
				sb.append( "Content-Type: " ).append( contentType ).append( "\r\n" );
			boolean isAscii = s.matches("\\p{ASCII}*");
			if( !isAscii )
				sb.append( "Content-Transfer-Encoding: base64\r\n" );
			sb.append( "\r\n" );
			if( isAscii ) {
				Matcher m = line.matcher(s);
				while( m.find() ) {
					sb.append(m.group()).append("\r\n");		
				}
			} else {
				addBase64( sb, GoodUtils.getBytes(s,"UTF-8") );
			}
		} else if( content instanceof byte[] ) {
			if( contentType!=null )
				sb.append( "Content-Type: " ).append( contentType ).append( "\r\n" );
			sb.append( "Content-Transfer-Encoding: base64\r\n" );
			sb.append( "\r\n" );
			addBase64( sb, (byte[])content );
		} else if( content instanceof Message[] ) {
			if( contentType==null )
				throw new MailException("Content-Type must be defined for multipart");
			Message[] messages = (Message[])content;
			String[] texts = new String[messages.length];
			StringBuilder allTextSb = new StringBuilder();
			for( int i=0; i<messages.length; i++ ) {
				String text = messages[i].toText();
				texts[i] = text;
				allTextSb.append(text);
			}
			String allText = allTextSb.toString();
			String boundary;
			do {
				boundary = Long.toHexString(new Random().nextLong());
			} while( allText.contains(boundary) );
			sb.append( "Content-Type: " ).append( contentType )
				.append( "; boundary=\"" ).append( boundary ).append( "\"\r\n" );
			sb.append( "\r\n" );
			for( String text : texts ) {
				sb.append( "--" ).append( boundary ).append( "\r\n" );
				sb.append( text );
				sb.append( "\r\n" );
			}
			sb.append( "--" ).append( boundary ).append( "--\r\n" );
		} else
			throw new RuntimeException();
		return sb.toString();
	}
}