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 package org.apache.james.jspf.policies.local; 021 022 import org.apache.james.jspf.core.DNSLookupContinuation; 023 import org.apache.james.jspf.core.Logger; 024 import org.apache.james.jspf.core.MacroExpand; 025 import org.apache.james.jspf.core.SPF1Constants; 026 import org.apache.james.jspf.core.SPF1Record; 027 import org.apache.james.jspf.core.SPF1Utils; 028 import org.apache.james.jspf.core.SPFChecker; 029 import org.apache.james.jspf.core.SPFSession; 030 import org.apache.james.jspf.core.exceptions.NeutralException; 031 import org.apache.james.jspf.core.exceptions.NoneException; 032 import org.apache.james.jspf.core.exceptions.PermErrorException; 033 import org.apache.james.jspf.core.exceptions.TempErrorException; 034 import org.apache.james.jspf.policies.PolicyPostFilter; 035 import org.apache.james.jspf.terms.Modifier; 036 037 /** 038 * Policy to add a default explanation 039 */ 040 public final class DefaultExplanationPolicy implements PolicyPostFilter { 041 042 043 private final class ExplanationChecker implements SPFChecker { 044 045 /** 046 * @see org.apache.james.jspf.core.SPFChecker#checkSPF(org.apache.james.jspf.core.SPFSession) 047 */ 048 public DNSLookupContinuation checkSPF(SPFSession spfData) 049 throws PermErrorException, 050 NoneException, TempErrorException, 051 NeutralException { 052 String attExplanation = (String) spfData.getAttribute(ATTRIBUTE_DEFAULT_EXPLANATION_POLICY_EXPLANATION); 053 try { 054 String explanation = macroExpand.expand(attExplanation, spfData, MacroExpand.EXPLANATION); 055 056 spfData.setExplanation(explanation); 057 } catch (PermErrorException e) { 058 // Should never happen ! 059 log.debug("Invalid defaulfExplanation: " + attExplanation); 060 } 061 return null; 062 } 063 } 064 065 private final class DefaultExplanationChecker implements Modifier { 066 067 private SPFChecker explanationCheckr = new ExplanationChecker(); 068 069 /** 070 * @see org.apache.james.jspf.core.SPFChecker#checkSPF(org.apache.james.jspf.core.SPFSession) 071 */ 072 public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException, NoneException, TempErrorException, NeutralException { 073 074 if (SPF1Constants.FAIL.equals(spfData.getCurrentResult())) { 075 if (spfData.getExplanation()==null || spfData.getExplanation().equals("")) { 076 String explanation; 077 if (defExplanation == null) { 078 explanation = SPF1Utils.DEFAULT_EXPLANATION; 079 } else { 080 explanation = defExplanation; 081 } 082 spfData.setAttribute(ATTRIBUTE_DEFAULT_EXPLANATION_POLICY_EXPLANATION, explanation); 083 spfData.pushChecker(explanationCheckr); 084 return macroExpand.checkExpand(explanation, spfData, MacroExpand.EXPLANATION); 085 } 086 } 087 088 return null; 089 } 090 091 public String toString() { 092 if (defExplanation == null) { 093 return "defaultExplanation"; 094 } else { 095 return "defaultExplanation="+defExplanation; 096 } 097 } 098 099 /** 100 * (non-Javadoc) 101 * @see org.apache.james.jspf.terms.Modifier#enforceSingleInstance() 102 */ 103 public boolean enforceSingleInstance() { 104 return false; 105 } 106 } 107 108 private static final String ATTRIBUTE_DEFAULT_EXPLANATION_POLICY_EXPLANATION = "DefaultExplanationPolicy.explanation"; 109 110 /** 111 * log 112 */ 113 private Logger log; 114 /** 115 * the default explanation 116 */ 117 private String defExplanation; 118 119 private MacroExpand macroExpand; 120 121 /** 122 * @param log the logger 123 * @param explanation the default explanation 124 * @param macroExpand the MacroExpand service 125 */ 126 public DefaultExplanationPolicy(Logger log, String explanation, MacroExpand macroExpand) { 127 this.log = log; 128 this.defExplanation = explanation; 129 this.macroExpand = macroExpand; 130 } 131 132 /** 133 * @see org.apache.james.jspf.policies.PolicyPostFilter#getSPFRecord(java.lang.String, org.apache.james.jspf.core.SPF1Record) 134 */ 135 public SPF1Record getSPFRecord(String currentDomain, SPF1Record spfRecord) throws PermErrorException, TempErrorException, NoneException, NeutralException { 136 if (spfRecord == null) return null; 137 // Default explanation policy. 138 spfRecord.getModifiers().add(new DefaultExplanationChecker()); 139 return spfRecord; 140 } 141 }