X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Fmail%2FMailingList.java;h=9708118e942c989196c945cb4f9e1f213ee5eb63;hb=8f7212f973567b5caf9d8a4d7f9b5b400f53f44f;hp=f5fade4ef402c625d652997aaba8c468e18f7e71;hpb=49dc1421b8da25c4e0703e455bd5f1867e5dd269;p=org.ibex.mail.git diff --git a/src/org/ibex/mail/MailingList.java b/src/org/ibex/mail/MailingList.java index f5fade4..9708118 100644 --- a/src/org/ibex/mail/MailingList.java +++ b/src/org/ibex/mail/MailingList.java @@ -9,186 +9,223 @@ import org.ibex.mail.target.*; import org.ibex.mail.protocol.*; import java.util.*; import java.io.*; -import org.prevayler.*; -import org.prevayler.Query; - -// FEATURE: umbrella structure to mailing lists -public class MailingList extends Target implements Serializable { - - public static enum UserType { Administrator, Moderator, Member } - public static enum SubscriptionType { All, None, Digest, MimeDigest } - public static enum Visibility { Members, Public, Nobody } - public static enum Action { Accept, Hold, Reject } - - public Address address; - public Mailbox archive; - private final long secret; - private MailingList(Address a, Mailbox ar, long s) { this.address=a; this.archive=ar; this.secret=s; } - - public Hashtable subscribers = new Hashtable(); - public Filter[] filters = new Filter[0]; - - public String homepage = ""; - public String one_line_description = ""; - public String long_description = ""; - public String message_footer = ""; - - public Visibility listVisibility = Visibility.Nobody; - public Visibility membershipVisibility = Visibility.Nobody; - public Visibility archiveVisibility = Visibility.Members; - public Action defaultPostingType = Action.Hold; - - public int bounceThreshhold = 10; - - public static MailingList getList(Object all, String listName) { return (MailingList)((Hashtable)all).get(listName); } - public static MailingList getList(final String listName) { - try { - return (MailingList)p.execute(new Query() { public Object query(Object o, Date now) { return getList(o, listName); } }); - } catch (Exception e) { - Log.error(MailingList.class, e); - return null; - } - } - - public synchronized Subscriber getSubscriber(Address subscriber) { - Subscriber s = (Subscriber)subscribers.get(subscriber.toString(false)); - if (s == null) subscribers.put(subscriber, s = new Subscriber()); - return s; +import java.net.*; +import javax.servlet.*; +import javax.servlet.http.*; + +public class MailingList extends Mailbox.MailboxWrapper { + + // FIXME + public MailingList(File path, FileBasedMailbox fbm) throws IOException { + super(fbm); + this.path = path; + this.mailbox = fbm; + properties = new PropertiesFile(new File(path.getCanonicalPath() + File.separatorChar + "properties")); + address = new Address(properties.get("address")); + homepage = properties.get("homepage"); + one_line_description = properties.get("description"); + message_footer = properties.get("footer"); } - public static class Subscriber implements Serializable { - public Address address; - public Action posting; - public UserType type; - public SubscriptionType subscription; - public boolean send_copy_of_own_post; - public boolean filter_duplicates_when_ccd; - } - - //public static class Filter { - // public class EmergencyModerationFilter { } - // public class MaximumLengthFilter { } - // public class SpamFilter { } - // public class MIMETypes { } - // public class MungeReplyTo { } - // public class AnonymizeSender { public boolean uncorrelated; } - //} - - - public void accept(Message m) throws IOException, MailException { - try { - m = Message.newMessage(new Fountain.StringFountain("List-Id: " + one_line_description + "<"+address+">\r\n" + - m.toString() + - "--\r\n" + - message_footer + "\r\n" + - "to unsubscribe, go to " + homepage + "\r\n")); - } catch (Exception e2) { - Log.error("[list]", e2); - throw new IOException(e2.toString()); - } - Log.warn(MailingList.class, "got message " + m.subject); - archive.accept(m); - try { - String[] subscribers = (String[])p.execute(subscribers()); - Log.warn("**", "length is " + subscribers.length); - for(int i=0; i"); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println(" "); + */ + String confirm = request.getParameter("confirm"); + if (confirm != null) { + Subscribe sub = (Subscribe)Confirmation.decode(confirm, secret, new Date()); + String email = sub.email; + synchronized(this) { + String path = this.path.getAbsolutePath() + File.separatorChar + "subscribers" + File.separatorChar+sub.email; + if (sub.un) new File(path).delete(); + else { + Log.warn(null, "creating " + path); + new FileOutputStream(path).close(); } } - } catch (Exception e2) { - Log.error("[list]", e2); + pw.println(" successfully "+sub.adj+"d " + email + " to " + properties.get("address")); + } else { + String action = request.getParameter("action"); + String email = request.getParameter("email"); + if (action != null) { + Subscribe sub = new Subscribe(email, request.getRequestURL().toString(), action.equals("unsubscribe")); + sub.signAndSend(new Address(properties.get("owner")), + secret, new Date()); + pw.println("a confirmation email has been sent to " + email + + "; click the enclosed link to confirm your request to " + action); + } else { + pw.println("
"); + pw.println(" "+properties.get("address")+"
"); + pw.println(" "+properties.get("description")+" "); + pw.println("
"); + pw.println("access via: "); + if (path.getAbsolutePath().startsWith("/afs/")) + pw.println("[AFS] "); + pw.println("[NNTP]"); + pw.println("[SMTP]"); + pw.println("[HTTP]"); + pw.println("
"); + pw.println("
"); + pw.println(" "); + pw.println(" "); + pw.println(" "); + pw.println("
"); + pw.println("
"); + } } + //pw.println(" "); + //pw.println(""); + pw.flush(); } + public class Subscribe extends Confirmation { + public String email; + public String basename; + public boolean un; + public String adj; + public Subscribe(String email, String basename, boolean un) { + super(new Address(email), new Date().getTime() + (1000 * 60 * 60 * 24)); + this.email = email; + this.basename = basename; + this.un = un; + this.adj = un ? "unsubscribe" : "subscribe"; + } + public String getDescription() { return adj + " " + email + " to " + properties.get("address"); } + public String getURL(String tail) { return basename + "?frame=banner&confirm="+URLEncoder.encode(tail); } + } - // Transactions /////////////////////////////////////////////////////////////////////////// + private final File path; + private final PropertiesFile properties; + private final FileBasedMailbox mailbox; + private final long secret = new Random().nextLong(); + public final Address address; + public String homepage; - ////////////////////////////////////////////////////////////////////////////// + public String one_line_description; + public String message_footer; - public static final String ROOT = System.getProperty("ibex.mail.list.root", Mailbox.STORAGE_ROOT+File.separatorChar+"lists"); - public static Prevayler p; - static { try { - PrevaylerFactory pf = new PrevaylerFactory(); - //pf.configureSnapshotManager(new org.prevayler.implementation.snapshot.XmlSnapshotManager(new Hashtable(), ROOT)); - pf.configurePrevalenceBase(ROOT); - p = pf.create(); - } catch (Exception e) { Log.error(MailingList.class, e); } } + public int bounceThreshhold = 10; - public static Transaction subscribeNewUser(final Address user, final String list) { - return new Transaction() { public void executeOn(final Object o, final Date now) { - try { - new AlterSubscription(user, - now.getTime() + 1000*60*60*24, - list, - SubscriptionType.All).signAndSend(getList(o, list).secret, now); - } catch (Exception e) { - Log.error(MailingList.class, e); - } - } }; } + public static class Subscriber { + public Subscriber(Address a) { this.address = a; } + public Address address; + } - /* - static { - try { - if (getList("test") == null) { - Mailbox archive = FileBasedMailbox.getFileBasedMailbox("/var/org.ibex.mail/lists/test@testing.megacz.com", true); - p.execute(create(Address.parse("test@testing.megacz.com"), archive)); - p.execute(new Transaction() { public void executeOn(Object all, Date now) { - getList(all, "test@testing.megacz.com").getSubscriber(Address.parse("megacz@gmail.com")).subscription = SubscriptionType.All; - }}); + + // Pooling ////////////////////////////////////////////////////////////////////////////// + + public Iterable subscribers() { + return new Iterable() { + public java.util.Iterator iterator() { + final File subdir = new File(path.getAbsolutePath() + File.separatorChar + "subscribers"); + if (!subdir.exists()) subdir.mkdirs(); + final String[] subs = !subdir.isDirectory() ? new String[0] : subdir.list(); + return new java.util.Iterator() { + int i=0; + Subscriber prep = null; + public void remove() { + try { + new File(subdir.getAbsolutePath() + File.separatorChar + subs[i++]).delete(); + } catch (Exception e) { + Log.error(MailingList.class, e); + } + } + public boolean hasNext() { if (prep==null) prep = next(); return prep!=null; } + public Subscriber next() { + if (prep!=null) { Subscriber ret = prep; prep = null; return ret; } + while(i cache = new HashMap(); + public static MailingList getMailingList(String path) throws IOException { return getMailingList(new File(path)); } + public static MailingList getMailingList(File path) throws IOException { + if (!path.exists()) path.mkdirs(); + MailingList ret = cache.get(path.getCanonicalPath()); + if (ret==null) cache.put(path.getCanonicalPath(), ret = new MailingList(path)); + return ret; } */ + // Methods ////////////////////////////////////////////////////////////////////////////// - public static Transaction create(final Address address, final Mailbox archive) { - final long random = new Random().nextLong(); - return new Transaction() { public void executeOn(Object all, Date now) { - ((Hashtable)all).put(address.toString(false), new MailingList(address, archive, random)); } }; + public void add(Message message) { + try { + accept(message); + } catch (Exception e) { throw new RuntimeException(e); } } - - public static Transaction delete(final Address address) { - return new Transaction() { public void executeOn(Object o,Date now) { - ((Hashtable)o).remove(address.toString(false)); } }; } - - public static Query all() { return new Query() { public Object query(Object o, Date now) { - Hashtable all = (Hashtable)o; - MailingList[] ret = new MailingList[all.size()]; - java.util.Enumeration e = all.elements(); - for(int i=0; i"); + head = head.set("Subject", properties.get("prefix") + " " + head.get("Subject")); + + m = Message.newMessage(new Fountain.StringFountain(head.getString()+"\r\n"+buf.toString())); + Log.warn(MailingList.class, "archiving list message " + m.subject); + mailbox.accept(m); + + for(Subscriber s : subscribers()) try { + Log.warn(MailingList.class, " trying " + s.address); + SMTP.accept(Message.newMessage(m, m.envelopeFrom, s.address)); + Log.warn("[list]", "successfully sent to " + s); + } catch (Exception e2) { Log.error("[list]", e2); } + } catch (Exception e) { throw new RuntimeException(e); } } + //public Filter[] filters = new Filter[0]; + //public static class Filter { + // public class EmergencyModerationFilter { } + // public class MaximumLengthFilter { } + // public class SpamFilter { } + // public class MIMETypes { } + // public class MungeReplyTo { } + // public class AnonymizeSender { public boolean uncorrelated; } + //} } + + //public static enum UserType { Administrator, Moderator, Member } + //public static enum SubscriptionType { All, None, Digest, MimeDigest } + //public static enum Visibility { Members, Public, Nobody } + //public static enum Action { Accept, Hold, Reject } + //public Visibility listVisibility = Visibility.Nobody; + //public Visibility membershipVisibility = Visibility.Nobody; + //public Visibility archiveVisibility = Visibility.Members; + //public Action defaultPostingType = Action.Hold; + + //public Action posting = Action.Accept; + //public UserType type = UserType.Member; + //public SubscriptionType subscription = SubscriptionType.All; + //public boolean send_copy_of_own_post = false; + //public boolean filter_duplicates_when_ccd = true;