implemented Conference E-Mail - automagically send E-mail to all readers

or posters in a conference or topic
This commit is contained in:
Eric J. Bowersox 2001-12-04 05:11:45 +00:00
parent 89eb0b23d2
commit d89c2bfdcb
12 changed files with 627 additions and 1 deletions

View File

@ -285,6 +285,7 @@
<default id="Create.Private" role="Conference.Member"/>
</defaults>
<permissions>
<permission id="EMailParticipants" role="Conference.AnyAdmin"/>
</permissions>
</security-definition>
</security>

View File

@ -171,4 +171,7 @@ public interface ConferenceContext
public abstract boolean canSendInvitation();
public abstract void sendMailToParticipants(boolean posters, int day_limit, String subject, String text)
throws AccessError, DataException;
} // end interface ConferenceContext

View File

@ -110,5 +110,8 @@ public interface TopicContext
public abstract boolean canSendInvitation();
public abstract void sendMailToParticipants(boolean posters, int day_limit, String subject, String text)
throws AccessError, DataException;
} // end interface TopicContext

View File

@ -888,6 +888,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public TopicContext addTopic(String title, String zp_pseud, String zp_text)
throws DataException, AccessError
{
if (logger.isDebugEnabled())
logger.debug("addTopic(\"" + title + "\") entry");
if (!(getConferenceData().canCreateTopic(level)))
{ // not allowed to create a topic - bail out
logger.error("addTopic(): user not permitted to create new topic");
@ -920,6 +922,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{ // call down to create the new topic!
real_title = title_ch.getValue();
new_topic_inf = getConferenceData().createNewTopic(env,real_title,zp_pseud_ch.getValue(),zp_text);
if (logger.isDebugEnabled())
logger.debug("Created new topic ID #" + new_topic_inf.getTopicID());
} // end try
catch (NotYetFinishedException e)
@ -939,6 +943,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
StringBuffer sql = new StringBuffer("INSERT INTO topicsettings (topicid, uid, last_post) VALUES (");
sql.append(new_topic_inf.getTopicID()).append(", ").append(env.getUserID()).append(", '");
sql.append(SQLUtil.encodeDate(new_topic_inf.getCreateDate())).append("');");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
stmt.executeUpdate(sql.toString());
// update the conference last-post information
@ -1489,6 +1495,90 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end canSendInvitation
public void sendMailToParticipants(boolean posters, int day_limit, String subject, String text)
throws AccessError, DataException
{
if (logger.isDebugEnabled())
logger.debug("sendMailToParticipants(" + posters + "," + day_limit + ")");
if (!(env.testPermission("Conference.EMailParticipants")))
throw new AccessError("You are not permitted to send E-mail to conference participants.");
if (day_limit==0)
return; // no-op
java.util.Date stop_point = null;
if (day_limit>0)
{ // compute stop point as a number of days back from this instant
Calendar right_now = Calendar.getInstance();
right_now.add(Calendar.DAY_OF_MONTH,-day_limit);
stop_point = right_now.getTime();
} // end if
Connection conn = null;
ArrayList rc = new ArrayList();
try
{ // retrieve a connection
conn = env.getConnection();
Statement stmt = conn.createStatement();
// Build the SQL statement.
StringBuffer sql = new StringBuffer("SELECT c.email, ");
if (posters)
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 ");
if (posters)
sql.append("ISNULL(s.last_post) = 0 ORDER BY s.last_post DESC;");
else
sql.append("ISNULL(s.last_read) = 0 ORDER BY s.last_read DESC;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// Execute the query and start reading E-mail addresses.
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // accumulate E-mail addresses
if (stop_point!=null)
{ // see if we can stop the loop yet
java.util.Date x = SQLUtil.getFullDateTime(rs,2);
if (stop_point.compareTo(x)>0)
break;
} // end if
rc.add(rs.getString(1)); // save off the E-mail address
} // end while
if (logger.isDebugEnabled())
logger.debug("Selected " + rc.size() + " address(es) for E-mailing");
} // end try
catch (SQLException e)
{ // this becomes a DataException
logger.error("DB error getting active poster list: " + e.getMessage(),e);
throw new DataException("unable to get active poster listing: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
env.releaseConnection(conn);
} // end finally
if (rc.size()>0)
{ // send the actual E-mail messages in the background
MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(),
rc,subject,text);
agent.start();
} // end if
} // end if
/*--------------------------------------------------------------------------------
* Implementations from interface ConferenceBackend
*--------------------------------------------------------------------------------

View File

@ -0,0 +1,118 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.core.impl;
import java.util.*;
import org.apache.log4j.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.internals.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.htmlcheck.*;
class MailerAgent extends Thread
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(MailerAgent.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private EnvUser env; // the environment
private String from_name; // the "from" name
private String from_addr; // the "from" address
private List recipients; // who gets the message
private String subject; // message subject
private String text; // message text
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
MailerAgent(EnvUser env, String from_name, String from_addr, List recipients, String subject, String text)
{
super();
setDaemon(false);
this.env = env;
this.from_name = from_name;
this.from_addr = from_addr;
this.recipients = recipients;
this.subject = subject;
this.text = text;
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class Thread
*--------------------------------------------------------------------------------
*/
public void run()
{
NDC.push("MailerAgent");
try
{ // attach the signature to the message
StringBuffer buf = new StringBuffer(text);
buf.append("\n--\n").append(env.getStockMessage("signature"));
// Create the emailer object and load it up with most of the data.
Emailer em = env.getEngine().createEmailer();
em.setSubject(subject);
em.setText(buf.toString());
// Deliver the mail to each of the target addresses in turn.
Iterator it = recipients.iterator();
while (it.hasNext())
{ // get ready to deliver the mail...
String addr = (String)(it.next());
if (logger.isDebugEnabled())
logger.debug("Delivering to " + addr);
try
{ // set the recipient and send it out
em.setFrom(from_name,from_addr);
em.setTo(addr);
em.send();
} // end try
catch (EmailException e)
{ // log the error and move on
logger.error("Caught EmailException when trying to send to " + addr,e);
} // end catch
} // end while
} // end try
finally
{ // make sure and pop the diagnostic context before we go
NDC.pop();
} // end finally
} // end run
} // end class MailerAgent

View File

@ -51,7 +51,7 @@ class PostDeliveryAgent extends Thread
PostDeliveryAgent(EnvConference env, String txt, String pseud, String topicname, int topicnum, List addrs)
{
super("PostDeliveryAgent");
super();
setDaemon(false);
// Save the calling data.

View File

@ -1310,6 +1310,90 @@ class TopicUserContextImpl implements TopicContext
} // end canSendInvitation
public void sendMailToParticipants(boolean posters, int day_limit, String subject, String text)
throws AccessError, DataException
{
if (logger.isDebugEnabled())
logger.debug("sendMailToParticipants(" + posters + "," + day_limit + ")");
if (!(env.testPermission("Conference.EMailParticipants")))
throw new AccessError("You are not permitted to send E-mail to conference participants.");
if (day_limit==0)
return; // no-op
java.util.Date stop_point = null;
if (day_limit>0)
{ // compute stop point as a number of days back from this instant
Calendar right_now = Calendar.getInstance();
right_now.add(Calendar.DAY_OF_MONTH,-day_limit);
stop_point = right_now.getTime();
} // end if
Connection conn = null;
ArrayList rc = new ArrayList();
try
{ // retrieve a connection
conn = env.getConnection();
Statement stmt = conn.createStatement();
// Build the SQL statement.
StringBuffer sql = new StringBuffer("SELECT c.email, ");
if (posters)
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 ");
if (posters)
sql.append("ISNULL(s.last_post) = 0 ORDER BY s.last_post DESC;");
else
sql.append("ISNULL(s.last_read) = 0 ORDER BY s.last_read DESC;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// Execute the query and start reading E-mail addresses.
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // accumulate E-mail addresses
if (stop_point!=null)
{ // see if we can stop the loop yet
java.util.Date x = SQLUtil.getFullDateTime(rs,2);
if (stop_point.compareTo(x)>0)
break;
} // end if
rc.add(rs.getString(1)); // save off the E-mail address
} // end while
if (logger.isDebugEnabled())
logger.debug("Selected " + rc.size() + " address(es) for E-mailing");
} // end try
catch (SQLException e)
{ // this becomes a DataException
logger.error("DB error getting active poster list: " + e.getMessage(),e);
throw new DataException("unable to get active poster listing: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
env.releaseConnection(conn);
} // end finally
if (rc.size()>0)
{ // send the actual E-mail messages in the background
MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(),
rc,subject,text);
agent.start();
} // end if
} // end sendMailToParticipants
/*--------------------------------------------------------------------------------
* External operations usable only from within the package
*--------------------------------------------------------------------------------

View File

@ -158,6 +158,7 @@ public class ConfOperations extends VeniceServlet
* E = Edit Conference Settings (requires conference parameter)
* FX = Fixseen (requires conference parameter)
* H = Add Conference to Hotlist (requires conference parameter)
* I = Conference E-Mail (requires conference parameter)
* M = Manage Conference Membership (requires conference parameter)
* Q = Display Conference Manage menu (requires conference parameter)
* RP = Report on Posters (requires conference parameter)
@ -589,6 +590,30 @@ public class ConfOperations extends VeniceServlet
} // end if ("H" command)
if (cmd.equals("I"))
{ // "I" = "Conference E-Mail" (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,comm,true,on_error);
on_error = "confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID() + "&cmd=Q";
try
{ // return the conference E-mail view
return new ConferenceEMail(comm,conf);
} // end try
catch (DataException de)
{ // something wrong in the database
return new ErrorBox("Database Error","Database error getting topic list " + de.getMessage(),
on_error);
} // end catch
catch (AccessError ae)
{ // some lack of access is causing problems
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
} // end if ("I" command)
if (cmd.equals("DEL"))
{ // "DEL" = "Delete Conference (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,comm,true,on_error);
@ -1040,6 +1065,80 @@ public class ConfOperations extends VeniceServlet
} // end if ("M" command)
if (cmd.equals("I"))
{ // "I" = "Conference E-Mail"
ConferenceContext conf = getConferenceParameter(request,comm,true,on_error);
on_error = "confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID() + "&cmd=I";
if (isImageButtonClicked(request,"cancel")) // "Cancel" button pressed - bail out
throw new RedirectResult("confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID()
+ "&cmd=Q");
if (isImageButtonClicked(request,"send"))
{ // OK, figure out who we want to send E-mail to
try
{ // retrieve the topic we want to send to
TopicContext topic = null;
String s = request.getParameter("top");
if ((s!=null) && !(s.equals("0")))
topic = conf.getTopic(Short.parseShort(s));
// retrieve other parameters
final String ZERO = "0";
boolean posters = ZERO.equals(request.getParameter("porl"));
final String YES = "Y";
int ndays = -1;
if (YES.equals(request.getParameter("xday")))
{ // they selected "within the last X days"
try
{ // parse the number of days
s = request.getParameter("day");
if (s!=null)
ndays = Integer.parseInt(s);
else
ndays = 0;
} // end try
catch (NumberFormatException nfe)
{ // always fail safe when doing e-mail parameters!
ndays = 0;
} // end catch
} // end if
if (topic!=null)
topic.sendMailToParticipants(posters,ndays,request.getParameter("subj"),
request.getParameter("pb"));
else
conf.sendMailToParticipants(posters,ndays,request.getParameter("subj"),
request.getParameter("pb"));
} // end try
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // database error creating the conference
return new ErrorBox("Database Error","Database error sending E-mail: " + de.getMessage(),
on_error);
} // end catch
// all done - bounce back to the menu
throw new RedirectResult("confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID()
+ "&cmd=Q");
} // end if ("send" pressed)
// we don't know what button was pressed
logger.error("no known button click on ConfOperations.doPost, cmd=I");
return new ErrorBox("Internal Error","Unknown command button pressed",on_error);
} // end if ("I" command)
// unrecognized command!
logger.error("invalid command to ConfOperations.doPost: " + cmd);
return new ErrorBox("Internal Error","Invalid command to ConfOperations.doPost",on_error);

View File

@ -0,0 +1,152 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.servlets.format;
import java.io.IOException;
import java.io.Writer;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.except.*;
public class ConferenceEMail implements JSPRender
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Attribute name for request attribute
protected static final String ATTR_NAME = "com.silverwrist.venice.content.ConferenceEMail";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private CommunityContext comm; // the community we're in
private ConferenceContext conf; // the conference being listed
private List topics; // list of topics in that conference
private String locator = null; // locator string
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public ConferenceEMail(CommunityContext comm, ConferenceContext conf) throws DataException, AccessError
{
this.comm = comm;
this.conf = conf;
this.topics = conf.getTopicList(ConferenceContext.DISPLAY_ALL,ConferenceContext.SORT_NAME);
} // end constructor
/*--------------------------------------------------------------------------------
* External static functions
*--------------------------------------------------------------------------------
*/
public static ConferenceEMail retrieve(ServletRequest request)
{
return (ConferenceEMail)(request.getAttribute(ATTR_NAME));
} // end retrieve
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceContent
*--------------------------------------------------------------------------------
*/
public String getPageTitle(RenderData rdat)
{
return "Conference E-Mail: " + conf.getName();
} // end getPageTitle
public String getPageQID()
{
return null;
} // end getPageQID
/*--------------------------------------------------------------------------------
* Implementations from interface JSPRender
*--------------------------------------------------------------------------------
*/
public void store(ServletRequest request)
{
request.setAttribute(ATTR_NAME,this);
} // end store
public String getTargetJSPName()
{
return "conf_email.jsp";
} // end getTargetJSPName
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public final int getCommunityID()
{
return comm.getCommunityID();
} // end getCommunityID
public final int getConferenceID()
{
return conf.getConfID();
} // end getConferenceID
public final String getConferenceName()
{
return conf.getName();
} // end getConferenceName
public final String getLocator()
{
if (locator==null)
locator = "sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID();
return locator;
} // end getLocator
public final void writeTopicChoices(Writer out) throws IOException
{
out.write("<OPTION VALUE=\"0\" SELECTED>(Entire conference)</OPTION>\n");
Iterator it = topics.iterator();
while (it.hasNext())
{ // write out the entire topic list as a drop-down list
TopicContext topic = (TopicContext)(it.next());
out.write("<OPTION VALUE=\"" + topic.getTopicNumber() + "\">" + StringUtil.encodeHTML(topic.getName())
+ "</OPTION>\n");
} // end while
} // end writeTopicChoices
} // end class ConferenceEMail

