diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/dao/ProfileDao.java b/orcid-persistence/src/main/java/org/orcid/persistence/dao/ProfileDao.java index 4a9626f4148..cbd04f1c121 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/dao/ProfileDao.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/dao/ProfileDao.java @@ -2,6 +2,7 @@ import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.List; import org.apache.commons.lang3.tuple.Pair; @@ -78,7 +79,7 @@ public interface ProfileDao extends GenericDao { public List> findEmailsUnverfiedDays(int daysUnverified, int maxResults); - public List> findEmailsUnverifiedDaysAndEventType(int daysUnverified, int maxResults, List eventTypes); + public HashMap> findEmailsUnverifiedDaysByEventType(int daysUnverified, int daysTooOld); String retrieveOrcidType(String orcid); diff --git a/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/ProfileDaoImpl.java b/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/ProfileDaoImpl.java index 2d97a19c212..58ea8004a5e 100644 --- a/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/ProfileDaoImpl.java +++ b/orcid-persistence/src/main/java/org/orcid/persistence/dao/impl/ProfileDaoImpl.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -22,11 +23,14 @@ import org.orcid.persistence.jpa.entities.ProfileEntity; import org.orcid.persistence.jpa.entities.ProfileEventEntity; import org.orcid.persistence.jpa.entities.ProfileEventType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; public class ProfileDaoImpl extends GenericDaoImpl implements ProfileDao { + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileDaoImpl.class); private static final String PRIVATE_VISIBILITY = "PRIVATE"; @@ -156,34 +160,34 @@ public List> findEmailsUnverfiedDays(int daysUnverified, int }); return results; } - + @SuppressWarnings("unchecked") @Override - public List> findEmailsUnverifiedDaysAndEventType(int daysUnverified, int maxResults, List eventTypes) { - List stringList = eventTypes.stream().map(Optional::ofNullable) //Stream> - .map(opt -> opt.orElse(null)) - .map(Objects::toString) - .map(opt -> "'"+opt+"'") - .collect(Collectors.toList()); - - String eventsTypeStr = StringUtils.collectionToCommaDelimitedString(stringList); - StringBuilder queryString = new StringBuilder("SELECT e.email, e.date_created FROM email e "); + public HashMap> findEmailsUnverifiedDaysByEventType(int daysUnverified, int daysTooOld) { + StringBuilder queryString = new StringBuilder("SELECT e.email, e.date_created, ev.email_event_type FROM email e "); queryString.append("LEFT JOIN email_event ev ON e.email = ev.email "); queryString.append("JOIN profile p on p.orcid = e.orcid and p.claimed = true "); queryString.append("AND p.deprecated_date is null AND p.profile_deactivation_date is null AND p.account_expiry is null "); - queryString.append("where (ev.email IS NULL or email_event_type NOT IN ("+ eventsTypeStr+"))" + "and e.is_verified = false "); - queryString.append("and e.date_created < (now() - CAST('").append(daysUnverified).append("' AS INTERVAL DAY)) "); + queryString.append("where ev.email IS NOT NULL and e.date_created between (now() - CAST('").append(daysTooOld).append("' AS INTERVAL DAY)) and (now() - CAST('") + .append(daysUnverified).append("' AS INTERVAL DAY)) "); queryString.append("and (e.source_id = e.orcid OR e.source_id is null)"); - queryString.append(" GROUP BY e.email, e.date_created, e.last_modified"); + queryString.append(" GROUP BY e.email, e.date_created, e.last_modified, ev.email_event_type"); queryString.append(" ORDER BY e.last_modified"); Query query = entityManager.createNativeQuery(queryString.toString()); - query.setMaxResults(maxResults); + LOGGER.debug("Unverified Emails Query by Event Type " + query.toString()); List dbInfo = query.getResultList(); - List> results = new ArrayList>(); + HashMap> results = new HashMap>(); + dbInfo.stream().forEach(element -> { - Pair pair = Pair.of((String) element[0], (Date) element[1]); - results.add(pair); + String email = (String) element[0]; + HashMap evMap = new HashMap(); + if (results.containsKey(email)) { + evMap = results.get(email); + evMap.put((String) element[2], (Date) element[1]); + } + results.put(email, evMap); }); + return results; } @@ -820,7 +824,7 @@ public void startSigninLock(String orcid) { query.executeUpdate(); return; } - + @Override @Transactional public void resetSigninLock(String orcid) { @@ -844,7 +848,7 @@ public void updateSigninLock(String orcid, Integer count) { query.executeUpdate(); return; } - + public boolean haveMemberPushedWorksOrAffiliationsToRecord(String orcid, String clientId) { try { String queryString = "select p.orcid from profile p where p.orcid = :orcid and ( exists (select 1 from work w where w.orcid = p.orcid and w.client_source_id = :clientId) or exists (select 1 from org_affiliation_relation o where o.orcid = p.orcid and o.client_source_id = :clientId));"; @@ -852,10 +856,10 @@ public boolean haveMemberPushedWorksOrAffiliationsToRecord(String orcid, String query.setParameter("orcid", orcid); query.setParameter("clientId", clientId); String result = (String) query.getSingleResult(); - if(orcid.equals(result)) { + if (orcid.equals(result)) { return true; - } - } catch(NoResultException nre) { + } + } catch (NoResultException nre) { return false; } return false; diff --git a/orcid-scheduler-web/src/main/java/org/orcid/scheduler/email/cli/manager/EmailMessageSenderImpl.java b/orcid-scheduler-web/src/main/java/org/orcid/scheduler/email/cli/manager/EmailMessageSenderImpl.java index 526e7812c7d..05cbbdd56f9 100644 --- a/orcid-scheduler-web/src/main/java/org/orcid/scheduler/email/cli/manager/EmailMessageSenderImpl.java +++ b/orcid-scheduler-web/src/main/java/org/orcid/scheduler/email/cli/manager/EmailMessageSenderImpl.java @@ -17,6 +17,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Resource; import javax.xml.datatype.XMLGregorianCalendar; @@ -78,17 +79,17 @@ public class EmailMessageSenderImpl implements EmailMessageSender { private static final Logger LOGGER = LoggerFactory.getLogger(EmailMessageSenderImpl.class); - + private final Integer MAX_RETRY_COUNT; - + ExecutorService pool; - + private int verifyReminderAfterTwoDays = 2; - + private int verifyReminderAfterSevenDays = 7; - + private int verifyReminderAfterTwentyEightDays = 28; - + @Resource private NotificationDao notificationDao; @@ -103,7 +104,7 @@ public class EmailMessageSenderImpl implements EmailMessageSender { @Resource private EmailDao emailDao; - + @Resource private TransactionTemplate transactionTemplate; @@ -124,33 +125,33 @@ public class EmailMessageSenderImpl implements EmailMessageSender { @Resource private ProfileEntityCacheManager profileEntityCacheManager; - + @Resource(name = "emailManagerReadOnlyV3") private EmailManagerReadOnly emailManagerReadOnly; - + @Resource private GenericDao emailEventDao; - + @Resource private ProfileDao profileDaoReadOnly; - + @Resource(name = "recordNameManagerV3") private RecordNameManager recordNameManagerV3; - + @Resource private VerifyEmailUtils verifyEmailUtils; - + @Value("${org.notifications.service_announcements.batchSize:60000}") private Integer batchSize; - + @Value("${org.notifications.max_elements_to_show:20}") - private Integer maxNotificationsToShowPerClient; - + private Integer maxNotificationsToShowPerClient; + @Value("${org.orcid.core.email.verify.tooOld:45}") - private int emailTooOld; - - private int emailTooOldLegacy = 15; - + private int emailTooOld; + + private int emailTooOldLegacy = 15; + public EmailMessageSenderImpl(@Value("${org.notifications.service_announcements.maxThreads:8}") Integer maxThreads, @Value("${org.notifications.service_announcements.maxRetry:3}") Integer maxRetry) { if (maxThreads == null || maxThreads > 64 || maxThreads < 1) { @@ -161,7 +162,7 @@ public EmailMessageSenderImpl(@Value("${org.notifications.service_announcements. MAX_RETRY_COUNT = maxRetry; } - + @Override public EmailMessage createDigest(String orcid, Collection notifications) { ProfileEntity record = profileEntityCacheManager.retrieve(orcid); @@ -171,7 +172,7 @@ public EmailMessage createDigest(String orcid, Collection notifica String bodyHtmlDelegate = null; String bodyHtmlDelegateRecipient = null; String bodyHtmlAdminDelegate = null; - + Set memberIds = new HashSet<>(); DigestEmail digestEmail = new DigestEmail(); @@ -227,19 +228,21 @@ public EmailMessage createDigest(String orcid, Collection notifica } } } - + List sortedClientIds = updatesByClient.keySet().stream().sorted().collect(Collectors.toList()); List sortedClientUpdates = new ArrayList(); - sortedClientIds.stream().forEach(s -> {sortedClientUpdates.add(updatesByClient.get(s));}); + sortedClientIds.stream().forEach(s -> { + sortedClientUpdates.add(updatesByClient.get(s)); + }); String emailName = recordNameManagerV3.deriveEmailFriendlyName(record.getId()); String subject = messages.getMessage("email.subject.digest", new String[] { emailName }, locale); Map params = new HashMap<>(); params.put("locale", locale); params.put("messages", messages); - params.put("messageArgs", new Object[0]); + params.put("messageArgs", new Object[0]); params.put("emailName", emailName); - params.put("digestEmail", digestEmail); + params.put("digestEmail", digestEmail); params.put("orcidMessageCount", orcidMessageCount); params.put("baseUri", orcidUrlManager.getBaseUrl()); params.put("subject", subject); @@ -262,17 +265,17 @@ public EmailMessage createDigest(String orcid, Collection notifica emailMessage.setBodyHtml(bodyHtml); return emailMessage; } - + private Locale getUserLocaleFromProfileEntity(ProfileEntity profile) { String locale = profile.getLocale(); if (locale != null) { AvailableLocales loc = AvailableLocales.valueOf(locale); return LocaleUtils.toLocale(loc.value()); } - + return LocaleUtils.toLocale("en"); } - + private String encryptAndEncodePutCode(Long putCode) { String encryptedPutCode = encryptionManager.encryptForExternalUse(String.valueOf(putCode)); try { @@ -285,26 +288,26 @@ private String encryptAndEncodePutCode(Long putCode) { @Override public void sendEmailMessages() { List orcidsWithUnsentNotifications = new ArrayList(); - orcidsWithUnsentNotifications = notificationDaoReadOnly.findRecordsWithUnsentNotifications(); - + orcidsWithUnsentNotifications = notificationDaoReadOnly.findRecordsWithUnsentNotifications(); + for (final Object[] element : orcidsWithUnsentNotifications) { - String orcid = (String) element[0]; + String orcid = (String) element[0]; try { Float emailFrequencyDays = null; Date recordActiveDate = null; recordActiveDate = (Date) element[1]; - + List notifications = notificationManager.findNotificationsToSend(orcid, emailFrequencyDays, recordActiveDate); - + EmailEntity primaryEmail = emailDao.findPrimaryEmail(orcid); if (primaryEmail == null) { LOGGER.info("No primary email for orcid: " + orcid); return; } - - if(!notifications.isEmpty()) { + + if (!notifications.isEmpty()) { LOGGER.info("Found {} messages to send for orcid: {}", notifications.size(), orcid); - EmailMessage digestMessage = createDigest(orcid, notifications); + EmailMessage digestMessage = createDigest(orcid, notifications); digestMessage.setFrom(EmailConstants.DO_NOT_REPLY_NOTIFY_ORCID_ORG); digestMessage.setTo(primaryEmail.getEmail()); boolean successfullySent = mailGunManager.sendEmail(digestMessage.getFrom(), digestMessage.getTo(), digestMessage.getSubject(), @@ -350,11 +353,11 @@ public Boolean call() throws Exception { e.printStackTrace(); } } - + @Override public void sendTips(Integer customBatchSize, String fromAddress) { LOGGER.info("About to send Tips messages"); - + List serviceAnnouncementsOrTips = new ArrayList(); try { long startTime = System.currentTimeMillis(); @@ -381,11 +384,11 @@ public Boolean call() throws Exception { e.printStackTrace(); } } - + private void processServiceAnnouncementOrTipNotification(NotificationEntity n) { processServiceAnnouncementOrTipNotification(n, null); } - + private void processServiceAnnouncementOrTipNotification(NotificationEntity n, String fromAddress) { String orcid = n.getOrcid(); EmailEntity primaryEmail = emailDao.findPrimaryEmail(orcid); @@ -394,7 +397,7 @@ private void processServiceAnnouncementOrTipNotification(NotificationEntity n, S flagAsFailed(orcid, n); return; } - if(!primaryEmail.getVerified()) { + if (!primaryEmail.getVerified()) { LOGGER.info("Primary email not verified for: " + orcid); flagAsFailed(orcid, n); return; @@ -402,23 +405,21 @@ private void processServiceAnnouncementOrTipNotification(NotificationEntity n, S try { boolean successfullySent = false; String fromAddressParam = EmailConstants.DO_NOT_REPLY_NOTIFY_ORCID_ORG; - if(!PojoUtil.isEmpty(fromAddress)) { + if (!PojoUtil.isEmpty(fromAddress)) { fromAddressParam = fromAddress; } if (n instanceof NotificationServiceAnnouncementEntity) { NotificationServiceAnnouncementEntity nc = (NotificationServiceAnnouncementEntity) n; // They might be custom notifications to have the // html/text ready to be sent - successfullySent = mailGunManager.sendMarketingEmail(fromAddressParam, primaryEmail.getEmail(), nc.getSubject(), nc.getBodyText(), - nc.getBodyHtml()); + successfullySent = mailGunManager.sendMarketingEmail(fromAddressParam, primaryEmail.getEmail(), nc.getSubject(), nc.getBodyText(), nc.getBodyHtml()); } else if (n instanceof NotificationTipEntity) { NotificationTipEntity nc = (NotificationTipEntity) n; // They might be custom notifications to have the // html/text ready to be sent - successfullySent = mailGunManager.sendMarketingEmail(fromAddressParam, primaryEmail.getEmail(), nc.getSubject(), nc.getBodyText(), - nc.getBodyHtml()); + successfullySent = mailGunManager.sendMarketingEmail(fromAddressParam, primaryEmail.getEmail(), nc.getSubject(), nc.getBodyText(), nc.getBodyHtml()); } - + if (successfullySent) { flagAsSent(n.getId()); } else { @@ -428,58 +429,58 @@ private void processServiceAnnouncementOrTipNotification(NotificationEntity n, S LOGGER.warn("Problem sending service announcement message to user: " + orcid, e); } } - + private void flagAsSent(Long id) { - transactionTemplate.execute(new TransactionCallbackWithoutResult() { + transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { notificationDao.flagAsSent(Arrays.asList(id)); } - }); + }); } - + private void flagAsFailed(String orcid, NotificationEntity n) { - transactionTemplate.execute(new TransactionCallbackWithoutResult() { + transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { - if(n.getRetryCount() != null && n.getRetryCount() >= MAX_RETRY_COUNT) { + if (n.getRetryCount() != null && n.getRetryCount() >= MAX_RETRY_COUNT) { notificationDao.flagAsNonSendable(orcid, n.getId()); } else { - if(n.getRetryCount() == null) { + if (n.getRetryCount() == null) { notificationDao.updateRetryCount(orcid, n.getId(), 1L); } else { notificationDao.updateRetryCount(orcid, n.getId(), (n.getRetryCount() + 1)); } - } + } } - }); + }); } - + public class ClientUpdates { String clientId; String clientName; String clientDescription; Integer counter = 0; Locale userLocale; - - Map>> updates = new HashMap<>(); - + + Map>> updates = new HashMap<>(); + public void setClientId(String clientId) { this.clientId = clientId; } - + public void setClientName(String clientName) { this.clientName = clientName; } - + public void setClientDescription(String clientDescription) { this.clientDescription = clientDescription; } - + public void setUserLocale(Locale locale) { this.userLocale = locale; } - + public String getClientId() { return clientId; } @@ -495,11 +496,11 @@ public String getClientDescription() { public Locale getUserLocale() { return userLocale; } - + public Map>> getUpdates() { return updates; } - + public Integer getCounter() { return counter; } @@ -507,11 +508,11 @@ public Integer getCounter() { private String renderCreationDate(XMLGregorianCalendar createdDate) { String result = new String(); result += createdDate.getYear(); - result += "-" + (createdDate.getMonth() < 10 ? "0" + createdDate.getMonth() : createdDate.getMonth()); - result += "-" + (createdDate.getDay() < 10 ? "0" + createdDate.getDay() : createdDate.getDay()); + result += "-" + (createdDate.getMonth() < 10 ? "0" + createdDate.getMonth() : createdDate.getMonth()); + result += "-" + (createdDate.getDay() < 10 ? "0" + createdDate.getDay() : createdDate.getDay()); return result; - } - + } + public void addElement(XMLGregorianCalendar createdDate, Item item) { init(item.getItemType().name(), item.getActionType() == null ? null : item.getActionType().name()); String value = null; @@ -548,7 +549,7 @@ public void addElement(XMLGregorianCalendar createdDate, Item item) { counter += 1; } - } + } private void init(String itemType, String actionType) { if (!updates.containsKey(itemType)) { @@ -567,22 +568,22 @@ private String getHtmlBody(NotificationAdministrative notificationAdministrative int bodyTagClose = notificationAdministrative.getBodyHtml().indexOf(""); return notificationAdministrative.getBodyHtml().substring(bodyTag + 6, bodyTagClose); } - + @Override synchronized public void processUnverifiedEmails2Days() { - LOGGER.info("About to process unverIfied emails for 2 days reminder"); + LOGGER.info("About to process unverified emails for 2 days reminder"); List> elements = Collections.> emptyList(); do { elements = profileDaoReadOnly.findEmailsUnverfiedDays(verifyReminderAfterTwoDays, 100); LOGGER.info("Got batch of {} profiles with unverified emails for 2 days reminder", elements.size()); LocalDateTime now = LocalDateTime.now(); - //togglz here + // togglz here Date tooOld = now.minusDays(emailTooOldLegacy).toDate(); - if(Features.SEND_ALL_VERIFICATION_EMAILS.isActive()) { + if (Features.SEND_ALL_VERIFICATION_EMAILS.isActive()) { tooOld = now.minusDays(emailTooOld).toDate(); } for (Pair element : elements) { - if(element.getRight() == null || element.getRight().after(tooOld)) { + if (element.getRight() == null || element.getRight().after(tooOld)) { processUnverifiedEmails2DaysInTransaction(element.getLeft()); } else { // Mark is as too old to send the verification email @@ -591,51 +592,44 @@ synchronized public void processUnverifiedEmails2Days() { } } while (!elements.isEmpty()); } - - + synchronized public void processUnverifiedEmails7Days() { - if(Features.SEND_ALL_VERIFICATION_EMAILS.isActive()) { - LOGGER.info("About to process unverIfied emails for 7 days reminder"); - List> elements = Collections.> emptyList(); - do { - elements = profileDaoReadOnly.findEmailsUnverfiedDays(verifyReminderAfterSevenDays, 100); - LOGGER.info("Got batch of {} profiles with unverified emails for 7 days reminder", elements.size()); - LocalDateTime now = LocalDateTime.now(); - Date tooOld = now.minusDays(emailTooOld).toDate(); - for (Pair element : elements) { - if(element.getRight() == null || element.getRight().after(tooOld)) { - processUnverifiedEmailsInTransaction(element.getLeft(), EmailEventType.VERIFY_EMAIL_7_DAYS_SENT, EmailEventType.VERIFY_EMAIL_7_DAYS_SENT_SKIPPED); - } else { - // Mark is as too old to send the verification email - markUnverifiedEmailAsTooOld(element.getLeft()); + if (Features.SEND_ALL_VERIFICATION_EMAILS.isActive()) { + LOGGER.info("About to process unverified emails for 7 days reminder"); + HashMap> elements = new HashMap>(); + elements = profileDaoReadOnly.findEmailsUnverifiedDaysByEventType(verifyReminderAfterSevenDays, emailTooOld); + LOGGER.info("Got {} profiles with unverified emails for 7 days reminder", elements.size()); + HashMap evMap; + for (String element : elements.keySet()) { + evMap = elements.get(element); + if (!evMap.containsKey(EmailEventType.VERIFY_EMAIL_7_DAYS_SENT.name()) && !evMap.containsKey(EmailEventType.VERIFY_EMAIL_7_DAYS_SENT_SKIPPED.name()) + && !evMap.containsKey(EmailEventType.VERIFY_EMAIL_TOO_OLD.name())) { + processUnverifiedEmailsInTransaction(element, EmailEventType.VERIFY_EMAIL_7_DAYS_SENT, EmailEventType.VERIFY_EMAIL_7_DAYS_SENT_SKIPPED); } } - } while (!elements.isEmpty()); + } + } - - + synchronized public void processUnverifiedEmails28Days() { - if(Features.SEND_ALL_VERIFICATION_EMAILS.isActive()) { - LOGGER.info("About to process unverIfied emails for 28 days reminder"); - List> elements = Collections.> emptyList(); - do { - elements = profileDaoReadOnly.findEmailsUnverfiedDays(verifyReminderAfterTwentyEightDays, 100); - LOGGER.info("Got batch of {} profiles with unverified emails for 28 days reminder", elements.size()); - LocalDateTime now = LocalDateTime.now(); - Date tooOld = now.minusDays(emailTooOld).toDate(); - for (Pair element : elements) { - if(element.getRight() == null || element.getRight().after(tooOld)) { - processUnverifiedEmailsInTransaction(element.getLeft(),EmailEventType.VERIFY_EMAIL_28_DAYS_SENT, EmailEventType.VERIFY_EMAIL_28_DAYS_SENT_SKIPPED); - } else { - // Mark is as too old to send the verification email - markUnverifiedEmailAsTooOld(element.getLeft()); + if (Features.SEND_ALL_VERIFICATION_EMAILS.isActive()) { + LOGGER.info("About to process unverified emails for 28 days reminder"); + HashMap> elements = new HashMap>(); + + elements = profileDaoReadOnly.findEmailsUnverifiedDaysByEventType(verifyReminderAfterTwentyEightDays, emailTooOld); + LOGGER.info("Got {} profiles with unverified emails for 28 days reminder", elements.size()); + HashMap evMap; + for (String element : elements.keySet()) { + evMap = elements.get(element); + if (!evMap.containsKey(EmailEventType.VERIFY_EMAIL_28_DAYS_SENT.name()) && !evMap.containsKey(EmailEventType.VERIFY_EMAIL_28_DAYS_SENT_SKIPPED.name()) + && !evMap.containsKey(EmailEventType.VERIFY_EMAIL_TOO_OLD.name())) { + processUnverifiedEmailsInTransaction(element, EmailEventType.VERIFY_EMAIL_28_DAYS_SENT, EmailEventType.VERIFY_EMAIL_28_DAYS_SENT_SKIPPED); } } - } while (!elements.isEmpty()); } } - + private void processUnverifiedEmailsInTransaction(final String email, EmailEventType eventSent, EmailEventType eventSkipped) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override @@ -654,7 +648,7 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { } }); } - + private void processUnverifiedEmails2DaysInTransaction(final String email) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override @@ -673,18 +667,18 @@ protected void doInTransactionWithoutResult(TransactionStatus status) { } }); } - + private void markUnverifiedEmailAsTooOld(final String email) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override @Transactional - protected void doInTransactionWithoutResult(TransactionStatus status) { + protected void doInTransactionWithoutResult(TransactionStatus status) { emailEventDao.persist(new EmailEventEntity(email, EmailEventType.VERIFY_EMAIL_TOO_OLD)); emailEventDao.flush(); } }); } - + private void sendVerificationReminderEmail(String userOrcid, String email) { ProfileEntity profile = profileEntityCacheManager.retrieve(userOrcid); Locale locale = getUserLocaleFromProfileEntity(profile); @@ -698,5 +692,5 @@ private void sendVerificationReminderEmail(String userOrcid, String email) { String body = templateManager.processTemplate("verification_email_v2.ftl", templateParams); String htmlBody = templateManager.processTemplate("verification_email_html_v2.ftl", templateParams); mailGunManager.sendEmail(EmailConstants.DO_NOT_REPLY_VERIFY_ORCID_ORG, email, subject, body, htmlBody); - } + } }