001: /*
002: * PopSession.java
003: *
004: * Copyright (C) 2000-2002 Peter Graves
005: * $Id: PopSession.java,v 1.1.1.1 2002/09/24 16:09:55 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j.mail;
023:
024: import java.io.IOException;
025: import java.io.OutputStreamWriter;
026: import java.net.Socket;
027: import java.net.SocketException;
028: import org.armedbear.j.Log;
029: import org.armedbear.j.Netrc;
030: import org.armedbear.j.SocketConnection;
031:
032: public final class PopSession {
033: private static final int DEFAULT_PORT = 110;
034:
035: // States.
036: private static final int DISCONNECTED = 0;
037: private static final int AUTHORIZATION = 1;
038: private static final int TRANSACTION = 2;
039:
040: // Responses.
041: public static final int OK = 0;
042: public static final int ERR = 1;
043:
044: private int state;
045: private boolean echo = false;
046: private String host;
047: private final String user;
048: private String password;
049: private int port;
050: private Socket socket;
051: private MailReader reader;
052: private OutputStreamWriter writer;
053: private String errorText;
054:
055: private PopSession(PopURL url, String user, String password) {
056: this .host = url.getHost();
057: this .port = url.getPort();
058: this .user = user;
059: this .password = password;
060: }
061:
062: public final String getHost() {
063: return host;
064: }
065:
066: public final int getPort() {
067: return port;
068: }
069:
070: public final String getUser() {
071: return user;
072: }
073:
074: public final String getPassword() {
075: return password;
076: }
077:
078: public final void setPassword(String password) {
079: this .password = password;
080: }
081:
082: public final void setEcho(boolean b) {
083: echo = b;
084: }
085:
086: public final boolean getEcho() {
087: return echo;
088: }
089:
090: public final String getErrorText() {
091: return errorText;
092: }
093:
094: public static PopSession getSession(PopURL url) {
095: if (url.getHost() == null)
096: return null;
097: String user = url.getUser();
098: if (user == null)
099: user = System.getProperty("user.name");
100: String password = Netrc.getPassword(url.getHost(), user);
101: if (password == null)
102: return null;
103: return new PopSession(url, user, password);
104: }
105:
106: public static PopSession getSession(PopURL url, String user) {
107: String password = Netrc.getPassword(url.getHost(), user);
108: if (password == null)
109: return null;
110: return new PopSession(url, user, password);
111: }
112:
113: public static PopSession getSession(PopURL url, String user,
114: String password) {
115: return new PopSession(url, user, password);
116: }
117:
118: public boolean connect() {
119: setEcho(true);
120: socket = null;
121: errorText = null;
122: SocketConnection sc = new SocketConnection(host, port, 30000,
123: 200, null);
124: socket = sc.connect();
125: if (socket == null) {
126: errorText = sc.getErrorText();
127: return false;
128: }
129: setTimeout(30000); // 30-second timeout
130: state = AUTHORIZATION;
131: try {
132: reader = new MailReader(socket.getInputStream());
133: writer = new OutputStreamWriter(socket.getOutputStream());
134: if (readLine() != null) {
135: if (write("user " + user)) {
136: if (getResponse() == OK) {
137: if (write("pass " + password)) {
138: if (getResponse() == OK) {
139: state = TRANSACTION;
140: setEcho(false);
141: return true;
142: }
143: }
144: }
145: }
146: }
147: } catch (IOException e) {
148: Log.error(e);
149: }
150: // Something went astray.
151: disconnect();
152: errorText = "Login failed";
153: setEcho(false);
154: return false;
155: }
156:
157: // Set specified timeout (in milliseconds).
158: private synchronized void setTimeout(int ms) {
159: if (socket != null) {
160: try {
161: socket.setSoTimeout(ms);
162: } catch (SocketException e) {
163: Log.error(e);
164: }
165: } else
166: Log.debug("PopSession.setTimeout socket is null");
167: }
168:
169: public synchronized boolean logout() {
170: Log.debug("PopSession.logout");
171: boolean succeeded = false;
172: if (state > DISCONNECTED) {
173: setEcho(true);
174: write("quit");
175: if (getResponse() == OK)
176: succeeded = true;
177: }
178: disconnect();
179: return succeeded;
180: }
181:
182: public void disconnect() {
183: if (socket != null) {
184: try {
185: socket.close();
186: } catch (IOException e) {
187: Log.error(e);
188: }
189: }
190: state = DISCONNECTED;
191: }
192:
193: protected void finalize() {
194: Log.debug("PopSession.finalize");
195: }
196:
197: public synchronized String readLine() {
198: try {
199: String s = reader.readLine();
200: if (echo && s != null)
201: Log.debug("<== " + s);
202: return s;
203: } catch (IOException e) {
204: Log.error(e);
205: disconnect();
206: return null;
207: }
208: }
209:
210: public synchronized boolean write(String s) {
211: if (writer == null)
212: return false;
213: if (echo)
214: Log.debug("==> " + (s.startsWith("pass ") ? "pass" : s));
215: s += "\r\n";
216: try {
217: writer.write(s);
218: writer.flush();
219: return true;
220: } catch (IOException e) {
221: Log.error(e);
222: disconnect();
223: return false;
224: }
225: }
226:
227: public synchronized int getResponse() {
228: while (true) {
229: String s = readLine();
230: if (s == null) {
231: state = DISCONNECTED;
232: return ERR;
233: }
234: if (s.startsWith("+OK"))
235: return OK;
236: if (s.startsWith("-ERR"))
237: return ERR;
238: }
239: }
240: }
|