1 package org.jent.checksmtp;
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.io.OutputStream;
10 * Socket accept proceed
12 import java.io.OutputStreamWriter;
13 import java.io.PrintWriter;
15 import java.net.Socket;
16 import java.security.KeyManagementException;
17 import java.security.NoSuchAlgorithmException;
19 import java.util.ArrayList;
20 import java.util.ListIterator;
21 import java.util.regex.Pattern;
22 import javax.net.SocketFactory;
23 import javax.net.ssl.SSLContext;
24 import javax.net.ssl.TrustManager;
25 import org.jent.checksmtp.ssl.RespondingX509TrustManager;
28 public class Processer implements Runnable, ResultNotify {
29 private Socket client;
32 private final int RESULT_UNKNOWN = 0;
33 private final int RESULT_OK = 1;
34 private final int RESULT_NG = 2;
35 private int result = RESULT_UNKNOWN;
38 private final int R354StartInput = 354;
39 private final int R221ServiceClosing = 221;
40 private final int R451RequestedActionAbort = 451;
41 private final int R502CommandNotImplemented = 502;
43 //private final int R500SyntexErrorInCommand = 500;
44 //private final int R501SyntaxErrorInArguments = 501;
45 //private final int R503BadSequenceOfCommands = 503:
46 //private final int R504CommandParameterNotImplemented = 504:
47 //private final int R211SystemStatusRepl = 211;
48 //private final int R214HelpMessage = 214;
49 //private final int R220ServiceReady = 220;
50 //private final int R421ClosingTransmissionChannel = 421;
51 //private final int R250RequestedActionCompleted = 250;
52 //private final int R251UserNotLocal = 251;
53 //private final int R252CannotVRFYuser = 252;
54 //private final int R450RequestedMailActionNotTaken = 450;
55 //private final int R550RequestedActionNotTaken = 550;
56 //private final int R551UserNotLocal = 551;
57 //private final int R452RequestedActionNotTaken = 452;
58 //private final int R552RequestedMailActionAborted = 552;
59 //private final int R553RequestedActionNotTaken = 553;
60 //private final int R554TransactionFailed = 554;
63 private final String COMMAND_RCPT_TO = "RCPT TO:"; // NOI18N
64 private final String COMMAND_DATA = "DATA"; // NOI18N
65 private final String COMMAND_RESET = "RSET"; // NOI18N
66 private final String COMMAND_TURN = "TURN"; // NOI18N
68 private final String COMMAND_NOOP = "NOOP";
69 //private final String COMAMND_QUIT = "QUIT";
71 //private final String COMMAND_EXHELLO = "EHLO";
72 //private final String COMMAND_HELLO = "HELO";
73 //private final String COMMAND_MAIL = "MAIL FROM:";
74 //private final String COMMAND_VERIFY = "VRFY";
75 //private final String COMMAND_EXPAND = "EXPN";
76 //private final String COMMAND_HELP = "HELP";
77 public Processer(Socket client) {
82 InputStream serverInput;
83 OutputStream serverOutput;
84 InputStream clientInput;
85 OutputStream clientOutput;
87 BufferedReader serverReader;
88 PrintWriter serverWriter;
89 BufferedReader clientReader;
90 PrintWriter clientWriter;
92 SocketFactory socketFactory = null;
96 //Connect to SMTP Server host
97 String servername = ApplicationProperties.getSmtpServerHost();
100 int serverport = ApplicationProperties.getSmtpServerPort();
102 if ( ApplicationProperties.getSmtpServerSSL() ) {
103 //SMTP Server use SSL
104 System.out.println("SMTP Server use SSL.");
105 //socketFactory = SSLSocketFactory.getDefault();
106 //OreOre server connection support TrustManager setting.
108 SSLContext sslContext = SSLContext.getInstance("TLS"); //SSL,TLS,TLSv1.1
109 sslContext.init(null,
110 new TrustManager[]{ new RespondingX509TrustManager() }, null);
111 socketFactory = sslContext.getSocketFactory();
112 } catch (NoSuchAlgorithmException nsaEx ) {//from SSLContext.getDefault()
114 nsaEx.printStackTrace(System.err);
115 } catch (KeyManagementException kmEx) {//from SSLContext.init()
117 kmEx.printStackTrace(System.err);
118 } catch (IllegalStateException isEx) {//from SSLContext.getSocketFactory()
120 isEx.printStackTrace(System.err);
121 } catch (Exception ex) { //for new RespondingX506TrustManager()
123 ex.printStackTrace(System.err);
126 //SMTP Server is normal Socket.
127 socketFactory = SocketFactory.getDefault();
130 //Connection to true SMTP server.
131 server = socketFactory.createSocket(servername, serverport);
132 serverInput = server.getInputStream();
133 serverOutput = server.getOutputStream();
134 clientInput = client.getInputStream();
135 clientOutput = client.getOutputStream();
137 serverReader = new BufferedReader(new InputStreamReader(
138 server.getInputStream()));
139 serverWriter = new PrintWriter(new SmtpBufferedWriter(
140 new OutputStreamWriter(server.getOutputStream(),
141 "ISO-8859-1")), true); // NOI18N
142 clientReader = new BufferedReader(new InputStreamReader(
143 client.getInputStream()));
144 clientWriter = new PrintWriter(new SmtpBufferedWriter(
145 new OutputStreamWriter(client.getOutputStream(),
146 "ISO-8859-1")), true); // NOI18N
148 smtpStart(serverReader, clientWriter, clientReader, serverWriter);
150 //for SMTP Server connection test
151 //SocketProxy forServer = new SocketProxy(clientInput, serverOutput, 0);
152 //SocketProxy forClient = new SocketProxy(serverInput, clientOutput, 1);
153 //Thread forServerThread = new Thread(forServer);
154 //Thread forClientThread = new Thread(forClient);
155 //forServerThread.start();
156 ////Use this ThreadforClientThread.run();
161 } catch (IOException e) {
162 String errorMessage = java.util.ResourceBundle.getBundle("org/jent/checksmtp/Bundle").getString("Processer.error.Execption_occurred_at_starting_SMTP_thread.");
163 System.err.println(errorMessage);
164 new MessageDialogUI(errorMessage, e, MessageDialogUI.ERROR_MODE);
165 } catch (RuntimeException runEx) {
166 new MessageDialogUI(java.util.ResourceBundle.getBundle("org/jent/checksmtp/Bundle").getString("Processer.error.Runtime_Exception_occurred_in_SMTP_parse"),
167 runEx, MessageDialogUI.ERROR_MODE);
169 //for failsafe Socket close.
170 if (server != null) {
173 } catch (IOException ioEx ) {
174 //IGNORE close Exception
177 if (client != null) {
180 } catch (IOException ioEx ) {
181 //IGNORE close Exception
184 //LDAP Connection close.
189 private int getCode(String s) {
192 code = Integer.parseInt(s.substring(0, 3));
193 } catch (NumberFormatException nfEx) {
194 code = -1; //Unexpected: SMTP CODE is allway 3digits.
199 private boolean isCompliteCode(int code) {
200 return code >=200 && code<=299 ;
203 private boolean isErrorCode(int code) {
204 return code>=400 && code<=599;
207 private boolean isContinue(String s) {
208 if ('-' == s.charAt(3)) {
215 private boolean isRcptTo(String s) {
216 if (s.startsWith(COMMAND_RCPT_TO)) {
223 private boolean isData(String s) {
224 if (s.startsWith(COMMAND_DATA)) {
231 private boolean isTurn(String s) {
232 if (s.startsWith(COMMAND_TURN)) {
239 public void sayOK() {
244 public void sayNG() {
249 private synchronized void notifyResult() {
253 private void smtpStart(BufferedReader serverReader,
254 PrintWriter clientWriter, BufferedReader clientReader,
255 PrintWriter serverWriter) {
259 ArrayList toList = new ArrayList();
263 line = serverReader.readLine();
264 clientWriter.println(line);
265 System.out.println(line);
267 if (isContinue(line)) {
268 continue; //Server responce continue
272 if (R221ServiceClosing == getCode(line)) {
273 break; //end of session.
274 } else if (R354StartInput == getCode(line)) {
275 System.out.println("Send mail data.");
278 line = clientReader.readLine();
279 serverWriter.println(line);
281 if (line.equals(".")) { // NOI18N
282 break; //end of mail dara.
287 line = clientReader.readLine();
290 //Finish client stream.
291 System.err.println("Client disconnected.");
292 break; //force disconnect.
295 if (isRcptTo(line)) {
296 //stored To: address.
297 toList.add(formatToAddress(line));
298 } else if (isTurn(line)) {
299 System.err.println("'TURN' is unsupported command.");
300 clientWriter.println(R502CommandNotImplemented);
302 continue; //read next client request.
303 } else if (isData(line)) {
304 //Client want to send data. Check out toList.
305 ListIterator iterater = toList.listIterator();
307 while (iterater.hasNext()) {
308 System.out.println("ADDRESS CHECK:" + iterater.next());
312 result = RESULT_UNKNOWN; //refresh RESULT flag.
313 new ToListUI(this, toList);
315 while (result == RESULT_UNKNOWN) {
317 synchronized (this) {
318 wait(4000); //TODO: Configurable NOOP time
319 //Dummy SMTP server access while ToListUI dialog wait.
320 serverWriter.println(COMMAND_NOOP);
321 String serverReply = serverReader.readLine();
322 System.out.println(COMMAND_NOOP + ":ANSER is " + serverReply);
323 //Server MUST retrun "250 OK" by NOOP command.
324 if ( isErrorCode(getCode(serverReply)) ) {
325 System.err.println("Fatal Error. Server return error code by NOOP command.");
326 //Ignore Fatal Error.
329 } catch (InterruptedException e) {
330 System.err.println("Confirm dialog wait interrupted");
334 toList = new ArrayList(); //refresh TO address list.
336 if (result != RESULT_OK ) {
337 System.out.println("CANCEL sending mail.");
338 serverWriter.println(COMMAND_RESET);
339 line = serverReader.readLine(); //Server MUST retrun "250 OK"
340 System.out.println(COMMAND_RESET + ":ANSER is " + line);
341 if ( isErrorCode(getCode(line)) ) {
342 System.err.println("Fatal Error. Server return error code by RESET command.");
343 //Ignore Fatal Error.
345 clientWriter.println(R451RequestedActionAbort);
347 continue; //I think Client QUIT or Retry.
351 break; // client read while(true);
357 serverWriter.println(line);
358 System.out.println(line);
361 } catch (IOException e) {
362 String errorMessage = java.util.ResourceBundle.getBundle("org/jent/checksmtp/Bundle").getString("Processer.error.Error_occurred_in_SMTP_parse.");
363 System.err.println(errorMessage);
364 new MessageDialogUI(errorMessage, e, MessageDialogUI.ERROR_MODE);
365 } catch (RuntimeException runEx) {
366 new MessageDialogUI(java.util.ResourceBundle.getBundle("org/jent/checksmtp/Bundle").getString("Processer.error.Runtime_Exception_occurred_in_SMTP_parse"),
367 runEx, MessageDialogUI.ERROR_MODE);
370 System.out.println("End of Session.");
373 private String formatToAddress(String line) {
374 System.out.println("FIND To: " + line);
376 //Splitting Mail address.
377 String str = line.substring(COMMAND_RCPT_TO.length() + 1);
378 Pattern pattern = Pattern.compile("[< >]+"); // NOI18N
379 String[] address = pattern.split(str); // 0<1>2 3
382 for (i = 0; i < address.length; i++) {
383 if (!address[i].equals("")) { // NOI18N
389 str = address[i] + " " + LDAPSearch.search(address[i]); // NOI18N