@ -163,24 +163,22 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -163,24 +163,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 < ListMember > 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 ( "Failed to read list members of {} from database. Cannot forward message!" , 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 ) ;
}
@ -216,16 +214,6 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -216,16 +214,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() failded for {}" , email ( ) , e ) ;
}
return false ;
}
public boolean hasState ( int test ) {
return ( state & test ) > 0 ;
}
@ -238,20 +226,6 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -238,20 +226,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 ( "Failed to load User for {}" , senderEmail , e ) ;
}
return this . isOpenForGuests ( ) ;
}
/ * *
* test , whether the current ML is subscribable by a given user
* @param user
@ -343,8 +317,8 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -343,8 +317,8 @@ public class MailingList implements MessageHandler, ProblemListener {
return false ;
}
public Set < ListMember > members ( ) throws SQLException {
return ListMember . of ( this ) ;
public Stream < ListMember > members ( ) throws SQLException {
return ListMember . of ( this ) . stream ( ) ;
}
public boolean membersMayBeListedBy ( User user ) {
@ -386,6 +360,10 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -386,6 +360,10 @@ public class MailingList implements MessageHandler, ProblemListener {
}
public Stream < ListMember > moderators ( ) throws SQLException {
return members ( ) . filter ( ListMember : : isModerator ) ;
}
public boolean modsMayEditMods ( ) {
return hasState ( STATE_MODS_CAN_EDIT_MODS ) ;
}
@ -412,27 +390,52 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -412,27 +390,52 @@ public class MailingList implements MessageHandler, ProblemListener {
public void onMessageReceived ( Message message ) throws MessagingException {
LOG . info ( "Message received: {}" , 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 {
@ -463,6 +466,10 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -463,6 +466,10 @@ public class MailingList implements MessageHandler, ProblemListener {
return list ;
}
public Stream < ListMember > owners ( ) throws SQLException {
return members ( ) . filter ( ListMember : : isOwner ) ;
}
public MailingList replyToList ( boolean on ) throws SQLException {
return setFlag ( STATE_REPLY_TO_LIST , on ) ;
}
@ -536,9 +543,7 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -536,9 +543,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 ( ", " ) ) ;
@ -619,6 +624,10 @@ public class MailingList implements MessageHandler, ProblemListener {
@@ -619,6 +624,10 @@ public class MailingList implements MessageHandler, ProblemListener {
}
}
private Stream < ListMember > 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 .