001: /*
002: * Mail.java
003: *
004: * Copyright (C) 2000-2003 Peter Graves
005: * $Id: Mail.java,v 1.2 2003/06/29 00:19:34 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.UnsupportedEncodingException;
025: import java.io.Writer;
026: import java.net.InetAddress;
027: import java.text.SimpleDateFormat;
028: import java.util.Calendar;
029: import java.util.List;
030: import org.armedbear.j.Directories;
031: import org.armedbear.j.Editor;
032: import org.armedbear.j.File;
033: import org.armedbear.j.FastStringBuffer;
034: import org.armedbear.j.FastStringReader;
035: import org.armedbear.j.Headers;
036: import org.armedbear.j.Log;
037: import org.armedbear.j.Property;
038: import org.armedbear.j.Utilities;
039:
040: public final class Mail {
041: private static File sentMessagesFile;
042:
043: public static final File getSentMessagesFile() {
044: final String fcc = Editor.preferences().getStringProperty(
045: Property.FCC);
046: if (fcc == null)
047: return null;
048:
049: // For now, we just support a hard-coded scheme.
050: if (!fcc.equals("sent"))
051: return null;
052:
053: if (sentMessagesFile == null) {
054: File local = File.getInstance(Directories
055: .getMailDirectory(), "local");
056: File sent = File.getInstance(local, "sent");
057: if (!sent.isDirectory())
058: sent.mkdirs();
059: if (sent.isDirectory())
060: sentMessagesFile = File.getInstance(sent, "mbox");
061: }
062: return sentMessagesFile;
063: }
064:
065: public static final MailAddress getUserMailAddress() {
066: String address = Editor.preferences().getStringProperty(
067: Property.USER_MAIL_ADDRESS);
068: if (address == null)
069: return null;
070: return new MailAddress(Editor.preferences().getStringProperty(
071: Property.USER_FULL_NAME), address);
072: }
073:
074: public static boolean bounceMessage(Message message,
075: MailAddress[] to) {
076: if (message == null)
077: return false;
078: if (to == null)
079: return false;
080: SmtpSession session = SmtpSession.getDefaultSession();
081: if (session == null)
082: return false;
083: boolean succeeded = bounceMessage(message, to, session);
084: session.quit();
085: return succeeded;
086: }
087:
088: public static boolean bounceMessage(Message message,
089: MailAddress[] to, SmtpSession session) {
090: if (message == null)
091: return false;
092: if (to == null)
093: return false;
094: if (session == null)
095: return false;
096: session.setEcho(true);
097: session.writeLine("rset");
098: int response = session.getResponse();
099: if (response == 500) {
100: // "command unrecognized"
101: Log.warn("bounceMessage calling session.quit()...");
102: session.quit();
103: Log.warn("bounceMessage calling session.reconnect()...");
104: if (!session.connect())
105: return false;
106: session.writeLine("rset");
107: response = session.getResponse();
108: }
109: if (response != 250)
110: return false;
111: session.writeLine("mail from:<"
112: + getUserMailAddress().getAddress() + ">");
113: if (session.getResponse() != 250)
114: return false;
115: for (int i = 0; i < to.length; i++) {
116: String address = to[i].getAddress();
117: session.writeLine("rcpt to: " + address);
118: if (session.getResponse() != 250)
119: return false;
120: }
121: session.writeLine("data");
122: if (session.getResponse() != 354)
123: return false;
124: session.setEcho(false);
125: if (!writeMessageText(message, to, session))
126: return false;
127: session.setEcho(true);
128: session.writeLine(".");
129: boolean succeeded = session.getResponse() == 250;
130: session.setEcho(false);
131: return succeeded;
132: }
133:
134: private static boolean writeMessageText(Message message,
135: MailAddress[] to, Writer writer) {
136: try {
137: FastStringReader reader = new FastStringReader(message
138: .getRawHeaders());
139: String s;
140: while ((s = reader.readLine()) != null) {
141: if (s.startsWith("X-J-Status"))
142: continue;
143: if (s.startsWith("X-UIDL"))
144: continue;
145: writer.write(s);
146: writer.write("\r\n");
147: }
148:
149: // Add "Resent" headers.
150: writer.write("Resent-From: ");
151: writer.write(getUserMailAddress().toString());
152: writer.write("\r\n");
153:
154: writer.write("Resent-Date: ");
155: writer.write(RFC822Date.getDateTimeString());
156: writer.write("\r\n");
157:
158: writer.write("Resent-To: ");
159: int length = 11;
160: for (int i = 0; i < to.length; i++) {
161: String address = to[i].toString();
162: if (length + address.length() > 76) {
163: writer.write("\r\n\t");
164: length = 8; // Assuming tab width is 8.
165: }
166: writer.write(address);
167: length += address.length();
168: if (i < to.length - 1) {
169: writer.write(", ");
170: length += 2;
171: }
172: }
173: writer.write("\r\n");
174:
175: writer.write("Resent-Message-Id: ");
176: writer.write(generateMessageId());
177: writer.write("\r\n");
178:
179: // Terminate headers.
180: writer.write("\r\n");
181:
182: // Body.
183: String body = message.getRawBody();
184: String contentType = message
185: .getHeaderValue(Headers.CONTENT_TYPE);
186: if (contentType != null) {
187: String charset = Utilities
188: .getCharsetFromContentType(contentType);
189: String encoding = Utilities
190: .getEncodingFromCharset(charset);
191: if (!encoding.equalsIgnoreCase("iso-8859-1")) {
192: try {
193: byte[] bytes = body.getBytes(encoding);
194: body = new String(bytes, 0);
195: } catch (UnsupportedEncodingException e) {
196: Log.error(e);
197: }
198: }
199: }
200: writer.write(body);
201: if (!body.endsWith("\r\n"))
202: writer.write("\r\n");
203: return true;
204: } catch (Exception e) {
205: Log.error(e);
206: return false;
207: }
208: }
209:
210: private static long messageIdentifier = System.currentTimeMillis() % 10000;
211:
212: public static String generateMessageId() {
213: String hostName = null;
214: try {
215: InetAddress addr = InetAddress.getLocalHost();
216: hostName = addr.getHostName();
217: } catch (Exception e) {
218: Log.error(e);
219: }
220: if (hostName == null)
221: hostName = "unknown"; // Avoid NPE below.
222: SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
223: Calendar cal = Calendar.getInstance();
224: FastStringBuffer sb = new FastStringBuffer(128);
225: sb.append('<');
226: sb.append(df.format(cal.getTime()));
227: sb.append('.');
228: sb.append(messageIdentifier++);
229: sb.append('@');
230: sb.append(hostName);
231: sb.append('>');
232: return sb.toString();
233: }
234:
235: public static boolean writeFcc(Message message, String destination,
236: int flags) {
237: if (destination.startsWith("mailbox:"))
238: destination = destination.substring(8);
239: File file = File.getInstance(destination);
240: if (file == null)
241: return false;
242: if (!file.isLocal())
243: return false;
244: Mbox mbox = Mbox.getInstance(file);
245: if (!mbox.lock())
246: return false;
247: boolean result = mbox.appendMessage(message, flags);
248: mbox.unlock();
249: mbox.updateViews();
250: return result;
251: }
252: }
|