You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2006/11/10 16:30:26 UTC

svn commit: r473367 - in /james/server/trunk/src: java/org/apache/james/smtpserver/core/filter/fastfail/ java/org/apache/james/util/junkscore/ test/org/apache/james/smtpserver/

Author: norman
Date: Fri Nov 10 07:30:25 2006
New Revision: 473367

URL: http://svn.apache.org/viewvc?view=rev&rev=473367
Log:
Create a JunkScoreHandler and the utils. First part for JAMES-614

Added:
    james/server/trunk/src/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java   (with props)
    james/server/trunk/src/java/org/apache/james/util/junkscore/
    james/server/trunk/src/java/org/apache/james/util/junkscore/ComposedJunkScore.java   (with props)
    james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScore.java   (with props)
    james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScoreImpl.java   (with props)
    james/server/trunk/src/test/org/apache/james/smtpserver/JunkScoreHandlerTest.java   (with props)

Added: james/server/trunk/src/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java?view=auto&rev=473367
==============================================================================
--- james/server/trunk/src/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java (added)
+++ james/server/trunk/src/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java Fri Nov 10 07:30:25 2006
@@ -0,0 +1,155 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+
+
+
+package org.apache.james.smtpserver.core.filter.fastfail;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+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.smtpserver.ConnectHandler;
+import org.apache.james.smtpserver.MessageHandler;
+import org.apache.james.smtpserver.SMTPSession;
+import org.apache.james.util.junkscore.ComposedJunkScore;
+import org.apache.james.util.junkscore.JunkScore;
+import org.apache.james.util.junkscore.JunkScoreImpl;
+import org.apache.james.util.mail.dsn.DSNStatus;
+
+public class JunkScoreHandler extends AbstractLogEnabled implements ConnectHandler, MessageHandler,Configurable {
+
+    private double maxScore = 0;
+    private String action;
+    private static final String REJECT_ACTION = "reject";
+    private static final String COMPOSE_ACTION = "compose";
+    private static final String HEADER_ACTION = "header";
+
+    /**
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+     */
+    public void configure(Configuration arg0) throws ConfigurationException {
+        Configuration maxScoreConfig = arg0.getChild("maxScore");
+
+        if (maxScoreConfig != null) {
+            setMaxScore(maxScoreConfig.getValueAsDouble(0));
+        }
+        
+        Configuration actionConfig = arg0.getChild("action");
+        if (actionConfig != null) {
+            setAction(actionConfig.getValue().toLowerCase());
+        } else {
+            throw new ConfigurationException("Please configure the action");
+        }
+    }
+    
+    public void setMaxScore(double maxScore) {
+        this.maxScore = maxScore;
+    }
+    
+    public void setAction(String action) throws ConfigurationException {
+        if (!action.equals(REJECT_ACTION) && !action.equals(COMPOSE_ACTION) && !action.equals(HEADER_ACTION)) 
+            throw new ConfigurationException("Illegal action: " + action);
+     
+        this.action = action;  
+    }
+    
+    /**
+     * @see org.apache.james.smtpserver.MessageHandler#onMessage(org.apache.james.smtpserver.SMTPSession)
+     */
+    public void onMessage(SMTPSession session) {
+        checkScore(session);
+    }
+
+    /**
+     * 
+     */
+    private void checkScore(SMTPSession session) {
+        JunkScore score1 = (JunkScore) session.getConnectionState().get(JunkScore.JUNK_SCORE_SESSION);
+        JunkScore score2 = (JunkScore) session.getState().get(JunkScore.JUNK_SCORE);
+        JunkScore composed = new ComposedJunkScore(score1,score2);
+        
+        if (action.equals(COMPOSE_ACTION)) {
+            // Save the scores attribute to maybe use it later!
+            session.getMail().setAttribute(JunkScore.JUNK_SCORE_SESSION_ATTR, String.valueOf(score1.getCompleteStoredScores()));
+            session.getMail().setAttribute(JunkScore.JUNK_SCORE_ATTR, String.valueOf(score2.getCompleteStoredScores()));
+            session.getMail().setAttribute(JunkScore.JUNK_SCORE_COMPOSED_ATTR, String.valueOf(composed.getCompleteStoredScores()));
+        } else if (action.equals(REJECT_ACTION)) {
+            if (maxScore <  composed.getCompleteStoredScores()) {
+
+                
+                String responseString = "554 "
+                    + DSNStatus.getStatus(DSNStatus.PERMANENT,
+                            DSNStatus.SECURITY_OTHER)
+                    + " This message reach the spam hits treshold. Please contact the Postmaster if the email is not SPAM. Message rejected";
+                StringBuffer buffer = new StringBuffer(256).append(
+                    "Rejected message from ").append(
+                    session.getState().get(SMTPSession.SENDER)
+                            .toString()).append(" from host ")
+                    .append(session.getRemoteHost()).append(" (")
+                    .append(session.getRemoteIPAddress()).append(
+                            ") " + responseString).append(
+                            ". Required rejection hits: "
+                                    + maxScore
+                                    + " hits: " + composed.getCompleteStoredScores());
+                getLogger().info(buffer.toString());
+                
+                session.writeResponse(responseString);
+                session.setStopHandlerProcessing(true);
+                session.abortMessage();
+            }
+        } else if (action.equals(HEADER_ACTION)) {
+            try {
+                MimeMessage message = session.getMail().getMessage();
+                Map scores = composed.getStoredScores();
+                Iterator itScores = scores.keySet().iterator();
+        
+                StringBuffer header = new StringBuffer();
+                while (itScores.hasNext()) {
+                    String key = itScores.next().toString();
+                    header.append(key);
+                    header.append("=");
+                    header.append(scores.get(key));
+                    header.append("; ");
+                }
+        
+                message.setHeader("X-JUNKSCORE", header.toString());
+                message.setHeader("X-JUNKSCORE-COMPOSED", String.valueOf(composed.getCompleteStoredScores()));
+        
+            } catch (MessagingException e) {
+                getLogger().info("Unable to add Junkscore to header: " + e.getMessage());
+            }
+        }
+    }
+        
+    /**
+     * @see org.apache.james.smtpserver.ConnectHandler#onConnect(org.apache.james.smtpserver.SMTPSession)
+     */
+    public void onConnect(SMTPSession session) {
+        session.getState().put(JunkScore.JUNK_SCORE, new JunkScoreImpl());
+        session.getConnectionState().put(JunkScore.JUNK_SCORE_SESSION, new JunkScoreImpl());
+    } 
+}

