@ -3,6 +3,7 @@ package org.gcube.portal.socialmail;
import java.security.GeneralSecurityException ;
import java.util.ArrayList ;
import java.util.Date ;
import java.util.List ;
import java.util.Properties ;
import java.util.UUID ;
@ -24,7 +25,16 @@ import org.gcube.application.framework.core.session.SessionManager;
import org.gcube.application.framework.core.util.GenderType ;
import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager ;
import org.gcube.applicationsupportlayer.social.NotificationsManager ;
import org.gcube.applicationsupportlayer.social.mailing.AppType ;
import org.gcube.applicationsupportlayer.social.mailing.EmailPlugin ;
import org.gcube.common.homelibrary.home.HomeLibrary ;
import org.gcube.common.homelibrary.home.exceptions.HomeNotFoundException ;
import org.gcube.common.homelibrary.home.exceptions.InternalErrorException ;
import org.gcube.common.homelibrary.home.workspace.Workspace ;
import org.gcube.common.homelibrary.home.workspace.exceptions.ItemNotFoundException ;
import org.gcube.common.homelibrary.home.workspace.exceptions.WorkspaceFolderNotFoundException ;
import org.gcube.common.homelibrary.home.workspace.sharing.WorkspaceMessage ;
import org.gcube.common.homelibrary.home.workspace.sharing.WorkspaceMessageManager ;
import org.gcube.common.portal.PortalContext ;
import org.gcube.portal.custom.communitymanager.OrganizationsUtil ;
import org.gcube.portal.databook.server.DatabookStore ;
@ -35,8 +45,10 @@ import org.gcube.portal.databook.shared.ex.ColumnNameNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException ;
import org.gcube.portal.databook.shared.ex.FeedTypeNotFoundException ;
import org.gcube.portal.databook.shared.ex.PrivacyLevelTypeNotFoundException ;
import org.gcube.portal.notifications.bean.GenericItemBean ;
import org.gcube.portal.notifications.thread.CommentNotificationsThread ;
import org.gcube.portal.notifications.thread.LikeNotificationsThread ;
import org.gcube.portal.notifications.thread.MessageNotificationsThread ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
@ -154,38 +166,26 @@ public class PeriodicTask implements Runnable {
String subject = message . getSubject ( ) ;
_log . info ( "Parsing email of " + message . getFrom ( ) [ 0 ] + " with subject: " + subject ) ;
if ( isValidReply ( message ) ) {
String feedId = extractFeedId ( message ) ;
String commentText = extractText ( portalName , feedId , message ) ;
_log . info ( "Extracted id: " + feedId + " text=" + commentText ) ;
String escapedCommentText = Utils . escapeHtmlAndTransformUrl ( commentText ) ;
String subAddressField = extractSubaddress ( message ) ;
Address [ ] froms = message . getFrom ( ) ;
String emailAddress = froms = = null ? null : ( ( InternetAddress ) froms [ 0 ] ) . getAddress ( ) ;
ASLSession fakeSession = getFakeASLSession ( emailAddress ) ;
if ( fakeSession ! = null ) {
if ( escapedCommentText . trim ( ) . compareTo ( "" ) = = 0 ) { //it is a favorite/subscription
_log . debug ( "Found favorite/subscription for feed with subject: " + subject ) ;
favoriteFeed ( feedId , fakeSession ) ;
}
else {
Comment comment = new Comment ( UUID . randomUUID ( ) . toString ( ) , fakeSession . getUsername ( ) ,
new Date ( ) , feedId , escapedCommentText , fakeSession . getUserFullName ( ) , fakeSession . getUserAvatarId ( ) ) ;
_log . debug ( "The EscapedCommentText =>" + escapedCommentText ) ;
boolean commentCommitResult = false ;
try {
if ( socialStore . addComment ( comment ) )
commentCommitResult = true ;
} catch ( FeedIDNotFoundException e ) {
_log . error ( "Related post not found for this comment " + e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
}
if ( commentCommitResult ) { //the notifications should start
notifyUsersInvolved ( comment , escapedCommentText , feedId , fakeSession ) ;
}
if ( subAddressField . endsWith ( AppType . POST . toString ( ) ) | | subAddressField . endsWith ( AppType . POST . toString ( ) . toLowerCase ( ) ) ) { //it is a post, a comment on a post or a mention
_log . debug ( "Looks like a post, a comment on a post or a mention to me" ) ;
String feedId = extractIdentifier ( subAddressField ) ;
handlePostReply ( portalName , feedId , message , fakeSession ) ;
}
else if ( subAddressField . endsWith ( AppType . MSG . toString ( ) ) | | subAddressField . endsWith ( AppType . MSG . toString ( ) . toLowerCase ( ) ) ) { //it is a message
_log . debug ( "Looks like a message reply to me" ) ;
String messageId = extractIdentifier ( subAddressField ) ;
handleMessageReply ( portalName , messageId , message , fakeSession ) ;
} else {
_log . warn ( "cannot identify the type of this email reply from " + message . getFrom ( ) [ 0 ] + " with subject: " + subject ) ;
}
} else {
}
else {
_log . warn ( "User Not Recognized, going to discard Message from emailAddress = " + emailAddress ) ;
}
}
@ -209,6 +209,125 @@ public class PeriodicTask implements Runnable {
e . printStackTrace ( ) ;
}
}
/ * *
* this method manages the replies coming from message notifications
* @param portalName
* @param messageId the message identifier in the System managing the messages ( currently in the Home Library )
* @param message the javax mail Message instance
* @param fakeSession
* @throws Exception
* /
private void handleMessageReply ( String portalName , String messageId , Message message , ASLSession fakeSession ) {
String subject = "" ;
String messageText = "" ;
String escapedMessageText = "" ;
try {
subject = message . getSubject ( ) ;
messageText = extractText ( portalName , messageId , message ) ;
escapedMessageText = Utils . escapeHtmlAndTransformUrl ( messageText ) ;
} catch ( Exception e1 ) {
e1 . printStackTrace ( ) ;
}
_log . debug ( "Found message reply, subject: " + subject , " body: " + messageText ) ;
String newMessageId = null ;
Workspace workspace ;
List < String > recipientIds = null ;
try {
workspace = getWorkspace ( fakeSession ) ;
WorkspaceMessageManager messageManager = workspace . getWorkspaceMessageManager ( ) ;
WorkspaceMessage theMessage = messageManager . getReceivedMessage ( messageId ) ;
recipientIds = theMessage . getAddresses ( ) ;
//add the sender and remove the person who is replying from the recipients
String sender = theMessage . getSender ( ) . getPortalLogin ( ) ;
recipientIds . add ( sender ) ;
recipientIds . remove ( fakeSession . getUsername ( ) ) ;
_log . debug ( "Message Recipients:" ) ;
for ( String rec : recipientIds ) {
_log . debug ( rec ) ;
}
_log . debug ( "Trying to send message with subject: " + subject , " to: " + recipientIds . toString ( ) ) ;
newMessageId = messageManager . sendMessageToPortalLogins ( subject , messageText , new ArrayList < String > ( ) , recipientIds ) ;
} catch ( WorkspaceFolderNotFoundException | InternalErrorException | HomeNotFoundException | ItemNotFoundException e ) {
e . printStackTrace ( ) ;
}
_log . debug ( "Message with subject: " + subject , " hase been sent, returned id: " + newMessageId ) ;
if ( newMessageId ! = null ) {
_log . debug ( "Sending message notifications ... " ) ;
List < GenericItemBean > recipients = getUsersbyUserId ( recipientIds ) ;
NotificationsManager nm = new ApplicationNotificationsManager ( fakeSession ) ;
Thread thread = new Thread ( new MessageNotificationsThread ( recipients , messageId , subject , escapedMessageText , nm ) ) ;
thread . start ( ) ;
} else {
_log . debug ( "Could not send message reply" ) ;
}
}
/ * *
* return the User instance given his id
* @param recipientIds
* @return
* /
private List < GenericItemBean > getUsersbyUserId ( List < String > recipientIds ) {
List < GenericItemBean > recipients = new ArrayList < GenericItemBean > ( ) ;
for ( String userid : recipientIds ) {
com . liferay . portal . model . User user ;
try {
user = UserLocalServiceUtil . getUserByScreenName ( OrganizationsUtil . getCompany ( ) . getCompanyId ( ) , userid ) ;
recipients . add ( new GenericItemBean ( "" + user . getUserId ( ) , user . getScreenName ( ) , user . getFullName ( ) , "" ) ) ;
} catch ( PortalException | SystemException e ) {
e . printStackTrace ( ) ;
}
}
return recipients ;
}
/ * *
* this method manages the replies coming from post notifications
* @param portalName
* @param feedId the identifier in the System managing the feeds
* @param message the javax mail Message instance
* @param fakeSession
* @throws Exception
* /
private void handlePostReply ( String portalName , String feedId , Message message , ASLSession fakeSession ) throws Exception {
String commentText = extractText ( portalName , feedId , message ) ;
_log . info ( "Extracted id: " + feedId + " text=" + commentText ) ;
String escapedCommentText = Utils . escapeHtmlAndTransformUrl ( commentText ) ;
String subject = message . getSubject ( ) ;
if ( escapedCommentText . trim ( ) . compareTo ( "" ) = = 0 ) { //it is a favorite/subscription
_log . debug ( "Found favorite/subscription for feed with subject: " + subject ) ;
favoriteFeed ( feedId , fakeSession ) ;
}
else {
Comment comment = new Comment ( UUID . randomUUID ( ) . toString ( ) , fakeSession . getUsername ( ) ,
new Date ( ) , feedId , escapedCommentText , fakeSession . getUserFullName ( ) , fakeSession . getUserAvatarId ( ) ) ;
_log . debug ( "The EscapedCommentText =>" + escapedCommentText ) ;
boolean commentCommitResult = false ;
try {
if ( socialStore . addComment ( comment ) )
commentCommitResult = true ;
} catch ( FeedIDNotFoundException e ) {
_log . error ( "Related post not found for this comment " + e . getMessage ( ) ) ;
e . printStackTrace ( ) ;
}
if ( commentCommitResult ) { //the notifications should start
notifyUsersInvolved ( comment , escapedCommentText , feedId , fakeSession ) ;
}
}
}
/ * *
* favorite the feed to subscribe to further comments
* @param feedId
@ -291,12 +410,12 @@ public class PeriodicTask implements Runnable {
return toReturn ;
}
/ * *
*
* extracts the sub - address ( the part after the + and before the @ ) from the email addressee
* @param message
* @return
* @return the sub - address without + and @
* @throws MessagingException
* /
private static String extract FeedId ( Message message ) throws MessagingException {
private static String extract Subaddress ( Message message ) throws MessagingException {
Address [ ] emails = message . getRecipients ( RecipientType . TO ) ;
String toParse = emails [ 0 ] . toString ( ) ;
int plus = toParse . indexOf ( '+' ) ;
@ -305,6 +424,20 @@ public class PeriodicTask implements Runnable {
return null ;
return toParse . substring ( plus + 1 , at ) ;
}
/ * *
* extracts the identifier ( the part before the $ ) from the Subaddress
* @param message
* @return the identifier
* @throws MessagingException
* /
private static String extractIdentifier ( String subAddress ) {
String id = subAddress ; //for backward compatibility
int at = subAddress . indexOf ( '$' ) ;
if ( at > - 1 )
id = subAddress . substring ( 0 , at ) ;
return id ;
}
/ * *
* the email is considered a valid reply if and only of it contains the EmailPlugin . WRITE_ABOVE_TO_REPLY text in the body
* @param message the message to check
@ -330,12 +463,16 @@ public class PeriodicTask implements Runnable {
}
String [ ] lines = toParse . split ( System . getProperty ( "line.separator" ) ) ;
for ( int i = 0 ; i < lines . length ; i + + ) {
if ( lines [ i ] . contains ( SEPARATOR ) )
if ( lines [ i ] . contains ( SEPARATOR ) ) {
_log . debug ( "Yes, it is a valid Reply" ) ;
return true ;
}
}
_log . debug ( "NOT a valid Reply" ) ;
return false ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
_log . error ( "Exceptiom returning NOT a valid Reply" ) ;
return false ;
}
}
@ -360,9 +497,11 @@ public class PeriodicTask implements Runnable {
toParse = part . getContent ( ) . toString ( ) ;
}
else {
_log . debug ( "Found g text/plain Message, getting text") ;
_log . debug ( "Found text/plain Message, getting text") ;
toParse = messageContent . toString ( ) ;
}
_log . debug ( "Got Message content = " + toParse ) ;
//cut the text below the WRITE_ABOVE_TO_REPLY text
String [ ] lines = toParse . split ( System . getProperty ( "line.separator" ) ) ;
int until = - 1 ;
@ -385,6 +524,22 @@ public class PeriodicTask implements Runnable {
if ( ! ( i = = until - 1 ) )
sb . append ( "\n" ) ;
}
return sb . toString ( ) . trim ( ) ;
String toReturn = sb . toString ( ) . trim ( ) ;
_log . debug ( "Returning text extracted = " + toReturn ) ;
return toReturn ;
}
/ * *
*
* @return the workspace instance
* @throws InternalErrorException
* @throws HomeNotFoundException
* @throws WorkspaceFolderNotFoundException
* /
private Workspace getWorkspace ( ASLSession session ) throws InternalErrorException , HomeNotFoundException , WorkspaceFolderNotFoundException {
Workspace workspace = HomeLibrary . getUserWorkspace ( session . getUsername ( ) ) ;
return workspace ;
}
}