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

📄 mboxmailrepository.java

📁 java mail,java mailjava mailjava mailjava mail
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/**************************************************************** * Licensed to the Apache Software Foundation (ASF) under one   * * or more contributor license agreements.  See the NOTICE file * * distributed with this work for additional information        * * regarding copyright ownership.  The ASF licenses this file   * * to you under the Apache License, Version 2.0 (the            * * "License"); you may not use this file except in compliance   * * with the License.  You may obtain a copy of the License at   * *                                                              * *   http://www.apache.org/licenses/LICENSE-2.0                 * *                                                              * * Unless required by applicable law or agreed to in writing,   * * software distributed under the License is distributed on an  * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       * * KIND, either express or implied.  See the License for the    * * specific language governing permissions and limitations      * * under the License.                                           * ****************************************************************//* TODO: * * 1. Currently, iterating through the message collection does not *    preserve the order in the file.  Change this with some form of *    OrderedMap.  There is a suitable class in Jakarta Commons *    Collections. * * 2. Optimize the remove operation. * * 3. Don't load entire message into memory.  This would mean computing *    the hash during I/O streaming, rather than loading entire message *    into memory, and using a MimeMessageWrapper with a suitable data *    source.  As a strawman, the interface to MessageAction would *    carry the hash, along with a size-limited stream providing the *    message body. * * 4. Decide what to do when there are IDENTICAL messages in the file. *    Right now only the last one will ever be processed, due to key *    collissions. * * 5. isComplete()  - DONE. * * 6. Buffered I/O. - Partially done, and optional. * */package org.apache.james.mailrepository;import org.apache.avalon.framework.activity.Initializable;import org.apache.avalon.framework.service.ServiceException;import org.apache.avalon.framework.service.ServiceManager;import org.apache.avalon.framework.service.Serviceable;import org.apache.avalon.framework.configuration.Configurable;import org.apache.avalon.framework.configuration.Configuration;import org.apache.avalon.framework.configuration.ConfigurationException;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.james.core.MailImpl;import org.apache.james.services.MailRepository;import org.apache.mailet.Mail;import org.apache.oro.text.regex.MalformedPatternException;import org.apache.oro.text.regex.Perl5Compiler;import org.apache.oro.text.regex.Pattern;import org.apache.oro.text.regex.Perl5Matcher;import javax.mail.MessagingException;import javax.mail.Session;import javax.mail.internet.MimeMessage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;import java.security.NoSuchAlgorithmException;import java.security.MessageDigest;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Collection;import java.util.Hashtable;import java.util.Iterator;import java.util.Locale;import java.util.Properties;/** * Implementation of a MailRepository using UNIX mbox files. * * <p>Requires a configuration element in the .conf.xml file of the form: *  <br>&lt;repository destinationURL="mbox://&lt;directory&gt;" *  <br>            type="MAIL" *  <br>&lt;/directory&gt; is where the individual mbox files are read from/written to * <br>Type can ONLY be MAIL (SPOOL is NOT supported) * * <p>Requires a logger called MailRepository. * * <p> Implementation notes: * <p> * This class keeps an internal store of the mbox file * When the internal mbox file is updated (added/deleted) * then the file will be re-read from disk and then written back. * This is a bit inefficent but means that the file on disk * should be correct. * <p> * The mbox store is mainly meant to be used as a one-way street. * Storing new emails is very fast (append to file) whereas reading them (via POP3) is * slower (read from disk and parse). * Therefore this implementation is best suited to people who wish to use the mbox format * for taking data out of James and into something else (IMAP server or mail list displayer) * * @version CVS $Revision: 495537 $ */public class MBoxMailRepository        extends AbstractLogEnabled            implements MailRepository, Serviceable, Configurable, Initializable {    static final SimpleDateFormat dy = new SimpleDateFormat("EE MMM dd HH:mm:ss yyyy", Locale.US);    static final String LOCKEXT = ".lock";    static final String WORKEXT = ".work";    static final int LOCKSLEEPDELAY = 2000; // 2 second back off in the event of a problem with the lock file    static final int MAXSLEEPTIMES = 100; //    static final long MLISTPRESIZEFACTOR = 10 * 1024;  // The hash table will be loaded with a initial capacity of  filelength/MLISTPRESIZEFACTOR    static final long DEFAULTMLISTCAPACITY = 20; // Set up a hashtable to have a meaningful default    /**     * Whether line buffering is turned used.     */    private static boolean BUFFERING = true;    /**     * Whether 'deep debugging' is turned on.     */    private static final boolean DEEP_DEBUG = true;    /**     * The internal list of the emails     * The key is an adapted MD5 checksum of the mail     */    private Hashtable mList = null;    /**     * The filename to read & write the mbox from/to     */    private String mboxFile;    /**     * A callback used when a message is read from the mbox file     */    public interface MessageAction {        public boolean isComplete();  // *** Not valid until AFTER each call to messageAction(...)!        public MimeMessage messageAction(String messageSeparator, String bodyText, long messageStart);    }    /**     * Convert a MimeMessage into raw text     * @param mc The mime message to convert     * @return A string representation of the mime message     * @throws IOException     * @throws MessagingException     */    private String getRawMessage(MimeMessage mc) throws IOException, MessagingException {        ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();        mc.writeTo(rawMessage);        return rawMessage.toString();    }    /**     * Parse a text block as an email and convert it into a mime message     * @param emailBody The headers and body of an email. This will be parsed into a mime message and stored     */    private MimeMessage convertTextToMimeMessage(String emailBody) {        //this.emailBody = emailBody;        MimeMessage mimeMessage = null;        // Parse the mime message as we have the full message now (in string format)        ByteArrayInputStream mb = new ByteArrayInputStream(emailBody.getBytes());        Properties props = System.getProperties();        Session session = Session.getDefaultInstance(props);        try {            mimeMessage = new MimeMessage(session, mb);        } catch (MessagingException e) {            getLogger().error("Unable to parse mime message!", e);        }        if (mimeMessage == null && getLogger().isDebugEnabled()) {            StringBuffer logBuffer =                    new StringBuffer(128)                    .append(this.getClass().getName())                    .append(" Mime message is null");            getLogger().debug(logBuffer.toString());        }        /*        String toAddr = null;        try {            // Attempt to read the TO field and see if it errors            toAddr = mimeMessage.getRecipients(javax.mail.Message.RecipientType.TO).toString();        } catch (Exception e) {            // It has errored, so time for plan B            // use the from field I suppose            try {                mimeMessage.setRecipients(javax.mail.Message.RecipientType.TO, mimeMessage.getFrom());                if (getLogger().isDebugEnabled()) {                    StringBuffer logBuffer =                            new StringBuffer(128)                            .append(this.getClass().getName())                            .append(" Patching To: field for message ")                            .append(" with  From: field");                    getLogger().debug(logBuffer.toString());                }            } catch (MessagingException e1) {                getLogger().error("Unable to set to: field to from: field", e);            }        } */        return mimeMessage;    }    /**     * Generate a hex representation of an MD5 checksum on the emailbody     * @param emailBody     * @return A hex representation of the text     * @throws NoSuchAlgorithmException     */    private String generateKeyValue(String emailBody) throws NoSuchAlgorithmException {        // MD5 the email body for a reilable (ha ha) key        byte[] digArray = MessageDigest.getInstance("MD5").digest(emailBody.getBytes());        StringBuffer digest = new StringBuffer();        for (int i = 0; i < digArray.length; i++) {            digest.append(Integer.toString(digArray[i], Character.MAX_RADIX).toUpperCase(Locale.US));        }        return digest.toString();    }    /**     * Parse the mbox file.     * @param ins The random access file to load. Note that the file may or may not start at offset 0 in the file     * @param messAct The action to take when a message is found     */    private MimeMessage parseMboxFile(RandomAccessFile ins, MessageAction messAct) {        if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {            StringBuffer logBuffer =                    new StringBuffer(128)                    .append(this.getClass().getName())                    .append(" Start parsing ")                    .append(mboxFile);            getLogger().debug(logBuffer.toString());        }        try {            Perl5Compiler sepMatchCompiler = new Perl5Compiler();            Pattern sepMatchPattern = sepMatchCompiler.compile("^From (.*) (.*):(.*):(.*)$");            Perl5Matcher sepMatch = new Perl5Matcher();            int c;            boolean inMessage = false;            StringBuffer messageBuffer = new StringBuffer();            String previousMessageSeparator = null;            boolean foundSep = false;            long prevMessageStart = ins.getFilePointer();            if (BUFFERING) {            String line = null;            while ((line = ins.readLine()) != null) {                foundSep = sepMatch.contains(line + "\n", sepMatchPattern);                if (foundSep && inMessage) {//                    if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) {//                        getLogger().debug(this.getClass().getName() + " Invoking " + messAct.getClass() + " at " + prevMessageStart);//                    }                    MimeMessage endResult = messAct.messageAction(previousMessageSeparator, messageBuffer.toString(), prevMessageStart);                    if (messAct.isComplete()) {                        // I've got what I want so just exit                        return endResult;                    }                    previousMessageSeparator = line;                    prevMessageStart = ins.getFilePointer() - line.length();                    messageBuffer = new StringBuffer();                    inMessage = true;                }                // Only done at the start (first header)                if (foundSep && !inMessage) {                    previousMessageSeparator = line.toString();                    inMessage = true;                }                if (!foundSep && inMessage) {

⌨️ 快捷键说明

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