package com.secretpal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.secretpal.components.person.SPGroupInvitationEmail; import com.secretpal.components.person.SPGroupInvitationTextEmail; import com.secretpal.components.person.SPResetPasswordEmail; import com.secretpal.components.person.SPResetPasswordTextEmail; import com.secretpal.model.SPGroup; import com.secretpal.model.SPMembership; import com.secretpal.model.SPPerson; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableArray; import er.extensions.appserver.ERXApplication; import er.extensions.eof.ERXEC; import er.extensions.eof.ERXEOControlUtilities; import er.javamail.ERMailDeliveryHTML; import er.javamail.ERMessage; public class SPUtilities { private static final Logger log = LoggerFactory.getLogger(SPUtilities.class); public static final String CONFIRMATION_CODE_KEY = "confirmationCode"; public static final String RESET_PASSWORD_CODE_KEY = "resetPasswordCode"; public static String confirmationUrl(SPMembership membership, WOContext context) { context.generateCompleteURLs(); String confirmationUrl = context.directActionURLForActionNamed("confirm", new NSDictionary<>(membership.confirmationCode(), SPUtilities.CONFIRMATION_CODE_KEY), true, false); context.generateRelativeURLs(); return confirmationUrl; } public static String resetPasswordUrl(SPPerson person, WOContext context) { context.generateCompleteURLs(); String resetPasswordUrl = context.directActionURLForActionNamed("resetPassword", new NSDictionary<>(person.resetPasswordCode(), SPUtilities.RESET_PASSWORD_CODE_KEY), true, false); context.generateRelativeURLs(); return resetPasswordUrl; } public static boolean sendEmailToPerson(String subject, WOComponent component, WOComponent plainTextComponent, SPPerson person, ERMessage.Delegate delegate, SPNoticeList errorNoticeList) { ERMailDeliveryHTML mail = new ERMailDeliveryHTML(); mail.setComponent(component); mail.setAlternativeComponent(plainTextComponent); mail.newMail(); boolean sentEmail = false; try { mail.setFromAddress("donotreply@secret-pal.com"); mail.setReplyToAddress("donotreply@secret-pal.com"); mail.setSubject(subject); mail.setToAddresses(new NSArray<>(person.emailAddress())); mail.setDelegate(delegate); mail.sendMail(); sentEmail = true; } catch (Exception e) { EOEditingContext editingContext = ERXEC.newEditingContext(); try { person.localInstanceIn(editingContext).setEmailDeliveryFailure(Boolean.TRUE); editingContext.saveChanges(); } finally { editingContext.unlock(); } editingContext.dispose(); log.error("Failed to send email to '{}'.", person.emailAddress(), e); errorNoticeList.addNotice("Failed to send email: " + e.getMessage()); } return sentEmail; } public static boolean sendResetPasswordEmail(SPPerson person, WOContext context, SPNoticeList errorNoticeList) { EOEditingContext editingContext = ERXEC.newEditingContext(); SPPerson localPerson = person.localInstanceIn(editingContext); localPerson.resetPassword(); editingContext.saveChanges(); WOContext contextClone = (WOContext) context.clone(); SPResetPasswordEmail resetPasswordEmail = ERXApplication.erxApplication().pageWithName(SPResetPasswordEmail.class, contextClone); resetPasswordEmail.setPerson(person); SPResetPasswordTextEmail resetPasswordTextEmail = ERXApplication.erxApplication().pageWithName(SPResetPasswordTextEmail.class, contextClone); resetPasswordTextEmail.setPerson(person); return SPUtilities.sendEmailToPerson("SecretPal Password Reset", resetPasswordEmail, resetPasswordTextEmail, person, new SPPersonEmailDelegate(person, errorNoticeList), errorNoticeList); } public static boolean sendInvitationEmail(SPMembership membership, WOContext context, SPNoticeList errorNoticeList) { EOEditingContext editingContext = membership.editingContext(); membership.resetConfirmation(); editingContext.saveChanges(); WOContext contextClone = (WOContext) context.clone(); SPGroupInvitationEmail validationEmail = ERXApplication.erxApplication().pageWithName(SPGroupInvitationEmail.class, contextClone); validationEmail.setMembership(membership); SPGroupInvitationTextEmail validationTextEmail = ERXApplication.erxApplication().pageWithName(SPGroupInvitationTextEmail.class, contextClone); validationTextEmail.setMembership(membership); return SPUtilities.sendEmailToPerson(membership.group().name() + " SecretPal Invitation", validationEmail, validationTextEmail, membership.person(), new SPPersonEmailDelegate(membership.person(), errorNoticeList), errorNoticeList); } public static void sendInvitationEmails(SPGroup group, String emailAddressesStr, WOContext context, SPNoticeList notificationNoticeList, SPNoticeList errorNoticeList, NSMutableArray<String> failedEmailAddresses) { if (emailAddressesStr != null && emailAddressesStr.length() != 0) { String[] emailAddresses = emailAddressesStr.split("[\\n;, ]"); int invitationsSent = 0; for (String emailAddress : emailAddresses) { String cleansedEmailAddress = SPUtilities.cleanseEmailAddress(emailAddress); if (cleansedEmailAddress.length() > 0) { EOEditingContext editingContext = ERXEC.newEditingContext(); SPMembership membership = group.localInstanceIn(editingContext).invite(cleansedEmailAddress); editingContext.saveChanges(); if (!membership.confirmed().booleanValue()) { boolean sentEmail = SPUtilities.sendInvitationEmail(membership, context, errorNoticeList); if (sentEmail) { invitationsSent++; } else { failedEmailAddresses.addObject(membership.person().emailAddress()); } } else { invitationsSent++; } editingContext.saveChanges(); } } if (invitationsSent == 0) { errorNoticeList.addNotice("Failed to send all invitations."); } else { notificationNoticeList.addNotice("Processing " + invitationsSent + " invitation(s) ..."); } } } public static String cleanseEmailAddress(String emailAddress) { return emailAddress.replaceAll("[()'\\[\\]<> ]", "").trim(); } public static class SPPersonEmailDelegate implements ERMessage.Delegate { private SPNoticeList _errorNoticeList; private Object _personGID; public SPPersonEmailDelegate(SPPerson person, SPNoticeList errorNoticeList) { _personGID = ERXEOControlUtilities.convertEOtoGID(person); _errorNoticeList = errorNoticeList; } public void invalidRecipients(ERMessage message, NSArray<String> invalidRecipientAddresses) { EOEditingContext editingContext = ERXEC.newEditingContext(); editingContext.lock(); try { SPPerson person = (SPPerson) ERXEOControlUtilities.convertGIDtoEO(editingContext, _personGID); _errorNoticeList.addNotice("Failed to send an email to '" + person.emailAddress() + "'."); } finally { editingContext.unlock(); editingContext.dispose(); } } public void deliverySucceeded(ERMessage message) { EOEditingContext editingContext = ERXEC.newEditingContext(); editingContext.lock(); try { SPPerson person = (SPPerson) ERXEOControlUtilities.convertGIDtoEO(editingContext, _personGID); person.setEmailDeliveryFailure(Boolean.FALSE); editingContext.saveChanges(); } finally { editingContext.unlock(); editingContext.dispose(); } } public void deliveryFailed(ERMessage message, Throwable failure) { EOEditingContext editingContext = ERXEC.newEditingContext(); editingContext.lock(); try { SPPerson person = (SPPerson) ERXEOControlUtilities.convertGIDtoEO(editingContext, _personGID); _errorNoticeList.addNotice("Failed to send an email to '" + person.emailAddress() + "'."); person.setEmailDeliveryFailure(Boolean.TRUE); editingContext.saveChanges(); } finally { editingContext.unlock(); editingContext.dispose(); } log.error("Failed to send email.", failure); } } }