diff --git a/pom.xml b/pom.xml index ec48e0b..20f4b79 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.example Widerhall - 0.2.33 + 0.2.35 diff --git a/src/main/java/de/srsoftware/widerhall/data/MailingList.java b/src/main/java/de/srsoftware/widerhall/data/MailingList.java index 80d45e4..064eac6 100644 --- a/src/main/java/de/srsoftware/widerhall/data/MailingList.java +++ b/src/main/java/de/srsoftware/widerhall/data/MailingList.java @@ -164,24 +164,22 @@ public class MailingList implements MessageHandler, ProblemListener { return this; } - private void forward(Message message) throws MessagingException { - try { - String newSender = !hasState(STATE_FORWARD_FROM) ? email() : null; - var receivers = members() - .stream() - .map(ListMember::user) - .map(User::email) - .toList(); - var subject = message.getSubject(); + private void forward(Message message, Stream members) throws MessagingException { + if (hasState(STATE_PUBLIC_ARCHIVE)) storeMessage(message); + String newSender = !hasState(STATE_FORWARD_FROM) ? email() : null; + var receivers = members + .map(ListMember::user) + .map(User::email) + .toList(); + var subject = message.getSubject(); - if (!subject.contains(stamp())) subject = stamp()+" "+subject; - var replyTo = (newSender == null && hasState(STATE_REPLY_TO_LIST)) ? email() : null; - smtp.forward(newSender,receivers,message,subject,hasState(STATE_FORWARD_ATTACHED),hasState(STATE_HIDE_RECEIVERS),replyTo); - } catch (SQLException e) { - LOG.error("Laden der Listen-Mitglieder von {} fehlgeschlagen. Nachricht kann nicht weitergeleitet werden!",email(),e); - } + if (!subject.contains(stamp())) subject = stamp()+" "+subject; + var replyTo = (newSender == null && hasState(STATE_REPLY_TO_LIST)) ? email() : null; + smtp.forward(newSender,receivers,message,subject,hasState(STATE_FORWARD_ATTACHED),hasState(STATE_HIDE_RECEIVERS),replyTo); } + + public MailingList forwardAttached(boolean forward) throws SQLException { return setFlag(STATE_FORWARD_ATTACHED,forward); } @@ -217,16 +215,6 @@ public class MailingList implements MessageHandler, ProblemListener { return ml; } - private boolean hashMember(String senderEmail) { - if (senderEmail == null) return false; - try { - return members().stream().map(ListMember::user).map(User::email).anyMatch(senderEmail::equals); - } catch (SQLException e) { - LOG.warn("hasMember() fehlgeschlagen für {}",email(),e); - } - return false; - } - public boolean hasState(int test){ return (state & test) > 0; } @@ -239,20 +227,6 @@ public class MailingList implements MessageHandler, ProblemListener { return setFlag(STATE_HIDE_RECEIVERS,hide); } - public boolean isAllowedSender(String senderEmail){ - if (senderEmail == null || senderEmail.isBlank()) return false; - try { - var user = User.load(senderEmail); - if (user == null) return this.isOpenForGuests(); - var member = ListMember.load(this,user); - if (member == null) return this.isOpenForGuests(); - if (member.isModerator()) return true; - if (member.isSubscriber()) return this.isOpenForSubscribers(); - } catch (SQLException e) { - LOG.warn("Laden des Nutzers zu {} fehlgeschlagen",senderEmail,e); - } - return this.isOpenForGuests(); - } /** * test, whether the current ML is subscribable by a given user * @param user @@ -344,8 +318,8 @@ public class MailingList implements MessageHandler, ProblemListener { return false; } - public Set members() throws SQLException { - return ListMember.of(this); + public Stream members() throws SQLException { + return ListMember.of(this).stream(); } public boolean membersMayBeListedBy(User user) { @@ -387,6 +361,10 @@ public class MailingList implements MessageHandler, ProblemListener { } + public Stream moderators() throws SQLException { + return members().filter(ListMember::isModerator); + } + public boolean modsMayEditMods(){ return hasState(STATE_MODS_CAN_EDIT_MODS); } @@ -413,27 +391,52 @@ public class MailingList implements MessageHandler, ProblemListener { public void onMessageReceived(Message message) throws MessagingException { LOG.info("Nachricht empfangen: {}",message.getFrom()); String subject = message.getSubject(); - if (subject.toLowerCase().contains("undelivered")){ - try { - var receivers = members().stream().filter(ListMember::isOwner).map(ListMember::user).map(User::email).toList(); - smtp.forward(email(), receivers, message, message.getSubject(), false,false,null); - } catch (SQLException e){ - LOG.error("Was not able to load members of {}; Non-Delivery notification dropped!",this.email(),e); - } - return; - } - Address from = message.getFrom()[0]; - if (from instanceof InternetAddress internetAddress){ - var senderEmail = ((InternetAddress) from).getAddress(); - if (!isAllowedSender(senderEmail)) { - retainMessage(message); - sentRetentionNotification(senderEmail); + try { + if (subject.toLowerCase().contains("undelivered")){ + forward(message,moderators()); return; } + + Address from = message.getFrom()[0]; + if (from instanceof InternetAddress internetAddress) { + var senderEmail = internetAddress.getAddress(); + + var user = User.load(senderEmail); + if (user == null) { // no subscription + if (this.isOpenForGuests()) { + forward(message,subscribers()); + } else { + retainMessage(message); + sentRetentionNotification(senderEmail); + + } + return; + } + + var member = ListMember.load(this, user); + if (member == null || member.isAwaiting()) { // no subscription + if (this.isOpenForGuests()) { + forward(message,subscribers()); + } else { + retainMessage(message); + sentRetentionNotification(senderEmail); + } + return; + } + + // at this point the member is at least a subscriber! + + if (member.isModerator() || this.isOpenForSubscribers()) { + forward(message,subscribers()); + } else { + forward(message,moderators()); + } + } + } catch (SQLException e){ + LOG.warn("Failed to process message '{}'",subject,e); } - if (hasState(STATE_PUBLIC_ARCHIVE)) storeMessage(message); - forward(message); + } public MailingList openForGuests(boolean open) throws SQLException { @@ -464,6 +467,10 @@ public class MailingList implements MessageHandler, ProblemListener { return list; } + public Stream owners() throws SQLException { + return members().filter(ListMember::isOwner); + } + public MailingList replyToList(boolean on) throws SQLException { return setFlag(STATE_REPLY_TO_LIST,on); } @@ -537,9 +544,7 @@ public class MailingList implements MessageHandler, ProblemListener { private void sentRetentionNotification(String senderEmail) { try { - var receivers = members() - .stream() - .filter(ListMember::isOwner) + var receivers = moderators() .map(ListMember::user) .map(User::email) .collect(Collectors.joining(", ")); @@ -620,6 +625,10 @@ public class MailingList implements MessageHandler, ProblemListener { } } + private Stream subscribers() throws SQLException { + return members().filter(ListMember::isSubscriber); + } + /** * Request list subscription for the given user. * Usually creates a ListMember entry with AWAITING_CONFIRMATION state is created and a confirmation request email is sent. diff --git a/src/main/java/de/srsoftware/widerhall/mail/SmtpClient.java b/src/main/java/de/srsoftware/widerhall/mail/SmtpClient.java index 0922005..1a7c3eb 100644 --- a/src/main/java/de/srsoftware/widerhall/mail/SmtpClient.java +++ b/src/main/java/de/srsoftware/widerhall/mail/SmtpClient.java @@ -37,15 +37,15 @@ public class SmtpClient { MimeMessage forward = new MimeMessage(session); var oldSender = message.getFrom()[0].toString(); if (newSender != null){ - var pos = subject.indexOf(" (from "); + var pos = subject.indexOf(" (von "); while (pos > 0){ var end = subject.indexOf(')',pos); if (end < pos) break; subject = (subject.substring(0,pos)+subject.substring(end+1)).trim(); - pos = subject.indexOf(" (from "); + pos = subject.indexOf(" (von "); } forward.setFrom(newSender); - forward.setSubject(subject+" (from "+oldSender+")"); + forward.setSubject(subject+" (von "+oldSender+")"); } else { forward.setFrom(oldSender); forward.setSubject(subject); @@ -57,7 +57,7 @@ public class SmtpClient { MimeMultipart multipart = new MimeMultipart(); if (forwardAsAttachment){ MimeBodyPart bodyPart = new MimeBodyPart(); - bodyPart.setText("Find the forwarded message in the attachment(s)!\n"); + bodyPart.setText("Die weitergeleitete Nachricht findest du im Anhang dieser E-Mail!\n"); multipart.addBodyPart(bodyPart); // create another body part to contain the message to be forwarded diff --git a/src/main/java/de/srsoftware/widerhall/web/Rest.java b/src/main/java/de/srsoftware/widerhall/web/Rest.java index 225e817..c9779bc 100644 --- a/src/main/java/de/srsoftware/widerhall/web/Rest.java +++ b/src/main/java/de/srsoftware/widerhall/web/Rest.java @@ -94,10 +94,15 @@ public class Rest extends HttpServlet { if (!allowed) return Map.of(ERROR,"Es ist dir nicht gestattet, diese Liste zu löschen!"); try { list.hide(true).enable(false).openForGuests(false).openForSubscribers(false); - for (ListMember member : list.members()) { // drop all list members except for owner - if (!member.isOwner()) member.unsubscribe(); - } - } catch (SQLException e) { + list.members().forEach(listMember -> { + try { + listMember.unsubscribe(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); + + } catch (Exception e) { LOG.debug("Disabling and hiding of {} failed",list.email(),e); } return Map.of(SUCCESS,t("Liste {} deaktiviert, Abonnement gesperrt, Liste de-publiziert. Mitglieder wurden entfernt.",list.email())); @@ -338,7 +343,6 @@ public class Rest extends HttpServlet { if (!list.membersMayBeListedBy(user)) Map.of(ERROR,t("Es ist dir nicht gestattet, die Mitglieder von '{}' aufzulisten",list.email())); try { var members = list.members() - .stream() .map(ListMember::safeMap) .toList(); return Map.of(MEMBERS,members,LIST,list.minimalMap());