Propchange: james/server/trunk/src/java/org/apache/james/smtpserver/core/filter/fastfail/JunkScoreHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: james/server/trunk/src/java/org/apache/james/util/junkscore/ComposedJunkScore.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/util/junkscore/ComposedJunkScore.java?view=auto&rev=473367
==============================================================================
--- james/server/trunk/src/java/org/apache/james/util/junkscore/ComposedJunkScore.java (added)
+++ james/server/trunk/src/java/org/apache/james/util/junkscore/ComposedJunkScore.java Fri Nov 10 07:30:25 2006
@@ -0,0 +1,89 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+
+
+package org.apache.james.util.junkscore;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Class to compose the two Junkscore Objects 
+ */
+public class ComposedJunkScore implements JunkScore {
+
+    JunkScore score1;
+    
+    JunkScore score2;
+    
+    /**
+     * Construct Class
+     * 
+     * @param score1 The JunkScore for the whole session
+     * @param score2 The JunkScore for the nail
+     * @throws IllegalArgumentException get thrown if one of the given JunkScore Objects is null
+     */
+    public ComposedJunkScore (JunkScore score1, JunkScore score2) throws IllegalArgumentException {
+        if (score1 == null || score2 == null ) throw new IllegalArgumentException("JunkScore can not be null");
+        this.score1 = score1;
+        this.score2 = score2;
+    }
+    
+    /** 
+     * @see org.apache.james.util.junkscore.JunkScore#getCompleteStoredScores()
+     */
+    public double getCompleteStoredScores() {
+        return (score1.getCompleteStoredScores() + score2.getCompleteStoredScores());
+    }
+
+    
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#getStoredScore(java.lang.String)
+     */
+    public double getStoredScore(String key) {
+        return (score1.getStoredScore(key) + score2.getStoredScore(key));
+    }
+
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#getStoredScores()
+     */
+    public Map getStoredScores() {
+        // copy the Map
+        Map m = new HashMap(score1.getStoredScores());
+        m.putAll(score2.getStoredScores());
+        return m;
+    }
+
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#resetStoredScores()
+     */
+    public double resetStoredScores() {
+        return (score1.resetStoredScores() + score2.resetStoredScores());
+    }
+
+    /**
+     * Return only 0
+     */
+    public double setStoredScore(String key, double score) {
+        // just do nothing here and return 0
+        return 0;
+    }
+    
+}

