view src/luan/modules/mail/MailCon.java @ 1586:fcca0ddf5a4d

luan uses goodjava.mail
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 12 Mar 2021 20:12:43 -0700
parents
children fa1a9aceac3e
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 MailCon {
	private final String host;
	private final int port;
	private final String username;
	private final String password;

	public MailCon(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" );
		if( body instanceof LuanTable ) {
			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);
			}
			body = msgs;
		}
		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( !hasContentType && body instanceof String )
			headers.put("Content-Type","text/plain; charset=utf-8");
		return new Message(headers,body);
	}

	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();
	}

}