added preliminary mailing list support
[org.ibex.mail.git] / src / org / ibex / mail / MailingList.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.mail;
6 import org.ibex.util.*;
7 import org.ibex.io.*;
8 import org.ibex.mail.target.*;
9 import org.ibex.mail.protocol.*;
10 import java.util.*;
11 import java.io.*;
12 import org.prevayler.*;
13 import org.prevayler.Query;
14
15 public class MailingList extends SkaringaFile {
16
17     public static MailingList getMailingList(String path) { return getMailingList(new File(path)); }
18     public static MailingList getMailingList(File path) {
19         if (!path.exists()) path.mkdirs();
20         File f = new File(path.getAbsolutePath() + File.separatorChar + ".mailinglist");
21         try {
22             if (!f.exists()) {
23                 MailingList ret = new MailingList(path);
24                 Subscriber s = new Subscriber();
25                 s.address = Address.parse("adam@megacz.com");
26                 ret.subscribers.put(s.address, s);
27                 /*
28                 Subscriber s = new Subscriber();
29                 s.address = Address.parse("david@zentus.com");
30                 ret.subscribers.put(s.address, s);
31                 Subscriber s = new Subscriber();
32                 s.address = Address.parse("brian@alliet.com");
33                 ret.subscribers.put(s.address, s);
34                 */
35                 ret.write(f);
36                 return ret;
37             } else {
38                 return (MailingList)SkaringaFile.read(f);
39             }
40         } catch (Exception e) {
41             Log.error(MailingList.class, e);
42             return null;
43         }
44     }
45
46     private transient File path;
47     public  transient Mailbox   archive;
48
49     private MailingList() { }
50     private MailingList(File path) {
51         this.path = path;
52         archive = FileBasedMailbox.getFileBasedMailbox(path.getAbsolutePath(), true); }
53
54     public static enum UserType         { Administrator, Moderator, Member }
55     public static enum SubscriptionType { All, None, Digest, MimeDigest }
56     public static enum Visibility       { Members, Public, Nobody }
57     public static enum Action           { Accept, Hold, Reject }
58
59     public  Address   address;
60     private long      secret;
61
62     public Hashtable    subscribers = new Hashtable();
63     public Filter[]     filters  = new Filter[0];
64
65     public String       homepage             = "";
66     public String       one_line_description = "";
67     public String       long_description     = "";
68     public String       message_footer       = "";
69
70     public Visibility   listVisibility       = Visibility.Nobody;
71     public Visibility   membershipVisibility = Visibility.Nobody;
72     public Visibility   archiveVisibility    = Visibility.Members;
73     public Action       defaultPostingType   = Action.Hold;
74
75     public int          bounceThreshhold     = 10;
76
77     public static class Subscriber {
78         public  Address          address;
79         public  Action           posting;
80         public  UserType         type;
81         public  SubscriptionType subscription;
82         public  boolean          send_copy_of_own_post;
83         public  boolean          filter_duplicates_when_ccd;
84     }
85
86     public static abstract class JSTarget extends org.ibex.js.JS.Obj implements Target { }
87     public transient JSTarget acceptor = new JSTarget() {
88             public void accept(Message m) throws IOException, MailException {
89                 Headers head = new Headers(m.headers.getStream());
90                 head.put("list-id", one_line_description + "<"+address+">");
91                 
92                 m = Message.newMessage(new Fountain.Concatenate(head, m.getBody()));
93                 Log.warn(MailingList.class, "archiving list message " + m.subject);
94                 archive.accept(m);
95                 
96                 for(java.util.Enumeration e = subscribers.elements(); e.hasMoreElements();) try {
97                     Subscriber s = (Subscriber)e.nextElement();
98                     Log.warn(MailingList.class, "  trying " + s.address);
99                     SMTP.Outgoing.accept(Message.newMessage(m, m.envelopeFrom, s.address));
100                     Log.warn("[list]", "successfully sent to " + s);
101                 } catch (Exception e2) { Log.error("[list]", e2); }
102             }
103         };
104
105
106     // Transactions ///////////////////////////////////////////////////////////////////////////
107     /*
108     public static Transaction create(final Address address, final Mailbox archive) {
109         final long random = new Random().nextLong();
110         return new Transaction() { public void executeOn(Object all, Date now) {
111             ((Hashtable)all).put(address.toString(false), new MailingList(address, archive, random)); } };
112     }
113
114     public static Transaction delete(final Address address) {
115         return new Transaction() { public void executeOn(Object o,Date now) {
116             ((Hashtable)o).remove(address.toString(false)); } }; }
117
118     public static Query all() { return new Query() { public Object query(Object o, Date now) {
119         Hashtable all = (Hashtable)o;
120         MailingList[] ret = new MailingList[all.size()];
121         java.util.Enumeration e = all.elements();
122         for(int i=0; i<ret.length; i++) ret[i] = (MailingList)e.nextElement();
123         return ret;
124     } }; }
125
126     public Query subscribers() { return new Query() { public Object query(Object o, Date now) {
127         Hashtable all = (Hashtable)o;
128         String[] ret = new String[subscribers.size()];
129         java.util.Enumeration e = subscribers.keys();
130         for(int i=0; i<ret.length; i++) ret[i] = e.nextElement().toString();
131         return ret;
132     } }; }
133
134     public static Query forAddress(final Address a) { return new Query() {
135             public Object query(Object o, Date now) {
136                 return ((Hashtable)o).get(a.toString(false)); } }; }
137
138     public static class AlterSubscription extends Confirmation {
139         public transient SubscriptionType newType = SubscriptionType.All;
140         public String list;
141         protected AlterSubscription(Address who, long expiration, String list, SubscriptionType newType) {
142             super(who, expiration); this.newType = newType; this.list = list; }
143         public String getDescription() { return "change your subscription"; }
144         public void executeOn(Object all, Date now) { getList(all, list).getSubscriber(who).subscription = newType; }
145     }
146     */
147
148     //public static class Filter {
149     //    public class EmergencyModerationFilter { }
150     //    public class MaximumLengthFilter { }
151     //    public class SpamFilter { }
152     //    public class MIMETypes { }
153     //    public class MungeReplyTo { }
154     //    public class AnonymizeSender { public boolean uncorrelated; }
155     //}
156 }