Propchange: james/server/trunk/src/java/org/apache/james/util/junkscore/ComposedJunkScore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScore.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScore.java?view=auto&rev=473367
==============================================================================
--- james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScore.java (added)
+++ james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScore.java Fri Nov 10 07:30:25 2006
@@ -0,0 +1,83 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+
+
+
+package org.apache.james.util.junkscore;
+
+import java.util.Map;
+
+public interface JunkScore {
+    
+    /**
+     * The key for the JunkScore Object which holds scores per SMTPSession
+     */
+    public final String JUNK_SCORE_SESSION = "JUNK_SCORE_SESSION";
+    
+    /**
+     * The key for the JunkScore Object which holds scores per mail
+     */
+    public final String JUNK_SCORE = "JUNK_SCORE";
+    
+    public final String JUNK_SCORE_SESSION_ATTR = "org.apache.james.junkscore.session";
+    
+    public final String JUNK_SCORE_ATTR = "org.apache.james.junkscore";
+    
+    public final String JUNK_SCORE_COMPOSED_ATTR = "org.apache.james.junkscore.composed";
+    
+    /**
+     * Return the summary of stored scores
+     * 
+     * @return score the summary of all stored scores
+     */
+    public double getCompleteStoredScores();
+    
+    
+    /**
+     * Return a copy of the Map which contains the keys with the correspending scores
+     * 
+     * @return scoreMape the map which holds all keys and scores
+     */
+    public Map getStoredScores();
+    
+    /**
+     * Return the score for the given key. Returns 0 if no score with the given key exist
+     * 
+     * @param key the key to get the score for
+     * @return score the score
+     */
+    public double getStoredScore(String key);
+    
+    /**
+     * Set the score for the given key. Return the previous stored score for the key.
+     * 
+     * @param key the key under which the score should be stored
+     * @param score the store to score
+     * @return oldScore the previous scored stored under the given key
+     */
+    public double setStoredScore(String key, double score);
+
+    /**
+     * Reset the all stored scores in the map. Return the summary of the previous stored scores.
+     * 
+     * @return oldScore the summary of the old score;
+     */
+    public double resetStoredScores();
+}

Propchange: james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScoreImpl.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScoreImpl.java?view=auto&rev=473367
==============================================================================
--- james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScoreImpl.java (added)
+++ james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScoreImpl.java Fri Nov 10 07:30:25 2006
@@ -0,0 +1,97 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+
+package org.apache.james.util.junkscore;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 
+ * The Object which holds all junkscore
+ */
+public class JunkScoreImpl implements JunkScore {
+    
+    /**
+     * The map to store the scores
+     */
+    private Map scoreMap = new HashMap();
+    
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#getCompleteStoredScores()
+     */
+    public double getCompleteStoredScores() {
+        double count = 0;
+        Iterator s = scoreMap.keySet().iterator();
+    
+        while (s.hasNext()) {
+            count =+ Double.parseDouble(scoreMap.get(s.next()).toString());    
+        }
+        return count;
+    }
+    
+    
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#getStoredScores()
+     */
+    public Map getStoredScores() {
+        // Get sure we return a copy of the Map so it can not get wrong objects added
+        return new HashMap(scoreMap);
+    }
+    
+
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#getStoredScore(java.lang.String)
+     */
+    public double getStoredScore(String key) {
+        Object s = scoreMap.get(key);
+    
+        if (s != null) {
+            return Double.parseDouble(s.toString());
+        } else {
+            return 0;
+        }
+    }
+    
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#setStoredScore(java.lang.String, double)
+     */
+    public double setStoredScore(String key, double score) {
+        Object s = null; 
+        scoreMap.put(key, String.valueOf(score));
+        
+        if (s == null) {
+            return 0;
+        } else {
+            return Double.parseDouble(s.toString());
+        }
+    }
+
+    /**
+     * @see org.apache.james.util.junkscore.JunkScore#resetStoredScores()
+     */
+    public double resetStoredScores() {
+        double oldSum = getCompleteStoredScores();
+        scoreMap.clear();
+        return oldSum;
+    }
+
+}