73
web/format/conf_email.jsp Normal file
View File

@ -0,0 +1,73 @@
<%--
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
WARRANTY OF ANY KIND, either express or implied. See the License for the specific
language governing rights and limitations under the License.
The Original Code is the Venice Web Communities System.
The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
Contributor(s):
--%>
<%@ page import = "java.util.*" %>
<%@ page import = "com.silverwrist.util.StringUtil" %>
<%@ page import = "com.silverwrist.venice.core.*" %>
<%@ page import = "com.silverwrist.venice.servlets.Variables" %>
<%@ page import = "com.silverwrist.venice.servlets.format.*" %>
<%
ConferenceEMail data = ConferenceEMail.retrieve(request);
Variables.failIfNull(data);
RenderData rdat = RenderConfig.createRenderData(application,request,response);
%>
<% if (rdat.useHTMLComments()) { %><!-- E-mail to conference #<%= data.getConferenceID() %> --><% } %>
<% rdat.writeContentHeader(out,"Conference E-Mail:",data.getConferenceName()); %>
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("confops") %>"><DIV CLASS="content">
<INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getCommunityID() %>">
<INPUT TYPE="HIDDEN" NAME="conf" VALUE="<%= data.getConferenceID() %>">
<INPUT TYPE="HIDDEN" NAME="cmd" VALUE="I">
<TABLE BORDER=0 CELLPADDING=0>
<TR VALIGN=MIDDLE>
<TD ALIGN=LEFT CLASS="content" COLSPAN=2><%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %>
Send E-mail to all&nbsp;
<SELECT NAME="porl" SIZE="1">
<OPTION VALUE="0" SELECTED>posters in</OPTION>
<OPTION VALUE="1">readers of</OPTION>
</SELECT>
&nbsp;topic:&nbsp;
<SELECT NAME="top" SIZE="1">
<% data.writeTopicChoices(out); %>
</SELECT>
</FONT></TD>
</TR>
<TR VALIGN=MIDDLE>
<TD>&nbsp;</TD>
<TD ALIGN=LEFT CLASS="content"><%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %>
<INPUT TYPE=CHECKBOX NAME="xday" VALUE="Y">
Within the last <INPUT TYPE=TEXT NAME="day" VALUE="7" SIZE=3> day(s)
</FONT></TD>
</TR>
<TR VALIGN=MIDDLE>
<TD ALIGN=LEFT CLASS="content">
<%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %>Subject:</FONT>
</TD>
<TD ALIGN=LEFT CLASS="cinput"><INPUT TYPE=TEXT CLASS="cinput" NAME="subj" SIZE=65
MAXLENGTH=255 VALUE=""></TD>
</TR>
<TR VALIGN=MIDDLE>
<TD ALIGN=LEFT CLASS="cinput" COLSPAN=2><TEXTAREA NAME="pb" WRAP=HARD ROWS=7 COLS=80></TEXTAREA></TD>
</TR>
<TR VALIGN=MIDDLE><TD ALIGN=LEFT COLSPAN=2 CLASS="content">
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_send_email.gif") %>" NAME="send"
ALT="Send E-Mail" WIDTH=80 HEIGHT=24 BORDER=0>&nbsp;
<INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_cancel.gif") %>" NAME="cancel"
ALT="Cancel" WIDTH=80 HEIGHT=24 BORDER=0>
</TD></TR>
</TABLE>
</DIV></FORM>

View File

@ -55,3 +55,4 @@
</TD></TR>
</TABLE>
</FORM></DIV>

View File

@ -75,6 +75,8 @@
Conference Members</A><P>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=QR") %>">Conference
Activity Reports</A><P>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=I") %>">Conference
E-Mail</A><P>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=DEL") %>">Delete
Conference</A><P>
</B></FONT>