blob: a6672e8ceaf0e57458521054306039154c2f4082 [file] [log] [blame]
/****************************************************************
* 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.jspf.core;
import org.apache.james.jspf.core.exceptions.PermErrorException;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.function.Predicate;
/**
*
* This Class is used as a container between the other classes. All necessary
* values get stored here and get retrieved from here.
*
*/
public class SPFSession implements MacroData {
private String ipAddress = ""; // also used for (i)<sending-host>
private String mailFrom = ""; // (s)<responsible-sender>
private String hostName = ""; // (h)<sender-domain>
private String currentSenderPart = ""; // (l)
private String currentDomain = ""; // (d)<current-domain>
private String inAddress = "in-addr"; // (v)
private String clientDomain = null; // (p)
private String senderDomain = ""; // (o)
private String readableIP = null; // (c)
private String receivingDomain = null; // (r)
private int currentDepth = 0;
/**
* The maximum mechanismn which are allowed to use
*/
public static final int MAX_DEPTH = 10;
private String explanation = null;
private String currentResult = null;
private boolean ignoreExplanation = false;
private Map<String,Object> attributes = new HashMap<String,Object>();
private Stack<SPFChecker> checkers = new Stack<SPFChecker>();
private String currentResultExpanded;
/**
* Build the SPFSession from the given parameters
*
* @param mailFrom
* The emailaddress of the sender
* @param heloDomain
* The helo provided by the sender
* @param clientIP
* The ipaddress of the client
*
*/
public SPFSession(String mailFrom, String heloDomain, String clientIP) {
super();
this.mailFrom = mailFrom.trim();
this.hostName = heloDomain.trim();
try {
this.ipAddress = IPAddr.getProperIpAddress(clientIP.trim());
// get the in Address
this.inAddress = IPAddr.getInAddress(clientIP);
} catch (PermErrorException e) {
// ip was not rfc conform
this.setCurrentResultExpanded(e.getResult());
}
// if nullsender is used postmaster@helo will be used as email
if (mailFrom.equals("")) {
this.currentSenderPart = "postmaster";
this.senderDomain = hostName;
this.mailFrom = currentSenderPart + "@" + hostName;
} else {
String[] fromParts = mailFrom.split("@");
// What to do when mailFrom is "@example.com" ?
if (fromParts.length > 1) {
this.senderDomain = fromParts[fromParts.length -1];
this.currentSenderPart = mailFrom.substring(0, mailFrom.length() - senderDomain.length() - 1);
if (this.currentSenderPart.length() == 0) {
this.currentSenderPart = "postmaster";
}
} else {
this.currentSenderPart = "postmaster";
this.senderDomain = mailFrom;
}
}
this.currentDomain = this.senderDomain;
}
/**
* @see org.apache.james.jspf.core.MacroData#getCurrentSenderPart()
*/
public String getCurrentSenderPart() {
return currentSenderPart;
}
/**
* @see org.apache.james.jspf.core.MacroData#getMailFrom()
*/
public String getMailFrom() {
return mailFrom;
}
/**
* @see org.apache.james.jspf.core.MacroData#getHostName()
*/
public String getHostName() {
return hostName;
}
/**
* @see org.apache.james.jspf.core.MacroData#getCurrentDomain()
*/
public String getCurrentDomain() {
return currentDomain;
}
/**
* @see org.apache.james.jspf.core.MacroData#getInAddress()
*/
public String getInAddress() {
return inAddress;
}
/**
* @see org.apache.james.jspf.core.MacroData#getClientDomain()
*/
public String getClientDomain() {
return clientDomain;
}
/**
* Sets the calculated clientDomain
* @param clientDomain the new clientDomain
*/
public void setClientDomain(String clientDomain) {
this.clientDomain = clientDomain;
}
/**
* @see org.apache.james.jspf.core.MacroData#getSenderDomain()
*/
public String getSenderDomain() {
return senderDomain;
}
/**
* Get the ipAddress which was used to connect
*
* @return ipAddres
*/
public String getIpAddress() {
return ipAddress;
}
/**
* @see org.apache.james.jspf.core.MacroData#getMacroIpAddress()
*/
public String getMacroIpAddress() {
if (IPAddr.isIPV6(ipAddress)) {
try {
return IPAddr.getAddress(ipAddress).getNibbleFormat();
} catch (PermErrorException e) {
}
}
return ipAddress;
}
/**
* @see org.apache.james.jspf.core.MacroData#getTimeStamp()
*/
public long getTimeStamp() {
return System.currentTimeMillis();
}
/**
* @see org.apache.james.jspf.core.MacroData#getReadableIP()
*/
public String getReadableIP() {
if (readableIP == null) {
readableIP = IPAddr.getReadableIP(ipAddress);
}
return readableIP;
}
/**
* @see org.apache.james.jspf.core.MacroData#getReceivingDomain()
*/
public String getReceivingDomain() {
return receivingDomain;
}
/**
* Sets the new receiving domain
*
* @param receivingDomain the new receiving domain
*/
public void setReceivingDomain(String receivingDomain) {
this.receivingDomain = receivingDomain;
}
/**
* Increase the current depth:
*
* if we reach maximum calls we must throw a PermErrorException. See
* SPF-RFC Section 10.1. Processing Limits
*/
public void increaseCurrentDepth() throws PermErrorException {
this.currentDepth++;
if (currentDepth > MAX_DEPTH)
throw new PermErrorException(
"Maximum mechanism/modifiers calls done: "
+ currentDepth);
}
/**
* Set the currentDomain
*
* @param domain The current used domain
*/
public void setCurrentDomain(String domain) {
this.currentDomain = domain;
}
/**
* Set the explanation which will returned when a fail match
*
* @param explanation
* This String is set as explanation
*/
public void setExplanation(String explanation) {
this.explanation = explanation;
}
/**
* Get the explanation
*
* @return explanation
*/
public String getExplanation() {
return explanation;
}
/**
* Set the current result
*
* @param result
* result
*/
public void setCurrentResult(String result) {
this.currentResult = result;
}
/**
* Get the current result
*
* @return current result
*/
public String getCurrentResult() {
return currentResult;
}
/**
* Get set to true if the explanation should be ignored
*
* @param ignoreExplanation true or false
*/
public void setIgnoreExplanation(boolean ignoreExplanation) {
this.ignoreExplanation = ignoreExplanation;
}
/**
* Return true if the explanation should be ignored
*
* @return true of false
*/
public boolean ignoreExplanation() {
return ignoreExplanation;
}
/**
* Retrieve a stored attribute
*
* @param key the attribute key
* @return the stored attribute
*/
public Object getAttribute(String key) {
return attributes.get(key);
}
/**
* Sets a new attribute in the session
*
* @param key attribute key
* @param value the value for this attribute
*/
public void setAttribute(String key, Object value) {
this.attributes.put(key, value);
}
/**
* Remove the attribute stored under the given key
*
* @param key the key of the attribute
* @return object the attribute which was stored with the key
*/
public Object removeAttribute(String key) {
return this.attributes.remove(key);
}
/**
* Add the given SPFChecker on top of the stack
*
* @param checker
*/
public void pushChecker(SPFChecker checker) {
checkers.push(checker);
}
/**
* Remove the SPFChecker on the top and return it. If no SPFChecker is left
* null is returned
*
* @return the last checker
*/
public SPFChecker popChecker() {
if (checkers.isEmpty()) {
return null;
} else {
SPFChecker checker = checkers.pop();
return checker;
}
}
public SPFChecker popChecker(Predicate<SPFChecker> predicate) {
SPFChecker result = null;
while (result == null) {
if (checkers.isEmpty()) {
return null;
}
SPFChecker checker = checkers.pop();
if (predicate.test(checker)) {
result = checker;
}
}
return result;
}
/**
* @param result
*/
public void setCurrentResultExpanded(String result) {
this.currentResultExpanded = result;
}
/**
* @return current result converted/expanded
*/
public String getCurrentResultExpanded() {
return currentResultExpanded;
}
@Override
public String toString() {
return "SPFSession{" +
"ipAddress='" + ipAddress + '\'' +
", mailFrom='" + mailFrom + '\'' +
", hostName='" + hostName + '\'' +
", currentSenderPart='" + currentSenderPart + '\'' +
", currentDomain='" + currentDomain + '\'' +
", inAddress='" + inAddress + '\'' +
", clientDomain='" + clientDomain + '\'' +
", senderDomain='" + senderDomain + '\'' +
", readableIP='" + readableIP + '\'' +
", receivingDomain='" + receivingDomain + '\'' +
", currentDepth=" + currentDepth +
", explanation='" + explanation + '\'' +
", currentResult='" + currentResult + '\'' +
", ignoreExplanation=" + ignoreExplanation +
", attributes=" + attributes +
", checkers=" + checkers +
", currentResultExpanded='" + currentResultExpanded + '\'' +
'}';
}
}