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

📄 mboxmailrepository.java

📁 java 开发的邮件服务器平台。支持以下协议。 协议可以修改为自己的专门标识
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************** * Copyright (c) 2000-2004 The Apache Software Foundation.             * * All rights reserved.                                                * * ------------------------------------------------------------------- * * Licensed 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.component.Component;import org.apache.avalon.framework.component.ComponentException;import org.apache.avalon.framework.component.ComponentManager;import org.apache.avalon.framework.component.Composable;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.context.Context;import org.apache.avalon.framework.context.ContextException;import org.apache.avalon.framework.context.Contextualizable;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.james.core.MailImpl;import org.apache.james.services.MailRepository;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 javax.mail.internet.InternetAddress;import java.util.*;import java.io.*;import java.security.NoSuchAlgorithmException;import java.security.MessageDigest;import java.text.SimpleDateFormat;import java.lang.reflect.Array;/** * 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: 1.1.2.5 $ */public class MBoxMailRepository        extends AbstractLogEnabled            implements MailRepository, Component, Contextualizable, Composable, 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 Avalon context used by the instance     */    private Context context;    /**     * 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);        String toAddr = null;        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());        }        /*        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());        }        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) {                    messageBuffer.append(line).append("\n");

⌨️ 快捷键说明

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