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.impl;
021
022 import org.apache.commons.cli.CommandLine;
023 import org.apache.commons.cli.CommandLineParser;
024 import org.apache.commons.cli.HelpFormatter;
025 import org.apache.commons.cli.OptionBuilder;
026 import org.apache.commons.cli.Options;
027 import org.apache.commons.cli.ParseException;
028 import org.apache.commons.cli.PosixParser;
029 import org.apache.james.jspf.core.exceptions.SPFErrorConstants;
030 import org.apache.james.jspf.executor.SPFResult;
031 import org.apache.log4j.ConsoleAppender;
032 import org.apache.log4j.Level;
033 import org.apache.log4j.Logger;
034 import org.apache.log4j.SimpleLayout;
035
036 /**
037 * This class is used for commandline usage of JSPF
038 *
039 */
040 public class SPFQuery {
041
042 private final static int PASS_RCODE = 0;
043
044 private final static int FAIL_RCODE = 1;
045
046 private final static int SOFTFAIL_RCODE = 2;
047
048 private final static int NEUTRAL_RCODE = 3;
049
050 private final static int TEMP_ERROR_RCODE = 4;
051
052 private final static int PERM_ERROR_RCODE = 5;
053
054 private final static int NONE_RCODE = 6;
055
056 private final static int UNKNOWN_RCODE = 255;
057
058 private final static String CMD_IP = "ip";
059 private final static char CHAR_IP = 'i';
060
061 private final static String CMD_SENDER = "sender";
062 private final static char CHAR_SENDER = 's';
063
064 private final static String CMD_HELO = "helo";
065 private final static char CHAR_HELO = 'h';
066
067 private final static String CMD_DEBUG = "debug";
068 private final static char CHAR_DEBUG = 'd';
069
070 private final static String CMD_VERBOSE = "verbose";
071 private final static char CHAR_VERBOSE = 'v';
072
073 private final static String CMD_DEFAULT_EXP = "default-explanation";
074 private final static char CHAR_DEFAULT_EXP = 'e';
075
076 private final static String CMD_BEST_GUESS = "enable-best-guess";
077 private final static char CHAR_BEST_GUESS = 'b';
078
079 private final static String CMD_TRUSTED_FORWARDER = "enable-trusted-forwarder";
080 private final static char CHAR_TRUSTED_FORWARDER = 't';
081
082 private static Logger logger = Logger.getRootLogger();
083
084 /**
085 * @param args
086 * The commandline arguments to parse
087 */
088 public static void main(String[] args) {
089
090 String ip = null;
091 String sender = null;
092 String helo = null;
093 String defaultExplanation = null;
094 boolean useBestGuess = false;
095 boolean useTrustedForwarder = false;
096
097 SimpleLayout layout = new SimpleLayout();
098 ConsoleAppender consoleAppender = new ConsoleAppender(layout);
099 logger.addAppender(consoleAppender);
100
101 logger.setLevel(Level.ERROR);
102
103 Options options = generateOptions();
104 CommandLineParser parser = new PosixParser();
105
106 try {
107 CommandLine line = parser.parse(options, args);
108
109 ip = line.getOptionValue(CHAR_IP);
110 sender = line.getOptionValue(CHAR_SENDER);
111 helo = line.getOptionValue(CHAR_HELO);
112 defaultExplanation = line.getOptionValue(CHAR_DEFAULT_EXP);
113 useBestGuess = line.hasOption(CHAR_BEST_GUESS);
114 useTrustedForwarder = line.hasOption(CHAR_TRUSTED_FORWARDER);
115 // check if all needed values was set
116 if (ip != null && sender != null && helo != null) {
117
118 if (line.hasOption(CHAR_DEBUG))
119 logger.setLevel(Level.DEBUG);
120 if (line.hasOption(CHAR_VERBOSE))
121 logger.setLevel(Level.TRACE);
122
123 SPF spf = new DefaultSPF(new Log4JLogger(logger));
124
125 // Check if we should set a costum default explanation
126 if (defaultExplanation != null) {
127 spf.setDefaultExplanation(defaultExplanation);
128 }
129
130 // Check if we should use best guess
131 if (useBestGuess == true) {
132 spf.setUseBestGuess(true);
133 }
134
135 if (useTrustedForwarder == true) {
136 spf.setUseTrustedForwarder(true);
137 }
138
139 SPFResult result = spf.checkSPF(ip, sender, helo);
140 System.out.println(result.getResult());
141 System.out.println(result.getHeader());
142 System.exit(getReturnCode(result.getResult()));
143
144 } else {
145 usage();
146 }
147 } catch (ParseException e) {
148 usage();
149 }
150 }
151
152 /**
153 * Return the generated Options
154 *
155 * @return options
156 */
157 private static Options generateOptions() {
158 Options options = new Options();
159
160 OptionBuilder.withLongOpt(CMD_IP);
161 OptionBuilder.withValueSeparator('=');
162 OptionBuilder.withArgName("ip");
163 OptionBuilder.withDescription("Sender IP address");
164 OptionBuilder.isRequired();
165 OptionBuilder.hasArg();
166 options.addOption(OptionBuilder.create(CHAR_IP));
167
168
169 OptionBuilder.withLongOpt(CMD_SENDER);
170 OptionBuilder.withValueSeparator('=');
171 OptionBuilder.withArgName("sender");
172 OptionBuilder.withDescription("Sender address");
173 OptionBuilder.isRequired();
174 OptionBuilder.hasArg();
175 options.addOption(OptionBuilder.create(CHAR_SENDER));
176
177 OptionBuilder.withLongOpt(CMD_HELO);
178 OptionBuilder.withValueSeparator('=');
179 OptionBuilder.withArgName("helo");
180 OptionBuilder.withDescription("Helo name");
181 OptionBuilder.isRequired();
182 OptionBuilder.hasArg();
183 options.addOption(OptionBuilder.create(CHAR_HELO));
184
185 OptionBuilder.withLongOpt(CMD_DEFAULT_EXP);
186 OptionBuilder.withValueSeparator('=');
187 OptionBuilder.withArgName("expl");
188 OptionBuilder.withDescription("Default explanation");
189 OptionBuilder.hasArg();
190 options.addOption(OptionBuilder.create(CHAR_DEFAULT_EXP));
191
192 OptionBuilder.withLongOpt(CMD_BEST_GUESS);
193 OptionBuilder.withArgName("bestguess");
194 OptionBuilder.withDescription("Enable 'best guess' rule");
195 options.addOption(OptionBuilder.create(CHAR_BEST_GUESS));
196
197 OptionBuilder.withLongOpt(CMD_TRUSTED_FORWARDER);
198 OptionBuilder.withArgName("trustedfwd");
199 OptionBuilder.withDescription("Enable 'trusted forwarder' rule");
200 options.addOption(OptionBuilder.create(CHAR_TRUSTED_FORWARDER));
201
202 OptionBuilder.withLongOpt(CMD_DEBUG);
203 OptionBuilder.withArgName("debug");
204 OptionBuilder.withDescription("Enable debug");
205 options.addOption(OptionBuilder.create(CHAR_DEBUG));
206
207 OptionBuilder.withLongOpt(CMD_VERBOSE);
208 OptionBuilder.withArgName("verbose");
209 OptionBuilder.withDescription("Enable verbose mode");
210 options.addOption(OptionBuilder.create(CHAR_VERBOSE));
211
212 return options;
213 }
214
215 /**
216 * Print out the usage
217 */
218 private static void usage() {
219 HelpFormatter hf = new HelpFormatter();
220 hf.printHelp("SPFQuery", generateOptions(), true);
221 System.exit(UNKNOWN_RCODE);
222 }
223
224 /**
225 * Return the return code for the result
226 *
227 * @param result
228 * The result
229 * @return returnCode
230 */
231 private static int getReturnCode(String result) {
232
233 if (result.equals(SPFErrorConstants.PASS_CONV)) {
234 return PASS_RCODE;
235 } else if (result.equals(SPFErrorConstants.FAIL_CONV)) {
236 return FAIL_RCODE;
237 } else if (result.equals(SPFErrorConstants.SOFTFAIL_CONV)) {
238 return SOFTFAIL_RCODE;
239 } else if (result.equals(SPFErrorConstants.NEUTRAL_CONV)) {
240 return NEUTRAL_RCODE;
241 } else if (result.equals(SPFErrorConstants.TEMP_ERROR_CONV)) {
242 return TEMP_ERROR_RCODE;
243 } else if (result.equals(SPFErrorConstants.PERM_ERROR_CONV)) {
244 return PERM_ERROR_RCODE;
245 } else if (result.equals(SPFErrorConstants.NONE_CONV)) {
246 return NONE_RCODE;
247 }
248
249 return UNKNOWN_RCODE;
250 }
251
252 }