Browse Source

confirmation mail now template based.

drop_old_mail
Stephan Richter 3 years ago
parent
commit
19c20816f8
  1. 3
      .gitignore
  2. 2
      pom.xml
  3. 3
      src/main/java/de/srsoftware/widerhall/Constants.java
  4. 23
      src/main/java/de/srsoftware/widerhall/data/ListMember.java
  5. 28
      src/main/java/de/srsoftware/widerhall/data/MailingList.java
  6. 6
      src/main/java/de/srsoftware/widerhall/web/TemplateServlet.java
  7. 10
      src/main/java/de/srsoftware/widerhall/web/Web.java
  8. 17
      static/templates/confirmation_mail.st
  9. 6
      static/templates/subscribe_mail.st

3
.gitignore vendored

@ -3,4 +3,5 @@ archive
target target
config/config.json config/config.json
*.sqlite3 *.sqlite3
jquery-3.6.0.min.js jquery-3.6.0.min.js
src/main/resources/logback-test.xml

2
pom.xml

@ -6,7 +6,7 @@
<groupId>org.example</groupId> <groupId>org.example</groupId>
<artifactId>Widerhall</artifactId> <artifactId>Widerhall</artifactId>
<version>0.2.31</version> <version>0.2.32</version>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>

3
src/main/java/de/srsoftware/widerhall/Constants.java

@ -28,8 +28,7 @@ public class Constants {
public static final String SUBJECT = "subject"; public static final String SUBJECT = "subject";
public static final String TEXT = "text"; public static final String TEXT = "text";
public static final String TOKEN = "token"; public static final String TOKEN = "token";
public static final String URL = "url";
public static final String USER = "user"; public static final String USER = "user";
public static final String VARCHAR = "VARCHAR(255)"; public static final String VARCHAR = "VARCHAR(255)";
} }

23
src/main/java/de/srsoftware/widerhall/data/ListMember.java