Propchange: james/server/trunk/src/java/org/apache/james/util/junkscore/JunkScoreImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: james/server/trunk/src/test/org/apache/james/smtpserver/JunkScoreHandlerTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/test/org/apache/james/smtpserver/JunkScoreHandlerTest.java?view=auto&rev=473367
==============================================================================
--- james/server/trunk/src/test/org/apache/james/smtpserver/JunkScoreHandlerTest.java (added)
+++ james/server/trunk/src/test/org/apache/james/smtpserver/JunkScoreHandlerTest.java Fri Nov 10 07:30:25 2006
@@ -0,0 +1,159 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+
+package org.apache.james.smtpserver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.container.ContainerUtil;
+import org.apache.james.smtpserver.core.filter.fastfail.JunkScoreHandler;
+import org.apache.james.test.mock.avalon.MockLogger;
+import org.apache.james.test.mock.javaxmail.MockMimeMessage;
+import org.apache.james.test.mock.mailet.MockMail;
+import org.apache.james.util.junkscore.JunkScore;
+import org.apache.mailet.Mail;
+
+import junit.framework.TestCase;
+
+public class JunkScoreHandlerTest extends TestCase {
+    private String response = null;
+    private boolean stopped = false;
+    private boolean messageAborted = false;
+    private final static String KEY1 = "KEY1";
+    private final static String KEY2 = "KEY2";
+    private final static double SCORE1 = 10.0;
+    private final static double SCORE2 = 7.1;
+
+    public void setUp() {
+        response = null;
+        stopped = false;
+        messageAborted = false;
+    }
+    
+    private SMTPSession setupMockedSMTPSession() {
+        SMTPSession session = new AbstractSMTPSession() {
+            HashMap state = new HashMap();
+            HashMap cState = new HashMap();
+            Mail m = null;
+        
+            public Map getState() {
+            state.put(SMTPSession.SENDER, "sender@localhost");
+                return state;
+            }
+
+            public Map getConnectionState() {
+                return cState;
+            }
+
+            public void writeResponse(String resp) {
+                response = resp;
+            }
+
+            public void setStopHandlerProcessing(boolean b) {
+                stopped = b;
+            }
+
+            public void abortMessage() {
+                messageAborted = true;
+            }
+            
+            public Mail getMail(){
+                if (m == null) m = getMockMail();
+                return m;
+            }
+            
+            public String getRemoteHost() {
+                return "anyHost";
+            }
+            
+            public String getRemoteIPAddress() {
+                return "000.000.000.001";
+            }
+        };
+        return session;
+    }
+    
+    private Mail getMockMail(){
+        Mail m = new MockMail();
+        try {
+            m.setMessage(new MockMimeMessage());
+        } catch (MessagingException e) {
+            e.printStackTrace();
+        }
+        return m;
+    }
+    
+    public void testIllegalActionThrowException() {
+        boolean exception = false;
+        JunkScoreHandler handler = new JunkScoreHandler();
+        ContainerUtil.enableLogging(handler,new MockLogger());
+    
+        try {
+            handler.setAction("invalid");
+        } catch (ConfigurationException e) {
+            exception = true;
+        }
+    
+        assertTrue("Exception thrown",exception);
+    }
+    
+    public void testRejectAction() throws ConfigurationException {
+
+        SMTPSession session = setupMockedSMTPSession();
+        JunkScoreHandler handler = new JunkScoreHandler();
+        ContainerUtil.enableLogging(handler,new MockLogger());
+    
+        handler.setAction("reject");
+        handler.setMaxScore(15.0);
+        handler.onConnect(session);
+        handler.onMessage(session);
+
+        assertNull("Not rejected",response);
+        ((JunkScore) session.getState().get(JunkScore.JUNK_SCORE)).setStoredScore(KEY1, SCORE1);
+        ((JunkScore) session.getConnectionState().get(JunkScore.JUNK_SCORE_SESSION)).setStoredScore(KEY2, SCORE2);
+        handler.onMessage(session);
+    
+        assertNotNull("Rejected",response);
+        assertTrue("Rejected",stopped);
+        assertTrue("Rejected",messageAborted);
+    }
+    
+    public void testHeaderAction() throws ConfigurationException, MessagingException {
+        SMTPSession session = setupMockedSMTPSession();
+        JunkScoreHandler handler = new JunkScoreHandler();
+        ContainerUtil.enableLogging(handler,new MockLogger());
+    
+        handler.setAction("header");
+
+        handler.onConnect(session);
+        ((JunkScore) session.getState().get(JunkScore.JUNK_SCORE)).setStoredScore(KEY1, SCORE1);
+        ((JunkScore) session.getConnectionState().get(JunkScore.JUNK_SCORE_SESSION)).setStoredScore(KEY2, SCORE2);
+        handler.onMessage(session);
+    
+        MimeMessage message = session.getMail().getMessage();
+        assertNotNull("Header added",message.getHeader("X-JUNKSCORE")[0]);
+        assertNotNull("Header added",message.getHeader("X-JUNKSCORE-COMPOSED")[0]);
+    }
+}

Propchange: james/server/trunk/src/test/org/apache/james/smtpserver/JunkScoreHandlerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org