From 9cc34facf6e58fabd5d48a0f749c74161e8cbbfc Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Tue, 4 Dec 2001 20:50:04 +0000 Subject: [PATCH] added some safeguards for the mail to community members/conference participants: to wit, any user can opt-out from ALL those mailings with one setting; each message now carries a standard disKlaimer indicating how the user can opt-out (and it's REAL opt-out, not this fakey stuff the spammers do) --- etc/venice-config.xml | 49 +++++++++++++++++++ src/com/silverwrist/util/OptionSet.java | 13 +++++ .../venice/core/UserProperties.java | 14 ++++++ .../core/impl/AdminUserContextImpl.java | 3 ++ .../venice/core/impl/CommunityCoreData.java | 6 ++- .../core/impl/CommunityUserContextImpl.java | 11 ++++- .../core/impl/ConferenceUserContextImpl.java | 20 ++++++-- .../core/impl/TopicUserContextImpl.java | 22 +++++++-- .../venice/core/impl/UserContextImpl.java | 4 ++ .../format/AdminModifyUserDialog.java | 6 +++ .../servlets/format/EditProfileDialog.java | 6 +++ 11 files changed, 142 insertions(+), 12 deletions(-) diff --git a/etc/venice-config.xml b/etc/venice-config.xml index fb14b57..e163e8e 100644 --- a/etc/venice-config.xml +++ b/etc/venice-config.xml @@ -485,6 +485,55 @@ click the "Manage" button, and click the "Stop Subscribing To This Topic" link. New Post in ${topic.name} + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/silverwrist/util/OptionSet.java b/src/com/silverwrist/util/OptionSet.java index f15bc56..baf76db 100644 --- a/src/com/silverwrist/util/OptionSet.java +++ b/src/com/silverwrist/util/OptionSet.java @@ -257,4 +257,17 @@ public class OptionSet extends BitSet } // end asString + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + public static final char getOptionChar(int index) + { + if ((index<0) || (index>=ALPHA.length())) + throw new IndexOutOfBoundsException(); + return ALPHA.charAt(index); + + } // end getOptionChar + } // end class OptionSet diff --git a/src/com/silverwrist/venice/core/UserProperties.java b/src/com/silverwrist/venice/core/UserProperties.java index 462db0c..8b63b3b 100644 --- a/src/com/silverwrist/venice/core/UserProperties.java +++ b/src/com/silverwrist/venice/core/UserProperties.java @@ -25,6 +25,7 @@ public class UserProperties */ private boolean display_post_pictures; + private boolean mass_mail_opt_out; /*-------------------------------------------------------------------------------- * Constructor @@ -34,6 +35,7 @@ public class UserProperties public UserProperties() { display_post_pictures = false; + mass_mail_opt_out = false; } // end constructor @@ -54,4 +56,16 @@ public class UserProperties } // end setDisplayPostPictures + public final boolean getMassMailOptOut() + { + return mass_mail_opt_out; + + } // end getMassMailOptOut + + public final void setMassMailOptOut(boolean b) + { + mass_mail_opt_out = b; + + } // end setMassMailOptOut + } // end class UserProperties diff --git a/src/com/silverwrist/venice/core/impl/AdminUserContextImpl.java b/src/com/silverwrist/venice/core/impl/AdminUserContextImpl.java index 3bf6200..1d5daa0 100644 --- a/src/com/silverwrist/venice/core/impl/AdminUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/AdminUserContextImpl.java @@ -144,6 +144,7 @@ class AdminUserContextImpl implements AdminUserContext AdminUserProperties rc = new AdminUserProperties(); rc.setDisplayPostPictures(flags.get(UserContextImpl.BF_POSTPICTURES)); rc.setDisallowPhoto(flags.get(UserContextImpl.BF_ADM_NOPHOTO)); + rc.setMassMailOptOut(flags.get(UserContextImpl.BF_MASSMAIL_OPTOUT)); return rc; } // end createProperties @@ -156,6 +157,8 @@ class AdminUserContextImpl implements AdminUserContext rc.set(UserContextImpl.PROP_FLAGS); if (flags.assign(UserContextImpl.BF_ADM_NOPHOTO,props.getDisallowPhoto())) rc.set(UserContextImpl.PROP_FLAGS); + if (flags.assign(UserContextImpl.BF_MASSMAIL_OPTOUT,props.getMassMailOptOut())) + rc.set(UserContextImpl.PROP_FLAGS); return rc; diff --git a/src/com/silverwrist/venice/core/impl/CommunityCoreData.java b/src/com/silverwrist/venice/core/impl/CommunityCoreData.java index b1e4fbf..c2ef691 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityCoreData.java +++ b/src/com/silverwrist/venice/core/impl/CommunityCoreData.java @@ -1838,9 +1838,11 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend // create the SQL statement StringBuffer sql = - new StringBuffer("SELECT c.email FROM contacts c, users u, sigmember m " + new StringBuffer("SELECT c.email FROM contacts c, users u, sigmember m, propuser p " + "WHERE c.contactid = u.contactid AND u.uid = m.uid AND m.sigid = "); - sql.append(cid).append(" AND u.is_anon = 0;"); + sql.append(cid).append(" AND u.is_anon = 0 AND p.uid = u.uid AND p.ndx = "); + sql.append(UserContextImpl.PROP_FLAGS).append(" AND p.data NOT LIKE '%"); + sql.append(OptionSet.getOptionChar(UserContextImpl.BF_MASSMAIL_OPTOUT)).append("%';"); if (logger.isDebugEnabled()) logger.debug("SQL: " + sql.toString()); diff --git a/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java b/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java index 8bd397d..ed7f29a 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java @@ -1378,9 +1378,16 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend // get the mailing list List mail_list = getData().getMassMailList(); if (mail_list.size()>0) - { // send the mail in the background! + { // prepare the E-mail message text; append the disKlaimer at the end + HashMap vars = new HashMap(); + vars.put("community.name",env.getCommunityName()); + String disklaimer = env.getStockMessage("mass-community-notice"); + StringBuffer buf = new StringBuffer(text); + buf.append("\n\n").append(StringUtil.replaceAllVariables(disklaimer,vars)); + + // send the mail in the background! MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(), - mail_list,subject,text); + mail_list,subject,buf.toString()); agent.start(); } // end if diff --git a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java index 18b2b76..d25a082 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java @@ -1528,8 +1528,11 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend sql.append("s.last_post"); else sql.append("s.last_read"); - sql.append(" FROM contacts c, users u, confsettings s WHERE c.contactid = u.contactid " - + "AND u.uid = s.uid AND s.confid = ").append(confid).append(" AND u.is_anon = 0 AND "); + sql.append(" FROM contacts c, users u, confsettings s, propuser p WHERE c.contactid = u.contactid " + + "AND u.uid = s.uid AND s.confid = ").append(confid); + sql.append(" AND u.is_anon = 0 AND u.uid = p.uid AND p.ndx = ").append(UserContextImpl.PROP_FLAGS); + sql.append(" AND p.data NOT LIKE '%"); + sql.append(OptionSet.getOptionChar(UserContextImpl.BF_MASSMAIL_OPTOUT)).append("%' AND "); if (posters) sql.append("ISNULL(s.last_post) = 0 ORDER BY s.last_post DESC;"); else @@ -1570,9 +1573,18 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend } // end finally if (rc.size()>0) - { // send the actual E-mail messages in the background + { // prepare the E-mail message text; append the disKlaimer at the end + HashMap vars = new HashMap(); + vars.put("community.name",env.getCommunityName()); + vars.put("conference.name",env.getConferenceName()); + String disklaimer = + env.getStockMessage(posters ? "mass-conference-notice-poster" : "mass-conference-notice-reader"); + StringBuffer buf = new StringBuffer(text); + buf.append("\n\n").append(StringUtil.replaceAllVariables(disklaimer,vars)); + + // send the actual E-mail messages in the background MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(), - rc,subject,text); + rc,subject,buf.toString()); agent.start(); } // end if diff --git a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java index 281dbf3..03cd169 100644 --- a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java @@ -20,6 +20,7 @@ package com.silverwrist.venice.core.impl; import java.sql.*; import java.util.*; import org.apache.log4j.*; +import com.silverwrist.util.OptionSet; import com.silverwrist.util.StringUtil; import com.silverwrist.venice.core.*; import com.silverwrist.venice.core.internals.*; @@ -1343,8 +1344,11 @@ class TopicUserContextImpl implements TopicContext sql.append("s.last_post"); else sql.append("s.last_read"); - sql.append(" FROM contacts c, users u, topicsettings s WHERE c.contactid = u.contactid " - + "AND u.uid = s.uid AND s.topicid = ").append(topicid).append(" AND u.is_anon = 0 AND "); + sql.append(" FROM contacts c, users u, topicsettings s, propuser p WHERE c.contactid = u.contactid " + + "AND u.uid = s.uid AND s.topicid = ").append(topicid); + sql.append(" AND u.is_anon = 0 AND u.uid = p.uid AND p.ndx = ").append(UserContextImpl.PROP_FLAGS); + sql.append(" AND p.data NOT LIKE '%"); + sql.append(OptionSet.getOptionChar(UserContextImpl.BF_MASSMAIL_OPTOUT)).append("%' AND "); if (posters) sql.append("ISNULL(s.last_post) = 0 ORDER BY s.last_post DESC;"); else @@ -1385,9 +1389,19 @@ class TopicUserContextImpl implements TopicContext } // end finally if (rc.size()>0) - { // send the actual E-mail messages in the background + { // prepare the E-mail message text; append the disKlaimer at the end + HashMap vars = new HashMap(); + vars.put("community.name",env.getCommunityName()); + vars.put("conference.name",env.getConferenceName()); + vars.put("topic.name",name); + String disklaimer = + env.getStockMessage(posters ? "mass-topic-notice-poster" : "mass-topic-notice-reader"); + StringBuffer buf = new StringBuffer(text); + buf.append("\n\n").append(StringUtil.replaceAllVariables(disklaimer,vars)); + + // send the actual E-mail messages in the background MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(), - rc,subject,text); + rc,subject,buf.toString()); agent.start(); } // end if diff --git a/src/com/silverwrist/venice/core/impl/UserContextImpl.java b/src/com/silverwrist/venice/core/impl/UserContextImpl.java index df998ea..0ae9b4d 100644 --- a/src/com/silverwrist/venice/core/impl/UserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/UserContextImpl.java @@ -43,6 +43,7 @@ class UserContextImpl implements UserContext, UserBackend // Boolean flag indexes static final int BF_POSTPICTURES = 0; static final int BF_ADM_NOPHOTO = 1; + static final int BF_MASSMAIL_OPTOUT = 2; private static Category logger = Category.getInstance(UserContextImpl.class); @@ -311,6 +312,7 @@ class UserContextImpl implements UserContext, UserBackend { UserProperties rc = new UserProperties(); rc.setDisplayPostPictures(flags.get(BF_POSTPICTURES)); + rc.setMassMailOptOut(flags.get(BF_MASSMAIL_OPTOUT)); return rc; } // end createProperties @@ -321,6 +323,8 @@ class UserContextImpl implements UserContext, UserBackend if (flags.assign(BF_POSTPICTURES,props.getDisplayPostPictures())) rc.set(PROP_FLAGS); + if (flags.assign(BF_MASSMAIL_OPTOUT,props.getMassMailOptOut())) + rc.set(PROP_FLAGS); return rc; diff --git a/src/com/silverwrist/venice/servlets/format/AdminModifyUserDialog.java b/src/com/silverwrist/venice/servlets/format/AdminModifyUserDialog.java index 6c5fcd3..0f8067e 100644 --- a/src/com/silverwrist/venice/servlets/format/AdminModifyUserDialog.java +++ b/src/com/silverwrist/venice/servlets/format/AdminModifyUserDialog.java @@ -148,6 +148,9 @@ public class AdminModifyUserDialog extends ContentDialog addFormField(new CDFormCategoryHeader("User Preferences")); addFormField(new CDCheckBoxFormField("pic_in_post","Display user photos next to conference posts", "(where applicable)",YES)); + addFormField(new CDCheckBoxFormField("no_mass_mail", + "Don't send user mass E-mail from community/conference hosts", + null,YES)); addFormField(new CDLocaleListFormField("locale","Default locale","(for formatting dates/times)",true)); addFormField(new CDTimeZoneListFormField("tz","Default time zone",null,true)); addCommandButton(new CDImageButton("update","bn_update.gif","Update",80,24)); @@ -289,6 +292,8 @@ public class AdminModifyUserDialog extends ContentDialog photo_control.setLinkURL("adminuserphoto?uid=" + admuser.getUID()); if (props.getDisplayPostPictures()) setFieldValue("pic_in_post",YES); + if (props.getMassMailOptOut()) + setFieldValue("no_mass_mail",YES); setFieldValue("locale",admuser.getLocale().toString()); setFieldValue("tz",admuser.getTimeZone().getID()); @@ -348,6 +353,7 @@ public class AdminModifyUserDialog extends ContentDialog ci.setPrivateEmail(YES.equals(getFieldValue("pvt_email"))); ci.setURL(getFieldValue("url")); props.setDisplayPostPictures(YES.equals(getFieldValue("pic_in_post"))); + props.setMassMailOptOut(YES.equals(getFieldValue("no_mass_mail"))); // Store the completed contact info. admuser.putContactInfo(ci); diff --git a/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java b/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java index ee3941a..e5e6b1c 100644 --- a/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java +++ b/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java @@ -141,6 +141,9 @@ public class EditProfileDialog extends ContentDialog addFormField(new CDFormCategoryHeader("User Preferences")); addFormField(new CDCheckBoxFormField("pic_in_post","Display user photos next to conference posts", "(where applicable)",YES)); + addFormField(new CDCheckBoxFormField("no_mass_mail", + "Don't send me mass E-mail from community/conference hosts", + null,YES)); addFormField(new CDLocaleListFormField("locale","Default locale","(for formatting dates/times)",true)); addFormField(new CDTimeZoneListFormField("tz","Default time zone",null,true)); addCommandButton(new CDImageButton("update","bn_update.gif","Update",80,24)); @@ -241,6 +244,8 @@ public class EditProfileDialog extends ContentDialog photo_control.setLinkURL("userphoto?tgt=" + URLEncoder.encode(target)); if (props.getDisplayPostPictures()) setFieldValue("pic_in_post",YES); + if (props.getMassMailOptOut()) + setFieldValue("no_mass_mail",YES); setFieldValue("locale",uc.getLocale().toString()); setFieldValue("tz",uc.getTimeZone().getID()); @@ -285,6 +290,7 @@ public class EditProfileDialog extends ContentDialog // Save off the properties. props.setDisplayPostPictures(YES.equals(getFieldValue("pic_in_post"))); + props.setMassMailOptOut(YES.equals(getFieldValue("no_mass_mail"))); uc.setProperties(props); // Save off the user's description and preferences.