@ -1,9 +1,13 @@
package de.srsoftware.widerhall.data; package de.srsoftware.widerhall.data;
import de.srsoftware.widerhall.Configuration;
import de.srsoftware.widerhall.Util; import de.srsoftware.widerhall.Util;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.stringtemplate.v4.ST;
import javax.mail.MessagingException;
import java.io.UnsupportedEncodingException;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.*;
@ -87,7 +91,7 @@ public class ListMember {
* @return * @return
* @throws SQLException * @throws SQLException
*/ */
public static User confirm(String token) throws SQLException { public static ListMember confirm(String token) throws SQLException {
var rs = Database.open().select(TABLE_NAME).where(TOKEN,token).compile().exec(); var rs = Database.open().select(TABLE_NAME).where(TOKEN,token).compile().exec();
if (rs.next()){ if (rs.next()){
var lm = ListMember.from(rs); var lm = ListMember.from(rs);
@ -103,12 +107,25 @@ public class ListMember {
.compile() .compile()
.run(); .run();
} }
return lm.user; return lm;
} }
return null; return null;
} }
public void sendConfirmationMail(ST template) throws SQLException, MessagingException {
var subject = t("[{}] Subscription complete!",list.name());
var data = new HashMap<String,Object>();
data.put(USER,user.safeMap());
data.put(LIST,list.minimalMap());
data.put(URL,Configuration.instance().baseUrl()+"/web/index");
if (list.isOpenForSubscribers()) data.put("open_list",true);
var text = template.add("data",data).render();
try {
list.smtp().send(list.email(),list.name(),user.email(),subject,text);
} catch (UnsupportedEncodingException e) {
LOG.warn("Failed to send list subscription confirmation!",e);
}
}
/** /**
* Create a new list member entry in the database. * Create a new list member entry in the database.
* If the member has the state AWAITING_CONFIRMATION, a token is assigned with the member, too. * If the member has the state AWAITING_CONFIRMATION, a token is assigned with the member, too.

28
src/main/java/de/srsoftware/widerhall/data/MailingList.java

@ -7,6 +7,7 @@ import de.srsoftware.widerhall.mail.ProblemListener;
import de.srsoftware.widerhall.mail.SmtpClient; import de.srsoftware.widerhall.mail.SmtpClient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.stringtemplate.v4.ST;
import javax.mail.*; import javax.mail.*;
import javax.mail.internet.AddressException; import javax.mail.internet.AddressException;
@ -60,6 +61,7 @@ public class MailingList implements MessageHandler, ProblemListener {
private static final int DEFAULT_STATE = STATE_PENDING|STATE_HIDE_RECEIVERS|STATE_PUBLIC_ARCHIVE; private static final int DEFAULT_STATE = STATE_PENDING|STATE_HIDE_RECEIVERS|STATE_PUBLIC_ARCHIVE;
private static final String RETAINED_FOLDER = "retained"; private static final String RETAINED_FOLDER = "retained";
private static final String LAST_ERROR = "last_error"; private static final String LAST_ERROR = "last_error";
private static final String LIST_NAME = "list_name";
private String email, name, lastError; private String email, name, lastError;
private int state; private int state;
private SmtpClient smtp; private SmtpClient smtp;
@ -532,21 +534,6 @@ public class MailingList implements MessageHandler, ProblemListener {
return this; return this;
} }
/**
* send an email to a potential subscriber asking for confirmation
* @param user
* @param token
* @throws MessagingException
* @throws UnsupportedEncodingException
*/
private void sendConfirmationRequest(User user, String token) throws MessagingException, UnsupportedEncodingException {
var subject = t("Please confirm your list subscription");
var config = Configuration.instance();
var url = new StringBuilder(config.baseUrl()).append("/web/confirm?token=").append(token);
var text = t("Please go to {} in order to complete your list subscription!",url);
smtp.send(email(),name(),user.email(),subject,text);
}
private void sentRetentionNotification(String senderEmail) { private void sentRetentionNotification(String senderEmail) {
try { try {
var receivers = members() var receivers = members()
@ -641,17 +628,24 @@ public class MailingList implements MessageHandler, ProblemListener {
* @throws SQLException * @throws SQLException
* @throws MessagingException * @throws MessagingException
*/ */
public void requestSubscription(User user, boolean skipConfirmation) throws SQLException, MessagingException { public void requestSubscription(User user, boolean skipConfirmation, ST template) throws SQLException, MessagingException {
var state = skipConfirmation ? ListMember.STATE_SUBSCRIBER : ListMember.STATE_AWAITING_CONFIRMATION; var state = skipConfirmation ? ListMember.STATE_SUBSCRIBER : ListMember.STATE_AWAITING_CONFIRMATION;
var member = ListMember.create(this,user,state); var member = ListMember.create(this,user,state);
if (skipConfirmation) return; if (skipConfirmation) return;
try { try {
sendConfirmationRequest(user, member.token()); var config = Configuration.instance();
var url = new StringBuilder(config.baseUrl()).append("/web/confirm?token=").append(member.token()).toString();
var subject = t("[{}] Please confirm your list subscription",name());
var text = template.add(URL,url).add(LIST_NAME,name()).render();
smtp.send(email(),name(),user.email(),subject,text);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new MessagingException(t("Failed to send email to {}",user.email()),e); throw new MessagingException(t("Failed to send email to {}",user.email()),e);
} }
} }
protected SmtpClient smtp(){
return smtp;
}
private String stamp() { private String stamp() {
return "["+name+"]"; return "["+name+"]";

6
src/main/java/de/srsoftware/widerhall/web/TemplateServlet.java

@ -1,6 +1,7 @@
package de.srsoftware.widerhall.web; package de.srsoftware.widerhall.web;
import de.srsoftware.widerhall.Configuration; import de.srsoftware.widerhall.Configuration;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup; import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STRawGroupDir; import org.stringtemplate.v4.STRawGroupDir;
@ -8,7 +9,6 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Map; import java.util.Map;
@ -24,6 +24,10 @@ public abstract class TemplateServlet extends HttpServlet {
loadTemplates(); loadTemplates();
} }
protected ST getTemplate(String name){
return templates.getInstanceOf(name);
}
protected String loadFile(String filename, HttpServletResponse resp) { protected String loadFile(String filename, HttpServletResponse resp) {
var path = String.join(File.separator,baseDir,"static",filename); var path = String.join(File.separator,baseDir,"static",filename);
var file = new File(path); var file = new File(path);

10
src/main/java/de/srsoftware/widerhall/web/Web.java

@ -142,8 +142,12 @@ public class Web extends TemplateServlet {
try { try {
var token = req.getParameter(TOKEN); var token = req.getParameter(TOKEN);
if (token== null || token.isBlank()) return t("Invalid or missing token!"); if (token== null || token.isBlank()) return t("Invalid or missing token!");
var user = ListMember.confirm(token); var listMember = ListMember.confirm(token);
if (user != null) return loadTemplate(INDEX,Map.of(USER,user.safeMap(),NOTES,"Confirmed list subscription!"),resp); if (listMember != null) {
listMember.sendConfirmationMail(getTemplate("confirmation_mail"));
return loadTemplate(INDEX,Map.of(USER,listMember.user().safeMap(),NOTES,"Confirmed list subscription!"),resp);
}
return t("Unknown user or token"); return t("Unknown user or token");
} catch (Exception e) { } catch (Exception e) {
LOG.debug("Failed to confirm list membership:",e); LOG.debug("Failed to confirm list membership:",e);
@ -517,7 +521,7 @@ public class Web extends TemplateServlet {
} }
try { try {
list.requestSubscription(user,skipConfirmation); list.requestSubscription(user,skipConfirmation,getTemplate("subscribe_mail"));
if (skipConfirmation) { if (skipConfirmation) {
data.put(NOTES, t("Successfully subscribed '{}' to '{}'.", user.email(), list.email())); data.put(NOTES, t("Successfully subscribed '{}' to '{}'.", user.email(), list.email()));
} else { } else {

17
static/templates/confirmation_mail.st

@ -0,0 +1,17 @@
Welcome, «data.user.name»!
You successfully subscribed to the "«data.list.name»" Mailing list!
«if(data.open_list)»
This is an open list. This means you may, at any time, send emails to «data.list.email» and we will forward your mail to the other subscribers.
«else»
This is a moderated list. This means, you (and all other subscribers) will receive any mails sent by a moderator. However, if you write (answer) messages to the list, only the moderators will receive your mail.
«endif»
If you want to answer exclusively to the author of an email you received via the list, you may find the respective address in the subject line of the received email.
If you wish to leave the list, you may, at any time, go to «data.url» and un-subscribe.
best wishes,
Stephan Richter (the software author)

6
static/templates/subscribe_mail.st

@ -0,0 +1,6 @@
Welcome to the "«list_name»" Mailing list subscription!
Someone, probably you, tried to register your email address!
If that was you, go to «url» in order to complete your list subscription.
If you did not wish to subscribe to the list, you may ignore this mail.
Loading…
Cancel
Save