@Override
  public EmailMessage createDigest(
      OrcidProfile orcidProfile, Collection<Notification> notifications, Locale locale) {
    int totalMessageCount = 0;
    int orcidMessageCount = 0;
    int addActivitiesMessageCount = 0;
    int amendedMessageCount = 0;
    int activityCount = 0;
    Set<String> memberIds = new HashSet<>();
    DigestEmail digestEmail = new DigestEmail();
    for (Notification notification : notifications) {
      digestEmail.addNotification(notification);
      totalMessageCount++;
      if (notification.getSource() == null) {
        orcidMessageCount++;
      } else {
        SourceClientId clientId = notification.getSource().getSourceClientId();
        if (clientId != null) {
          memberIds.add(clientId.getPath());
        }
      }
      if (notification instanceof NotificationPermission) {
        addActivitiesMessageCount++;
        NotificationPermission permissionNotification = (NotificationPermission) notification;
        activityCount += permissionNotification.getItems().getItems().size();
        String encryptedPutCode =
            encryptionManager.encryptForExternalUse(
                String.valueOf(permissionNotification.getPutCode()));
        try {
          permissionNotification.setEncryptedPutCode(
              Base64.encodeBase64URLSafeString(encryptedPutCode.getBytes("UTF-8")));
        } catch (UnsupportedEncodingException e) {
          throw new RuntimeException(
              "Problem base 64 encoding notification put code for notification id = "
                  + permissionNotification.getPutCode(),
              e);
        }
      }
      if (notification instanceof NotificationAmended) {
        amendedMessageCount++;
      }
    }
    String emailName = notificationManager.deriveEmailFriendlyName(orcidProfile);
    String subject =
        messages.getMessage(
            "email.subject.digest",
            new String[] {emailName, String.valueOf(totalMessageCount)},
            locale);
    Map<String, Object> params = new HashMap<>();
    params.put("locale", locale);
    params.put("messages", messages);
    params.put("messageArgs", new Object[0]);
    params.put("orcidProfile", orcidProfile);
    params.put("emailName", emailName);
    params.put("digestEmail", digestEmail);
    params.put(
        "frequency", orcidProfile.getOrcidInternal().getPreferences().getSendEmailFrequencyDays());
    params.put("totalMessageCount", String.valueOf(totalMessageCount));
    params.put("orcidMessageCount", orcidMessageCount);
    params.put("addActivitiesMessageCount", addActivitiesMessageCount);
    params.put("activityCount", activityCount);
    params.put("amendedMessageCount", amendedMessageCount);
    params.put("memberIdsCount", memberIds.size());
    params.put("baseUri", orcidUrlManager.getBaseUrl());
    params.put("subject", subject);
    String bodyText = templateManager.processTemplate("digest_email.ftl", params, locale);
    String bodyHtml = templateManager.processTemplate("digest_email_html.ftl", params, locale);
    EmailMessage emailMessage = new EmailMessage();

    emailMessage.setSubject(subject);
    emailMessage.setBodyText(bodyText);
    emailMessage.setBodyHtml(bodyHtml);
    return emailMessage;
  }
  @Override
  public void sendAmendEmail(
      OrcidProfile amendedProfile, AmendedSection amendedSection, Collection<Item> items) {
    String amenderOrcid = sourceManager.retrieveSourceOrcid();
    if (amenderOrcid == null) {
      LOGGER.debug("Not sending amend email, because amender is null: {}", amendedProfile);
      return;
    }
    if (amenderOrcid.equals(amendedProfile.getOrcidIdentifier().getPath())) {
      LOGGER.debug("Not sending amend email, because self edited: {}", amendedProfile);
      return;
    }
    SendChangeNotifications sendChangeNotifications =
        amendedProfile.getOrcidInternal().getPreferences().getSendChangeNotifications();
    if (sendChangeNotifications == null || !sendChangeNotifications.isValue()) {
      LOGGER.debug(
          "Not sending amend email, because option to send change notifications not set to true: {}",
          amendedProfile);
      return;
    }
    if (OrcidType.ADMIN.equals(profileDao.retrieveOrcidType(amenderOrcid))) {
      LOGGER.debug(
          "Not sending amend email, because modified by admin ({}): {}",
          amenderOrcid,
          amendedProfile);
      return;
    }

    String subject = getSubject("email.subject.amend", amendedProfile);

    // Create map of template params
    Map<String, Object> templateParams = new HashMap<String, Object>();
    templateParams.put("emailName", deriveEmailFriendlyName(amendedProfile));
    templateParams.put("orcid", amendedProfile.getOrcidIdentifier().getPath());
    templateParams.put("amenderName", extractAmenderName(amendedProfile, amenderOrcid));
    templateParams.put("baseUri", orcidUrlManager.getBaseUrl());
    templateParams.put("baseUriHttp", orcidUrlManager.getBaseUriHttp());
    templateParams.put("subject", subject);

    addMessageParams(templateParams, amendedProfile);

    // Generate body from template
    String body = templateManager.processTemplate("amend_email.ftl", templateParams);
    // Generate html from template
    String html = templateManager.processTemplate("amend_email_html.ftl", templateParams);

    boolean notificationsEnabled =
        profileDao.find(amendedProfile.getOrcidIdentifier().getPath()).getEnableNotifications();
    if (notificationsEnabled) {
      NotificationAmended notification = new NotificationAmended();
      notification.setNotificationType(NotificationType.AMENDED);
      notification.setAmendedSection(amendedSection);
      if (items != null) {
        notification.setItems(new Items(new ArrayList<>(items)));
      }
      createNotification(amendedProfile.getOrcidIdentifier().getPath(), notification);
    } else {
      String email =
          amendedProfile.getOrcidBio().getContactDetails().retrievePrimaryEmail().getValue();
      mailGunManager.sendEmail(AMEND_NOTIFY_ORCID_ORG, email, subject, body, html);
    }
  }