001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020
021 package org.apache.james.protocols.smtp.core.fastfail;
022
023 import java.util.ArrayList;
024 import java.util.Collection;
025 import java.util.HashMap;
026 import java.util.Map;
027
028 import org.apache.james.protocols.smtp.SMTPSession;
029 import org.apache.james.protocols.smtp.hook.HookResult;
030 import org.apache.james.protocols.smtp.hook.HookReturnCode;
031 import org.apache.james.protocols.smtp.hook.RcptHook;
032 import org.apache.mailet.MailAddress;
033
034 /**
035 * This handler can be used for providing a spam trap. IPAddresses which send emails to the configured
036 * recipients will get blacklisted for the configured time.
037 */
038 public class SpamTrapHandler implements RcptHook {
039
040 /** Map which hold blockedIps and blockTime in memory */
041 private Map<String,Long> blockedIps = new HashMap<String,Long>();
042
043 private Collection<String> spamTrapRecips = new ArrayList<String>();
044
045 /** Default blocktime 12 hours */
046 protected long blockTime = 4320000;
047
048
049 public void setSpamTrapRecipients(Collection<String> spamTrapRecips) {
050 this.spamTrapRecips = spamTrapRecips;
051 }
052
053 public void setBlockTime(long blockTime) {
054 this.blockTime = blockTime;
055 }
056
057 /**
058 * @see org.apache.james.protocols.smtp.hook.RcptHook#doRcpt(org.apache.james.protocols.smtp.SMTPSession, org.apache.mailet.MailAddress, org.apache.mailet.MailAddress)
059 */
060 public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
061 if (isBlocked(session.getRemoteIPAddress(), session)) {
062 return new HookResult(HookReturnCode.DENY);
063 } else {
064
065 if (spamTrapRecips.contains(rcpt.toString().toLowerCase())){
066
067 addIp(session.getRemoteIPAddress(), session);
068
069 return new HookResult(HookReturnCode.DENY);
070 }
071 }
072 return new HookResult(HookReturnCode.DECLINED);
073 }
074
075
076 /**
077 * Check if ipAddress is in the blockList.
078 *
079 * @param ip ipAddress to check
080 * @param session not null
081 * @return true or false
082 */
083 private boolean isBlocked(String ip, SMTPSession session) {
084 Long rawTime = blockedIps.get(ip);
085
086 if (rawTime != null) {
087 long blockTime = rawTime.longValue();
088
089 if (blockTime > System.currentTimeMillis()) {
090 session.getLogger().debug("BlockList contain Ip " + ip);
091 return true;
092 } else {
093 session.getLogger().debug("Remove ip " + ip + " from blockList");
094
095 synchronized(blockedIps) {
096 blockedIps.remove(ip);
097 }
098 }
099 }
100 return false;
101 }
102
103 /**
104 * Add ipaddress to blockList
105 *
106 * @param ip IpAddress to add
107 * @param session not null
108 */
109 private void addIp(String ip, SMTPSession session) {
110 long bTime = System.currentTimeMillis() + blockTime;
111
112 session.getLogger().debug("Add ip " + ip + " for " + bTime + " to blockList");
113
114 synchronized(blockedIps) {
115 blockedIps.put(ip, Long.valueOf(bTime));
116 }
117
118 }
119 }