⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mailsource.java

📁 java编写的OCR软件
💻 JAVA
字号:
/*
    Jacson
    Copyright (C) 2003 Patrick Carl, patrick.carl@web.de
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.
 
    This library 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
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package de.spieleck.app.jacson.source;

import de.spieleck.app.jacson.JacsonException;
import de.spieleck.app.jacson.JacsonReport;
import de.spieleck.app.jacson.JacsonState;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Properties;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Flags.Flag;
import javax.mail.search.FlagTerm;
import javax.mail.search.SearchTerm;

/**
 * This class implements a JacsonChunkSource for emails using.<br>
 * It supports the POP3 and the IMAP protocolls. When using IMAP processed
 * mails are marked as being seen and at default only unseen mails are
 * processed. So you can avoid double processing by using IMAP. If you have to
 * use POP3 and have to avoid double processing - :( Not possible at the
 * moment. But remember, it's open source :-) <br>
 * This class needs the JavaMail and the Java activation framework.<br>
 * Notice that a mail consists of an header and a body. The header contains
 * information like subject, sender or receiver. The body contains the actual
 * text of the mail. To indicate to which part a chunk belongs, the name of
 * the header field or the value of the constant @link MailSouce#BODY is stored
 * within the JacsonState connected to @link MailSource#JACSON_STATE_CHUNK_TYPE.
 * <br>Furthermore a mail starts with a header so whenever you get a header
 * chunk and the last was a body chunk a new mail began.<br>
 * For details see
 * <a href="http://www.faqs.org/ftp/rfc/rfc822.txt">RFC 822</a>.
 *
 * @author  Patrick Carl
 * @author fsn
 * @version 0.71
 */
