immf.MyWiser.java Source code

Java tutorial

Introduction

Here is the source code for immf.MyWiser.java

Source

/*
 * imoten - i mode.net mail tensou(forward)
 * 
 * Copyright (C) 2010 shoozhoo (http://code.google.com/p/imoten/)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * 
 */

package immf;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.mail.Session;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.subethamail.smtp.MessageContext;
import org.subethamail.smtp.MessageHandler;
import org.subethamail.smtp.MessageHandlerFactory;
import org.subethamail.smtp.RejectException;
import org.subethamail.smtp.TooMuchDataException;
import org.subethamail.smtp.auth.EasyAuthenticationHandlerFactory;
import org.subethamail.smtp.auth.UsernamePasswordValidator;
import org.subethamail.smtp.server.SMTPServer;

public class MyWiser implements MyMessageListener, MessageHandlerFactory {
    /** */
    private final static Log log = LogFactory.getLog(MyWiser.class);

    /** */
    SMTPServer server;

    /** */
    //List<MyWiserMessage> messages = Collections.synchronizedList(new ArrayList<MyWiserMessage>());

    private MyWiserMailListener listener;

    /**
     * Create a new SMTP server with this class as the listener.
     * The default port is 25. Call setPort()/setHostname() before
     * calling start().
     */
    public MyWiser(UsernamePasswordValidator userPass, int port, MyWiserMailListener listener,
            final String tlsKeyStore, final String tlsKeyType, final String tlsKeyPasswd) {
        if (tlsKeyStore == null) {
            log.info("SMTP Server disable TLS");
            this.server = new SMTPServer(this, new EasyAuthenticationHandlerFactory(userPass));
            this.server.setHideTLS(true); // TLS?

        } else {
            // TLS
            log.info("SMTP Server enable TLS");
            this.server = new SMTPServer(this, new EasyAuthenticationHandlerFactory(userPass)) {
                public SSLSocket createSSLSocket(Socket socket) throws IOException {
                    SSLSocketFactory sf = createSslSocketFactory(tlsKeyStore, tlsKeyType, tlsKeyPasswd);
                    InetSocketAddress remoteAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
                    SSLSocket s = (SSLSocket) (sf.createSocket(socket, remoteAddress.getHostName(),
                            socket.getPort(), true));

                    s.setUseClientMode(false);

                    s.setEnabledCipherSuites(s.getSupportedCipherSuites());

                    return s;
                }
            };
            this.server.setRequireTLS(true); // TLS
        }
        this.server.setPort(port);
        this.listener = listener;
    }

    private SSLSocketFactory createSslSocketFactory(String keystoreFile, String keyType, String keypasswd) {
        InputStream keyis = null;
        try {
            keyis = new FileInputStream(keystoreFile);
            KeyStore keyStore = KeyStore.getInstance(keyType);
            keyStore.load(keyis, keypasswd.toCharArray());

            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(keyStore, keypasswd.toCharArray());

            SSLContext context = SSLContext.getInstance("TLS");

            context.init(kmf.getKeyManagers(), null, new SecureRandom());
            return context.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
            return (SSLSocketFactory) SSLSocketFactory.getDefault();
        } finally {
            try {
                keyis.close();
            } catch (Exception e) {
            }
        }
    }

    /**
     * The hostname that the server should listen on.
     * @param hostname
     */
    public void setHostname(String hostname) {
        this.server.setHostName(hostname);
    }

    /** Starts the SMTP Server */
    public void start() {
        this.server.start();
    }

    /** Stops the SMTP Server */
    public void stop() {
        this.server.stop();
    }

    /** Always accept everything */
    public boolean accept(String from, String recipient) {
        if (log.isDebugEnabled())
            log.debug("Accepting mail from " + from + " to " + recipient);

        return true;
    }

    /** Cache the messages in memory */
    public void deliver(String from, List<String> recipient, InputStream data)
            throws TooMuchDataException, RejectException, IOException {
        if (log.isDebugEnabled())
            log.debug("Delivering mail from " + from + " to " + recipient);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        data = new BufferedInputStream(data);

        // read the data from the stream
        int current;
        while ((current = data.read()) >= 0) {
            out.write(current);
        }

        byte[] bytes = out.toByteArray();
        //log.info("raw message:" + new String(bytes));

        if (log.isDebugEnabled())
            log.debug("Creating message from data with " + bytes.length + " bytes");

        // create a new WiserMessage.
        try {

            this.listener.receiveMail(new MyWiserMessage(this, from, recipient, bytes));
        } catch (IOException e) {
            throw new RejectException(e.getMessage());
        }
        //this.messages.add(new MyWiserMessage(this, from, recipient, bytes));
    }

    /**
     * Creates the JavaMail Session object for use in WiserMessage
     */
    protected Session getSession() {
        return Session.getDefaultInstance(new Properties());
    }

    /**
     * @return the list of WiserMessages
     */
    /*
    public List<MyWiserMessage> getMessages()
    {
       return this.messages;
    }*/

    /**
     * @return the server implementation
     */
    public SMTPServer getServer() {
        return this.server;
    }

    /**
     * For debugging purposes, dumps a rough outline of the messages to the output stream.
     */
    /*
    public void dumpMessages(PrintStream out) throws MessagingException
    {
       out.println("----- Start printing messages -----");
        
       for (MyWiserMessage wmsg: this.getMessages())
     wmsg.dumpMessage(out);
        
       out.println("----- End printing messages -----");
    }
    */

    public MessageHandler create(MessageContext messagecontext) {
        return new Handler(messagecontext);
    }

    class Handler implements MessageHandler {
        MessageContext ctx;
        String from;
        List<String> recipients = new ArrayList<String>();

        /** */
        public Handler(MessageContext ctx) {
            this.ctx = ctx;
        }

        /** */
        public void from(String from) throws RejectException {
            this.from = from;
            if (ctx.getAuthenticationHandler() == null || ctx.getAuthenticationHandler().getIdentity() == null) {
                log.warn("SMTP?????");
                throw new RejectException("Require SMTP Auth.");
            }
            log.info("SMTP Auth, User " + ctx.getAuthenticationHandler().getIdentity());
        }

        /** */
        public void recipient(String recipient) throws RejectException {
            this.recipients.add(recipient);
        }

        /** */
        public void data(InputStream data) throws TooMuchDataException, RejectException, IOException {

            deliver(this.from, this.recipients, data);
        }

        /** */
        public void done() {
        }
    }

}