view src/luan/modules/mail/MailSender.java @ 1589:0c46edec25dd

mail work
author Franklin Schmidt <fschmidt@gmail.com>
date Sat, 13 Mar 2021 21:02:38 -0700
parents src/luan/modules/mail/MailCon.java@fa1a9aceac3e
children 1ffe1e06ea55
line wrap: on
line source

package luan.modules.mail;

import java.io.IOException;
import java.net.Socket;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.List;
import goodjava.mail.Message;
import goodjava.mail.Smtp;
import goodjava.mail.MailException;
import luan.Luan;
import luan.LuanTable;
import luan.LuanException;


public final class MailSender {
	private final String host;
	private final int port;
	private final String username;
	private final String password;

	public MailSender(LuanTable paramsTbl) throws LuanException {
		Map<Object,Object> params = paramsTbl.asMap();

		String host = getString(params,"host");
		if( host==null )
			throw new LuanException( "parameter 'host' is required" );
		this.host = host;

		Object port = params.remove("port");
		if( port==null )
			throw new LuanException( "parameter 'port' is required" );
		if( !(port instanceof Number) )
			throw new LuanException( "parameter 'port' must be an integer" );
		Integer i = Luan.asInteger(port);
		if( i == null )
			throw new LuanException( "parameter 'port' must be an integer" );
		this.port = i;

		this.username = getString(params,"username");
		this.password = getString(params,"password");
		if( this.username!=null && this.password==null )
			throw new LuanException( "password required with username" );
		if( this.username==null && this.password!=null )
			throw new LuanException( "username required with password" );

		if( !params.isEmpty() )
			throw new LuanException( "unrecognized parameters: "+params );
	}

	private static String getString(Map<Object,Object> params,String key) throws LuanException {
		Object val = params.remove(key);
		if( val!=null && !(val instanceof String) )
			throw new LuanException( "parameter '"+key+"' must be a string" );
		return (String)val;
	}

	private static Message message(LuanTable mailTbl) throws LuanException {
		Map<Object,Object> mailParams = mailTbl.asMap();
		Object body = mailParams.remove("body");
		if( body == null )
			throw new LuanException( "parameter 'body' is required" );
		Map<String,String> headers = new LinkedHashMap<String,String>();
		boolean hasContentType = false;
		for( Map.Entry<Object,Object> entry : mailParams.entrySet() ) {
			Object key = entry.getKey();
			Object value = entry.getValue();
			if( !(key instanceof String) )
				throw new LuanException( "keys must be strings" );
			if( !(value instanceof String) )
				throw new LuanException( "value for '"+key+"' must be string" );
			String name = (String)key;
			headers.put(name,(String)value);
			if( name.equalsIgnoreCase("content-type") )
				hasContentType = true;
		}
		if( body instanceof String ) {
			if( !hasContentType )
				headers.put("Content-Type","text/plain; charset=utf-8");
			return new Message(headers,(String)body);
		}
		if( body instanceof byte[] ) {
			if( !hasContentType )
				throw new LuanException("Content-Type required for binary body");
			return new Message(headers,(byte[])body);
		}
		if( body instanceof LuanTable ) {
			if( !hasContentType )
				headers.put("Content-Type","multipart/mixed");
			LuanTable tbl = (LuanTable)body;
			if( !tbl.isList() )
				throw new LuanException( "body table must be a list" );
			List list = tbl.asList();
			Message[] msgs = new Message[list.size()];
			for( int i=0; i<msgs.length; i++ ) {
				Object obj = list.get(i);
				if( !(obj instanceof LuanTable) )
					throw new LuanException( "body table must be a list of part tables" );
				msgs[i] = message((LuanTable)obj);
			}
			return new Message(headers,msgs);
		}
		throw new LuanException("body must be a string, binary, or list of part tables");
	}

	public void send(LuanTable mailTbl) throws LuanException, IOException, MailException {
		Message msg = message(mailTbl);
		Socket socket = new Socket(host,port);
		Smtp smtp = new Smtp(socket);
		if( username != null )
			smtp.authenticate(username,password);
		smtp.send(msg);
		smtp.close();
	}

}