-// soft line limit (suggested): 78 chars / hard line limit: 998 chars
-// folded headers: can insert CRLF anywhere that whitespace appears (before the whitespace)
-// date/time parsing: see spec, 3.3
-
-// FEATURE: MIME RFC2045, 2046, 2049
-// FEATURE: PGP-signature-parsing
-// FEATURE: mailing list header parsing
-// FEATURE: delivery status notification (and the sneaky variety)
-// FEATURE: threading as in http://www.jwz.org/doc/threading.html
-
-public class Message extends JSReflection {
-
- // FIXME: case-insensitive header hashmap
- public int rfc822size() { return -1; } // FIXME
- public int numLines() { return -1; } // FIXME
- public int messageNum = -1;
-
- public final String allHeaders; // pristine headers
- public final Hashtable headers; // hash of headers (not including resent's and traces)
- public final String body; // entire body
-
- public final Date date;
- public final Address to;
- public final Address from; // if multiple From entries, this is sender
- public final Address replyto; // if none provided, this is equal to sender
- public final String subject;
- public final String messageid;
- public final Address[] cc;
- public final Address[] bcc;
- public final Hashtable[] resent;
- public final Trace[] traces;
-
- public final Address envelopeFrom;
- public final Address[] envelopeTo;
-
- public final Date arrival; // when the message first arrived at this machine; IMAP "internal date message attr"
-
- public void dump(OutputStream os) throws IOException {
- Writer w = new OutputStreamWriter(os);
- w.write(allHeaders);
- w.write("X-IbexMail-EnvelopeFrom: " + envelopeFrom + "\r\n");
- w.write("X-IbexMail-EnvelopeTo: "); for(int i=0; i<envelopeTo.length; i++) w.write(envelopeTo[i] + " "); w.write("\r\n");
- w.write("\r\n");
- w.write(body);
- w.flush();
+// FEATURE: body constraints (how to enforce without reading stream, though?)
+// - messages must NEVER contain 8-bit binary data; this is a violation of IMAP
+// - RFC822 1,000-char limit per line [soft line limit (suggested): 78 chars / hard line limit: 998 chars]
+
+/**
+ * [immutable] This class encapsulates a message "floating in the
+ * ether": RFC2822 data but no storage-specific flags or other
+ * metadata.
+ */
+public class Message extends MIME.Part {
+
+ // Parsed Headers //////////////////////////////////////////////////////////////////////////////
+
+ public final Address to;
+ public final Address from; // if multiple From entries, this is sender
+ public final Address envelopeFrom;
+ public final Address envelopeTo;
+ public final Date date;
+ public final Date arrival;
+ public final Address replyto; // if none provided, this is equal to sender
+ public final String subject;
+ public final String messageid;
+ public final Address[] cc;
+ public final Address[] bcc;
+
+ public static Message newMessage(Fountain in) throws Malformed { return new Message(in, null); }
+ public static Message newMessageFromHeadersAndBody(Headers head, Fountain body, Address from, Address to) throws Malformed {
+ return new Message(Fountain.Util.concat(head, Fountain.Util.create("\r\n"), body),
+ new String[] {
+ "Return-Path", from==null ? "<>" : from.toString(true),
+ "Envelope-To", to.toString(true)
+ });