BdkimUsageExample.java
001 /**
002  * BdkimUsageExample.java
003  * Copyright (c) 2011, Casey Connor
004  * All rights reserved.
005  
006  * Redistribution and use in source and binary forms, with or without modification,
007  * are permitted provided that the following conditions are met:
008  *
009  *    - Redistributions of source code must retain the above copyright notice, this
010  *      list of conditions and the following disclaimer.
011  *    - Redistributions in binary form must reproduce the above copyright notice,
012  *      this list of conditions and the following disclaimer in the documentation
013  *      and/or other materials provided with the distribution.
014  *    - Neither the name of Lacinato nor the names of its contributors may be used to
015  *      endorse or promote products derived from this software without specific prior
016  *      written permission.
017  *
018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
019  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
020  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
021  * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
023  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
024  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
025  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
026  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027  
028  * http://lacinato.com/cm/software/emailrelated/bdkim
029  
030  * This is an example of how to use the BdkimAnalyzer. The main method takes a command-line argument for the path to a raw email message file
031  * (containing all raw RFC-2822 headers and message content). It sends the message to the BDKIM perl server (which must be running and
032  * configured) and prints the results returned from the server to stdout.
033  
034  @author Casey Connor -- lacinato.com
035  @version 1.0
036  */
037 
038 package com.lacinato.tools.examples;
039 
040 import com.lacinato.tools.bdkim.BdkimAnalyzer;
041 import com.lacinato.tools.bdkim.AuthVerificationException;
042 import com.lacinato.tools.bdkim.BdkimAnalyzer.SignatureResults;
043 
044 import java.io.*;
045 
046 /**
047  * <a href="http://lacinato.com/cm/software/emailrelated/bdkim">http://lacinato.com/cm/software/emailrelated/bdkim</a>
048  <p/>
049  * This is a simple example of how to use the BdkimAnalyzer (and perhaps also useful for testing.) See the sourc code
050  * for the details.
051  <p/>
052  * The main() method takes three command-line arguments:<br/>
053  * - the path to a raw email message file (containing all raw headers and message content, etc)<br/>
054  * - the hostname or IP address of the BDKIM perl server (e.g. "localhost")<br/>
055  * - the port that the BDKIM perl server is using (e.g. 12300)
056  <p/>
057  * It sends the message over to the BDKIM perl server (which must be configured and running) and
058  * prints the results returned from the server to stdout.
059  <p/>
060  * For information on the BdkimAnalyzer.SignatureResults object, which contains the results in a
061  * structured form, see documentation for that class.
062  
063  @author Casey Connor -- <a href="http://lacinato.com">lacinato.com</a>
064  @version 1.0
065  */
066 public class BdkimUsageExample
067 {
068     public static void main(String[] args)
069     {
070         // args[0] is filename
071         // args[1] is hostname of BDKIM server (e.g. "localhost")
072         // args[2] is the port of the BDKIM server (e.g. 12300)
073         if (args.length < 3)
074         {
075             System.out.println("supply file name, host, and port!");
076             System.exit(1);
077         }
078 
079         // read in the source file:
080         String message_txt = null;
081         try message_txt = readMessageFile(args[0])}
082         catch (Exception e) { System.out.println("Got exception opening message file: " + e); System.exit(1)}
083 
084         // The lines have to have proper \r\n email message line-endings. You can either ensure proper
085         // line endings in the file itself before it is read in, here in Java (or your custom client), or on the
086         // perl side. We don't need to clean line endings because the deafult config of BdkimAnalyzer and
087         // BDKIM cleans them for us, but this is here in case you need it for testing, etc.
088         // message_txt = cleanLineEndings(message_txt);
089 
090         // make a new analyzer instance and configure it (in your program keep this reference around for re-use):
091         BdkimAnalyzer analyzer = new BdkimAnalyzer();
092         analyzer.setHost(args[1]);
093         try analyzer.setPort(Integer.parseInt(args[2]))}
094         catch (NumberFormatException nfe) { System.out.println("bad port number specified!"); System.exit(1)}
095 
096         BdkimAnalyzer.SignatureResults results = null;
097 
098         // compute the results (this sends to the BDKIM server):
099         try results = analyzer.determineDkimStatuses(message_txt)}
100         catch (AuthVerificationException ave)
101         {
102             System.out.println("Got exception when attempting to determineDkimStatuses: " + ave);
103             return;
104         }
105 
106         // Use the results:
107 
108         System.out.println("Summary result (not recommended for precise use): " + SignatureResults.resultToString(results.getSummaryResult()));
109 
110         System.out.println("\ntoString() result is as follows: " + results);
111 
112         System.out.println("\nResults per signature:");
113 
114         int num_sigs;
115 
116         if ((num_sigs = results.getNumberOfSignatures()) == 0)
117             System.out.println("NONE - there were no signatures found in the message.");
118         else
119         {
120             for (int i = 0; i < num_sigs; i++)
121             {
122                 System.out.println("-----------");
123                 System.out.println("Signature at index " + i + ":");
124                 System.out.println("Result: " + SignatureResults.resultToString(results.getResult(i)));
125                 System.out.println("Verbose result: " + results.getRawResult(i));
126                 System.out.println("Domain: " + results.getDomain(i));
127                 System.out.println("Headers signed by signature: " + results.getRawHeaderList(i));
128                 // could also fetch getHeaderList for an array form of the same
129             }
130         }
131     }
132 
133     /**
134      * Unused in default code above, but provided in case it's useful to you.
135      */
136     @SuppressWarnings("unused")
137     private static String cleanLineEndings(String message_text)
138     {
139         BufferedReader my_bufr = new BufferedReader(new StringReader(message_text));
140         
141         String line;
142         StringBuffer outp = new StringBuffer(message_text.length());
143 
144         try
145         {
146             while ((line = my_bufr.readLine()) != null)
147             {
148                 outp.append(line + "\r\n");
149             }
150         }
151         catch (IOException ioe)
152         {
153             System.out.println("Strange... couldn't fix line endings. Data is corrupt and will not work. IOException: " + ioe);
154             return(outp.toString());
155         }
156 
157         return(outp.toString());
158     }
159 
160     /**
161      * Read the file in.
162      */
163     private static String readMessageFile(String paththrows FileNotFoundException, IOException
164     {
165         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(path)));
166 
167         boolean go = true;
168         byte[] buf = new byte[4096];
169         int read = -1;
170         StringBuffer message_txt = new StringBuffer();
171 
172         while (go)
173         {
174             read = bis.read(buf, 04096);
175             if (read > 0message_txt.append(new String(buf, 0, read));
176             else go = false;
177         }
178 
179         bis.close();
180         return(message_txt.toString());
181     }
182 }