public class MailSource
extends ChunkSourceBase {
    
    /**
     * indicates that the current chunk is part of the mail's body
     */
    public static final String BODY = "Body";
    
    /**
     * name of the parameter used to indicate the chunk type within JacsonState
     */
    public static final String JACSON_STATE_CHUNK_TYPE =
    "de.spieleck.app.source.MailSource.ChunkType";
    
    /**
     * String constant used to say that MailSource that it should use the
     * IMAP protocoll for receiving mails
     */
    public static final String IMAP = "imap";
    /**
     * String constant used to say that MailSource that it should use the
     * POP3 protocoll for receiving mails
     */
    public static final String POP3 = "pop3";
    
    /**
     * some things for the mail stuff
     */
    private String user;
    private String password;
    private String mailServer;
    private String protocoll;
    private Folder folder;
    private Message[] messages;
    private SearchTerm searchTerm;
    
    /**
     * this thread is used to read in the mails in an own thread
     */
    private Thread messageParserThread;
    /**
     * this is where the thread puts its chunks
     */
    private LinkedList chunks;
    
    /**
     * Creates a new instance of Pop3Source with the given settings. Only those
     * mails are processed which have not set the SEEN flag (does not work
     * with POP3)
     * @param user user of the mailbox read
     * @param password users password at the mailbox read
     * @param mailServer server of the mailbox read
     */
    public MailSource(String user, String password, String mailServer)
    throws JacsonException {
        this(user, password, mailServer,
        new FlagTerm(new Flags(Flag.SEEN), false));
    }
    
    /**
     * A using the given settings but only receives
     * messages that match the given SearchTerm
     * @param user user of the mailbox read
     * @param password users password at the mailbox read
     * @param mailServer server of the mailbox read
     * @param searchTerm a SearchTerm to select messages to read
     */
    public MailSource(String user, String password, String mailServer,
    SearchTerm searchTerm) throws JacsonException {
        this.user = user;
        this.password = password;
        this.mailServer = mailServer;
        chunks = new LinkedList();
        this.searchTerm = searchTerm;
    }
    
    protected void finalize() throws Throwable {
        cleanUp();
        super.finalize();
    }
    
    /**
     * Cleaning up resources
     */
    protected void cleanUp() throws JacsonException {
        try{
            if (protocoll.equals(IMAP))
                folder.setFlags(messages, new Flags(Flag.SEEN), true);
            folder.close(true);
        } catch(Exception e){
            e.printStackTrace();
            throw new JacsonException("Exception during cleanUp", e);
        }
    }
    
    /**
     * sets the protocoll used to retrieve emails. It the given parameter is
     * not a known protocoll, IMAP will be used instead.
     */
    public void setProtocoll(String protocoll) {
        // we need always a lowercase protocoll, if user provides Pop3 we can
        // assume he wants to use pop3
        if (protocoll == null){
            this.protocoll = IMAP;
        }
        protocoll = protocoll.toLowerCase();
        if (POP3.equals(protocoll) || IMAP.equals(protocoll))
            this.protocoll = protocoll;
        else{
            System.out.println("MailSource can only use " + IMAP + " or " + POP3
            + " to receive mails. You provided an unknown protocoll. MailSource "
            + "will use " + IMAP + " as default.");
            this.protocoll = IMAP;
        }
    }
    
    /**
     * receives the message, filters them and starts a new Thread to
     * parse the Messages
     */
    public synchronized void startMessageFetching()
    throws JacsonException {
        Properties props = System.getProperties();
        Session session = Session.getDefaultInstance(props, null);
        try{
            if (protocoll == null)
                protocoll = IMAP;
            Store store = session.getStore(protocoll);
            store.connect(mailServer, user, password);
            folder = store.getFolder("INBOX");
            if (folder == null)
                throw new JacsonException("INBOX could not be opened for "
                + user + "@" + mailServer);
            if (protocoll.equals(POP3))
                folder.open(folder.READ_ONLY);
            else if (protocoll.equals(IMAP))
                folder.open(folder.READ_WRITE);
            // if a SearchTerm is defined we only want the matching messages
            if (searchTerm != null)
                messages = folder.search(searchTerm);
            else
                messages = folder.getMessages();
            messageParserThread = new MailSource.MessageParserThread(messages);
            messageParserThread.start();
        } catch(Exception e){
            e.printStackTrace();
            throw new JacsonException(e.getMessage());
        }
    }
    
    /**
     * implementation analog to  LineChunkSource
     */
    public String message() {
        JacsonReport jr = getRegReport();
        jr.begin("mail");
        jr.report("protocoll", protocoll);
        jr.report("server", mailServer);
        jr.report("user", user);
        if ( messages != null )
            jr.report("mails", "" + messages.length);
        return "mail";
    }
    
    /**
     * implementation analog to  LineChunkSource
     */
    public void summary() {
        getRegReport().end();
    }
    
    /** Deliver a sequence of chunks (that is Strings).
     * The delievered chunks are in the same
     * format which the Message.writeTo(OutputStream os) provides.
     * To indicate the type of the current chunk the JacsonState parameter
     * de.spieleck.app.source.MailSource.ChunkType is set to one of the
     * following values:<ul>
     * <li>@link
     * Before
     * returning null and by that indicating the end of the sequence, cleanUp
     * is called to clean up resources.
     * @return The next String if available, null if sequence is finished.
     */
    public String nextChunk()
    throws JacsonException {
        // if not yet started we will start the MessageParser
        if (messageParserThread == null){
            startMessageFetching();
        }
        
        MarkedChunk chunk = null;
        synchronized( chunks ) {
            while ( chunks.isEmpty() && messageParserThread.isAlive() ) {
                try {
                    chunks.wait();
                }
                catch(InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
            chunk = (MarkedChunk) chunks.removeFirst();
        }
        if ( chunk == null ) {
            cleanUp();
            return null;
        }
        else {
            getRegState().put(JACSON_STATE_CHUNK_TYPE, chunk.getExtra());
            return chunk.getChunk();
        }
    }
    
    /**
     * main method for testing functionality
     */
    public static void main(String[] args)
    throws Exception {
        
        if (args.length < 3) {
            System.out.print("Usage java de.spieleck.apps." +
            "jacson.source.MailSource [-p <protocoll] [-f file] <user> " +
            "<password> <server>\n");
            System.out.print("Example java de.spieleck.apps.jacson.source." +
            " MailSource -p pop3 -f out.txt myuser mypassword myserver\n");
            System.out.println("-p specifies the used protocoll, default IMAP");
            System.out.println("-f specifies the file to write chunks in");
            System.out.println("If no file is given chunks are written to " +
            "standard out");
        }
        
        PrintWriter pw;
        // check if file param was given
        if (args[0].equals("-f"))
            pw = new PrintWriter(new FileWriter(args[1]));
        else if (args[2].equals("-f"))
            pw = new PrintWriter(new FileWriter(args[2]));
        else
            pw = new PrintWriter(System.out);
        
        int l = args.length;
        MailSource me = new MailSource(args[l-3], args[l-2], args[l-1]);
        
        // check if protocoll was given
        if (args[0].equals("-p"))
            me.setProtocoll(args[1]);
        else if (args[2].equals("-p"))
            me.setProtocoll(args[3]);
        // now we can start the MessageFetching
        me.startMessageFetching();
        //Thread.sleep(1000 * 5);
        JacsonState state = new JacsonState();
        String line = me.nextChunk();
        
        while(line != null){
            pw.println((String) state.get(JACSON_STATE_CHUNK_TYPE)
            + "<" + line + ">");
            line = me.nextChunk();
        }
        pw.flush();
        pw.close();
    }
    
    /**
     * threaded class for parsing the messages and writing the single lines
     * in a Stack
     */
    public class MessageParserThread
    extends Thread {
        private Message[] messages;
        
        /**
         * Constructs a MessageParserThread which will parse the given
         * messages
         */
        public MessageParserThread(Message[] messages) {
            this.messages = messages;
        }
        
        /**
         * parses the messages and writes the chunks to the chunk storage of
         * MailSource
         */
        public void run() {
            for(int i=0; i < messages.length; i++) {
                try {
                    
                    Enumeration headers = messages[i].getAllHeaders();
                    Header header;
                    while(headers.hasMoreElements()){
                        header = (Header) headers.nextElement();
                        synchronized(chunks) {
                            chunks.add(new MarkedChunk(header.getName() + ": " +
                            header.getValue(),
                            header.getName()));
                            chunks.notify();
                        }
                    }
                    BufferedReader br = new BufferedReader(
                    new InputStreamReader(messages[i].getInputStream()));
                    String line = null;
                    while((line = br.readLine()) != null) {
                        synchronized(chunks) {
                            chunks.add(new MarkedChunk(line, BODY));
                            chunks.notify();
                        }
                    }
                    br.close();
                }
                catch(Exception e) {
                    e.printStackTrace();
                }
            }
            synchronized(chunks) {
                chunks.notify();
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -