diff --git a/doc/release-notes/9185-contact-email-updates.md b/doc/release-notes/9185-contact-email-updates.md new file mode 100644 index 00000000000..3e03461a383 --- /dev/null +++ b/doc/release-notes/9185-contact-email-updates.md @@ -0,0 +1,12 @@ +## Contact Email Improvements + +Email sent from the contact forms to the contact(s) for a collection, dataset, or datafile can now optionally be cc'd to a support email address. The support email address can be changed from the default :SystemEmail address to a separate :SupportEmail address. When multiple contacts are listed, the system will now send one email to all contacts (with the optional cc if configured) instead of separate emails to each contact. Contact names with a comma that refer to Organizations will no longer have the name parts reversed in the email greeting. A new protected feedback API has been added. + +## Backward Incompatibilities + +When there are multiple contacts, the system will now send one email with all of the contacts in the To: header instead of sending one email to each contact (with no indication that others have been notified). + +## New JVM/MicroProfile Settings + +dataverse.mail.support-email - allows a separate email, distinct from the :SystemEmail to be used as the to address in emails from the contact form/ feedback api. +dataverse.mail.cc-support-on-contact-emails - include the support email address as a CC: entry when contact/feedback emails are sent to the contacts for a collection, dataset, or datafile. \ No newline at end of file diff --git a/doc/sphinx-guides/source/api/native-api.rst b/doc/sphinx-guides/source/api/native-api.rst index ab191b35add..072c39e7c2a 100644 --- a/doc/sphinx-guides/source/api/native-api.rst +++ b/doc/sphinx-guides/source/api/native-api.rst @@ -1618,6 +1618,8 @@ The fully expanded example above (without environment variables) looks like this The people who need to review the dataset (often curators or journal editors) can check their notifications periodically via API to see if any new datasets have been submitted for review and need their attention. See the :ref:`Notifications` section for details. Alternatively, these curators can simply check their email or notifications to know when datasets have been submitted (or resubmitted) for review. +.. _return-a-dataset: + Return a Dataset to Author ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1645,6 +1647,8 @@ The fully expanded example above (without environment variables) looks like this The review process can sometimes resemble a tennis match, with the authors submitting and resubmitting the dataset over and over until the curators are satisfied. Each time the curators send a "reason for return" via API, that reason is persisted into the database, stored at the dataset version level. +The :ref:`send-feedback` API call may be useful as a way to move the conversation to email. However, note that these emails go to contacts (versus authors) and there is no database record of the email contents. (:ref:`dataverse.mail.cc-support-on-contact-email` will send a copy of these emails to the support email address which would provide a record.) + Link a Dataset ~~~~~~~~~~~~~~ @@ -4497,3 +4501,29 @@ A curl example using allowing access to a dataset's metadata Please see :ref:`dataverse.api.signature-secret` for the configuration option to add a shared secret, enabling extra security. + +.. _send-feedback: + +Send Feedback To Contact(s) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This API call allows sending an email to the contacts for a collection, dataset, or datafile or to the support email address when no object is specified. +The call is protected by the normal /admin API protections (limited to localhost or requiring a separate key), but does not otherwise limit the sending of emails. +Administrators should be sure only trusted applications have access to avoid the potential for spam. + +The call is a POST with a JSON object as input with four keys: +- "targetId" - the id of the collection, dataset, or datafile. Persistent ids and collection aliases are not supported. (Optional) +- "subject" - the email subject line +- "body" - the email body to send +- "fromEmail" - the email to list in the reply-to field. (Dataverse always sends mail from the system email, but does it "on behalf of" and with a reply-to for the specified user.) + +A curl example using an ``ID`` + +.. code-block:: bash + + export SERVER_URL=http://localhost + export JSON='{"targetId":24, "subject":"Data Question", "body":"Please help me understand your data. Thank you!", "fromEmail":"dataverseSupport@mailinator.com"}' + + curl -X POST -H 'Content-Type:application/json' -d "$JSON" $SERVER_URL/api/admin/feedback + +Note that this call could be useful in coordinating with dataset authors (assuming they are also contacts) as an alternative/addition to the functionality provided by :ref:`return-a-dataset`. diff --git a/doc/sphinx-guides/source/installation/config.rst b/doc/sphinx-guides/source/installation/config.rst index 9828d5bb6e4..e5ef0db4cd6 100644 --- a/doc/sphinx-guides/source/installation/config.rst +++ b/doc/sphinx-guides/source/installation/config.rst @@ -2349,6 +2349,27 @@ See :ref:`discovery-sign-posting` for details. Can also be set via any `supported MicroProfile Config API source`_, e.g. the environment variable ``DATAVERSE_SIGNPOSTING_LEVEL1_ITEM_LIMIT``. +dataverse.mail.support-email +++++++++++++++++++++++++++++ + +This provides an email address distinct from the :ref:`systemEmail` that will be used as the email address for Contact Forms and Feedback API. This address is used as the To address when the Contact form is launched from the Support entry in the top navigation bar and, if configured via :ref:`dataverse.mail.cc-support-on-contact-email`, as a CC address when the form is launched from a Dataverse/Dataset Contact button. +This allows configuration of a no-reply email address for :ref:`systemEmail` while allowing feedback to go to/be cc'd to the support email address, which would normally accept replies. If not set, the :ref:`systemEmail` is used for the feedback API/contact form email. + +Note that only the email address is required, which you can supply without the ``<`` and ``>`` signs, but if you include the text, it's the way to customize the name of your support team, which appears in the "from" address in emails as well as in help text in the UI. If you don't include the text, the installation name (see :ref:`Branding Your Installation`) will appear in the "from" address. + +Can also be set via any `supported MicroProfile Config API source`_, e.g. the environment variable ``DATAVERSE_MAIL_SUPPORT_EMAIL``. + +.. _dataverse.mail.cc-support-on-contact-email: + +dataverse.mail.cc-support-on-contact-email +++++++++++++++++++++++++++++++++++++++++++ + +If this setting is true, the contact forms and feedback API will cc the system (:SupportEmail if set, :SystemEmail if not) when sending email to the collection, dataset, or datafile contacts. +A CC line is added to the contact form when this setting is true so that users are aware that the cc will occur. +The default is false. + +Can also be set via *MicroProfile Config API* sources, e.g. the environment variable ``DATAVERSE_MAIL_CC_SUPPORT_ON_CONTACT_EMAIL``. + .. _feature-flags: @@ -3812,3 +3833,4 @@ To use the current GDCC version directly: ``curl -X PUT -d 'https://gdcc.github.io/dvwebloader/src/dvwebloader.html' http://localhost:8080/api/admin/settings/:WebloaderUrl`` .. _supported MicroProfile Config API source: https://docs.payara.fish/community/docs/Technical%20Documentation/MicroProfile/Config/Overview.html + diff --git a/src/main/java/edu/harvard/iq/dataverse/MailServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/MailServiceBean.java index 0eef5203d91..2f8c2b6d6b4 100644 --- a/src/main/java/edu/harvard/iq/dataverse/MailServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/MailServiceBean.java @@ -81,37 +81,6 @@ public class MailServiceBean implements java.io.Serializable { public MailServiceBean() { } - public void sendMail(String host, String reply, String to, String subject, String messageText) { - Properties props = System.getProperties(); - props.put("mail.smtp.host", host); - Session session = Session.getDefaultInstance(props, null); - - try { - MimeMessage msg = new MimeMessage(session); - String[] recipientStrings = to.split(","); - InternetAddress[] recipients = new InternetAddress[recipientStrings.length]; - try { - InternetAddress fromAddress = getSystemAddress(); - setContactDelegation(reply, fromAddress); - msg.setFrom(fromAddress); - msg.setReplyTo(new Address[] {new InternetAddress(reply, charset)}); - for (int i = 0; i < recipients.length; i++) { - recipients[i] = new InternetAddress(recipientStrings[i], "", charset); - } - } catch (UnsupportedEncodingException ex) { - logger.severe(ex.getMessage()); - } - msg.setRecipients(Message.RecipientType.TO, recipients); - msg.setSubject(subject, charset); - msg.setText(messageText, charset); - Transport.send(msg, recipients); - } catch (AddressException ae) { - ae.printStackTrace(System.out); - } catch (MessagingException me) { - me.printStackTrace(System.out); - } - } - @Resource(name = "mail/notifyMailSession") private Session session; @@ -177,11 +146,7 @@ public InternetAddress getSystemAddress() { } //@Resource(name="mail/notifyMailSession") - public void sendMail(String from, String to, String subject, String messageText) { - sendMail(from, to, subject, messageText, new HashMap<>()); - } - - public void sendMail(String reply, String to, String subject, String messageText, Map extraHeaders) { + public void sendMail(String reply, String to, String cc, String subject, String messageText) { try { MimeMessage msg = new MimeMessage(session); // Always send from system address to avoid email being blocked @@ -202,18 +167,12 @@ public void sendMail(String reply, String to, String subject, String messageText msg.setSentDate(new Date()); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false)); + if (cc != null) { + msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc, false)); + } msg.setSubject(subject, charset); msg.setText(messageText, charset); - if (extraHeaders != null) { - for (Object key : extraHeaders.keySet()) { - String headerName = key.toString(); - String headerValue = extraHeaders.get(key).toString(); - - msg.addHeader(headerName, headerValue); - } - } - Transport.send(msg); } catch (AddressException ae) { ae.printStackTrace(System.out); diff --git a/src/main/java/edu/harvard/iq/dataverse/SendFeedbackDialog.java b/src/main/java/edu/harvard/iq/dataverse/SendFeedbackDialog.java index 363972b48c3..13a7cc51357 100644 --- a/src/main/java/edu/harvard/iq/dataverse/SendFeedbackDialog.java +++ b/src/main/java/edu/harvard/iq/dataverse/SendFeedbackDialog.java @@ -3,11 +3,12 @@ import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.feedback.Feedback; import edu.harvard.iq.dataverse.feedback.FeedbackUtil; +import edu.harvard.iq.dataverse.settings.JvmSettings; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.BundleUtil; import edu.harvard.iq.dataverse.util.MailUtil; import edu.harvard.iq.dataverse.util.SystemConfig; -import java.util.List; +import java.util.Optional; import java.util.Random; import java.util.logging.Logger; import javax.ejb.EJB; @@ -62,7 +63,7 @@ public class SendFeedbackDialog implements java.io.Serializable { * Either the dataverse or the dataset that the message is pertaining to. If * there is no recipient, this is a general feedback message. */ - private DvObject recipient; + private DvObject feedbackTarget; /** * :SystemEmail (the main support address for an installation). @@ -97,11 +98,11 @@ public void initUserInput(ActionEvent ae) { userMessage = ""; messageSubject = ""; Random random = new Random(); - op1 = new Long(random.nextInt(10)); - op2 = new Long(random.nextInt(10)); + op1 = Long.valueOf(random.nextInt(10)); + op2 = Long.valueOf(random.nextInt(10)); userSum = null; - String systemEmail = settingsService.getValueForKey(SettingsServiceBean.Key.SystemEmail); - systemAddress = MailUtil.parseSystemAddress(systemEmail); + String supportEmail = JvmSettings.SUPPORT_EMAIL.lookupOptional().orElse(settingsService.getValueForKey(SettingsServiceBean.Key.SystemEmail)); + systemAddress = MailUtil.parseSystemAddress(supportEmail); } public Long getOp1() { @@ -129,19 +130,27 @@ public void setUserSum(Long userSum) { } public String getMessageTo() { - if (recipient == null) { + if (feedbackTarget == null) { return BrandingUtil.getSupportTeamName(systemAddress); - } else if (recipient.isInstanceofDataverse()) { - return ((Dataverse) recipient).getDisplayName() + " " + BundleUtil.getStringFromBundle("contact.contact"); + } else if (feedbackTarget.isInstanceofDataverse()) { + return ((Dataverse) feedbackTarget).getDisplayName() + " " + BundleUtil.getStringFromBundle("contact.contact"); } else { return BundleUtil.getStringFromBundle("dataset") + " " + BundleUtil.getStringFromBundle("contact.contact"); } } + + public String getMessageCC() { + if (ccSupport()) { + return BrandingUtil.getSupportTeamName(systemAddress); + } + return null; + } + public String getFormHeader() { - if (recipient == null) { + if (feedbackTarget == null) { return BrandingUtil.getContactHeader(systemAddress); - } else if (recipient.isInstanceofDataverse()) { + } else if (feedbackTarget.isInstanceofDataverse()) { return BundleUtil.getStringFromBundle("contact.dataverse.header"); } else { return BundleUtil.getStringFromBundle("contact.dataset.header"); @@ -173,11 +182,11 @@ public String loggedInUserEmail() { } public DvObject getRecipient() { - return recipient; + return feedbackTarget; } public void setRecipient(DvObject recipient) { - this.recipient = recipient; + this.feedbackTarget = recipient; } public void validateUserSum(FacesContext context, UIComponent component, Object value) throws ValidatorException { @@ -200,16 +209,26 @@ public void validateUserEmail(FacesContext context, UIComponent component, Objec public String sendMessage() { String installationBrandName = BrandingUtil.getInstallationBrandName(); String supportTeamName = BrandingUtil.getSupportTeamName(systemAddress); - List feedbacks = FeedbackUtil.gatherFeedback(recipient, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, systemConfig.getDataverseSiteUrl(), installationBrandName, supportTeamName); - if (feedbacks.isEmpty()) { + + Feedback feedback = FeedbackUtil.gatherFeedback(feedbackTarget, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, systemConfig.getDataverseSiteUrl(), installationBrandName, supportTeamName, ccSupport()); + if (feedback==null) { logger.warning("No feedback has been sent!"); return null; } - for (Feedback feedback : feedbacks) { logger.fine("sending feedback: " + feedback); - mailService.sendMail(feedback.getFromEmail(), feedback.getToEmail(), feedback.getSubject(), feedback.getBody()); - } + mailService.sendMail(feedback.getFromEmail(), feedback.getToEmail(), feedback.getCcEmail(), feedback.getSubject(), feedback.getBody()); return null; } + + public boolean ccSupport() { + return ccSupport(feedbackTarget); + } + + public static boolean ccSupport(DvObject feedbackTarget) { + //Setting is enabled and this isn't already a direct message to support (no feedbackTarget) + Optional ccSupport = JvmSettings.CC_SUPPORT_ON_CONTACT_EMAIL.lookupOptional(Boolean.class); + + return feedbackTarget!=null && ccSupport.isPresent() &&ccSupport.get(); + } } diff --git a/src/main/java/edu/harvard/iq/dataverse/api/FeedbackApi.java b/src/main/java/edu/harvard/iq/dataverse/api/FeedbackApi.java index d9a94ee340b..53829cf09cc 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/FeedbackApi.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/FeedbackApi.java @@ -2,11 +2,15 @@ import edu.harvard.iq.dataverse.DataverseSession; import edu.harvard.iq.dataverse.DvObject; -import edu.harvard.iq.dataverse.DvObjectServiceBean; +import edu.harvard.iq.dataverse.MailServiceBean; +import edu.harvard.iq.dataverse.SendFeedbackDialog; import edu.harvard.iq.dataverse.branding.BrandingUtil; import edu.harvard.iq.dataverse.feedback.Feedback; import edu.harvard.iq.dataverse.feedback.FeedbackUtil; -import java.util.List; +import edu.harvard.iq.dataverse.settings.JvmSettings; +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import edu.harvard.iq.dataverse.util.MailUtil; + import javax.ejb.EJB; import javax.json.Json; import javax.json.JsonArrayBuilder; @@ -17,34 +21,47 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; @Path("admin/feedback") public class FeedbackApi extends AbstractApiBean { - @EJB - DvObjectServiceBean dvObjectSvc; - + @EJB MailServiceBean mailService; + + /** + * This method mimics the contact form and sends an email to the contacts of the + * specified Collection/Dataset/DataFile, optionally ccing the support email + * address, or to the support email address when there is no target object. + * + * !!!!! This should not be moved outside the /admin path unless/until some form + * of captcha or other spam-prevention mechanism is added. As is, it allows an + * unauthenticated user (with access to the /admin api path) to send email from + * anyone to any contacts in Dataverse. (It also does not do much to validate + * user input (e.g. to strip potentially malicious html, etc.)!!!! + **/ @POST public Response submitFeedback(JsonObject jsonObject) throws AddressException { - JsonNumber jsonNumber = jsonObject.getJsonNumber("id"); - DvObject recipient = null; + JsonNumber jsonNumber = jsonObject.getJsonNumber("targetId"); + DvObject feedbackTarget = null; if (jsonNumber != null) { - recipient = dvObjectSvc.findDvObject(jsonNumber.longValue()); + feedbackTarget = dvObjSvc.findDvObject(jsonNumber.longValue()); + if(feedbackTarget==null) { + return error(Status.BAD_REQUEST, "Feedback target object not found"); + } } DataverseSession dataverseSession = null; String userMessage = jsonObject.getString("body"); - String systemEmail = "support@librascholar.edu"; - InternetAddress systemAddress = new InternetAddress(systemEmail); + String systemEmail = JvmSettings.SUPPORT_EMAIL.lookupOptional().orElse(settingsSvc.getValueForKey(SettingsServiceBean.Key.SystemEmail)); + InternetAddress systemAddress = MailUtil.parseSystemAddress(systemEmail); String userEmail = jsonObject.getString("fromEmail"); String messageSubject = jsonObject.getString("subject"); String baseUrl = systemConfig.getDataverseSiteUrl(); String installationBrandName = BrandingUtil.getInstallationBrandName(); String supportTeamName = BrandingUtil.getSupportTeamName(systemAddress); JsonArrayBuilder jab = Json.createArrayBuilder(); - List feedbacks = FeedbackUtil.gatherFeedback(recipient, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - feedbacks.forEach((feedback) -> { - jab.add(feedback.toJsonObjectBuilder()); - }); + Feedback feedback = FeedbackUtil.gatherFeedback(feedbackTarget, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, SendFeedbackDialog.ccSupport(feedbackTarget)); + jab.add(feedback.toJsonObjectBuilder()); + mailService.sendMail(feedback.getFromEmail(), feedback.getToEmail(), feedback.getCcEmail(), feedback.getSubject(), feedback.getBody()); return ok(jab); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/feedback/Feedback.java b/src/main/java/edu/harvard/iq/dataverse/feedback/Feedback.java index e8677869496..c9acb491aa2 100644 --- a/src/main/java/edu/harvard/iq/dataverse/feedback/Feedback.java +++ b/src/main/java/edu/harvard/iq/dataverse/feedback/Feedback.java @@ -3,16 +3,20 @@ import javax.json.Json; import javax.json.JsonObjectBuilder; +import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder; + public class Feedback { private final String fromEmail; private final String toEmail; + private final String ccEmail; private final String subject; private final String body; - public Feedback(String fromEmail, String toEmail, String subject, String body) { + public Feedback(String fromEmail, String toEmail, String ccEmail, String subject, String body) { this.fromEmail = fromEmail; this.toEmail = toEmail; + this.ccEmail=ccEmail; this.subject = subject; this.body = body; } @@ -24,6 +28,10 @@ public String getFromEmail() { public String getToEmail() { return toEmail; } + + public String getCcEmail() { + return ccEmail; + } public String getSubject() { return subject; @@ -35,13 +43,14 @@ public String getBody() { @Override public String toString() { - return "Feedback{" + "fromEmail=" + fromEmail + ", toEmail=" + toEmail + ", subject=" + subject + ", body=" + body + '}'; + return "Feedback{" + "fromEmail=" + fromEmail + ", toEmail=" + toEmail + ", ccEmail=" + ccEmail + ", subject=" + subject + ", body=" + body + '}'; } public JsonObjectBuilder toJsonObjectBuilder() { - return Json.createObjectBuilder() + return new NullSafeJsonBuilder() .add("fromEmail", fromEmail) .add("toEmail", toEmail) + .add("ccEmail", ccEmail) .add("subject", subject) .add("body", body); } diff --git a/src/main/java/edu/harvard/iq/dataverse/feedback/FeedbackUtil.java b/src/main/java/edu/harvard/iq/dataverse/feedback/FeedbackUtil.java index 0e17d14f455..750a3923806 100644 --- a/src/main/java/edu/harvard/iq/dataverse/feedback/FeedbackUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/feedback/FeedbackUtil.java @@ -10,10 +10,14 @@ import edu.harvard.iq.dataverse.DataverseSession; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.util.BundleUtil; +import edu.harvard.iq.dataverse.util.PersonOrOrgUtil; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Logger; + +import javax.json.JsonObject; import javax.mail.internet.InternetAddress; public class FeedbackUtil { @@ -22,87 +26,118 @@ public class FeedbackUtil { private static final String NO_DATASET_CONTACT_INTRO = BundleUtil.getStringFromBundle("contact.context.dataset.noContact"); - // TODO: consider changing "recipient" into an object called something like FeedbackTarget - public static List gatherFeedback(DvObject recipient, DataverseSession dataverseSession, String messageSubject, String userMessage, InternetAddress systemAddress, String userEmail, String dataverseSiteUrl, String installationBrandName, String supportTeamName) { + public static Feedback gatherFeedback(DvObject feedbackTarget, DataverseSession dataverseSession, String messageSubject, String userMessage, InternetAddress systemAddress, String userEmail, String dataverseSiteUrl, String installationBrandName, String supportTeamName, boolean ccSupport) { String systemEmail = null; if (systemAddress != null) { systemEmail = systemAddress.getAddress(); } logger.fine("systemAddress: " + systemAddress); - List feedbacks = new ArrayList<>(); + Feedback feedback = null; if (isLoggedIn(dataverseSession)) { userEmail = loggedInUserEmail(dataverseSession); } - if (recipient != null) { + String contextIntro; + String contextEnding; + String contactEmails; + String ccEmails = ccSupport ? systemEmail : null; + + if (feedbackTarget != null) { messageSubject = BundleUtil.getStringFromBundle("contact.context.subject.dvobject", Arrays.asList(installationBrandName, messageSubject)); - if (recipient.isInstanceofDataverse()) { - Dataverse dataverse = (Dataverse) recipient; - String dataverseContextEnding = BundleUtil.getStringFromBundle("contact.context.dataverse.ending", Arrays.asList(supportTeamName, systemEmail, dataverseSiteUrl, dataverse.getAlias(), supportTeamName, systemEmail)); - List dataverseContacts = getDataverseContacts(dataverse); - for (DvObjectContact dataverseContact : dataverseContacts) { - String placeHolderIfDataverseContactsGetNames = ""; - String dataverseContextIntro = BundleUtil.getStringFromBundle("contact.context.dataverse.intro", Arrays.asList(placeHolderIfDataverseContactsGetNames, userEmail, installationBrandName, dataverse.getAlias())); - Feedback feedback = new Feedback(userEmail, dataverseContact.getEmail(), messageSubject, dataverseContextIntro + userMessage + dataverseContextEnding); - feedbacks.add(feedback); + + String contactGreeting; + + if (feedbackTarget.isInstanceofDataverse()) { + // Dataverse target + Dataverse dataverse = (Dataverse) feedbackTarget; + contextEnding = BundleUtil.getStringFromBundle("contact.context.dataverse.ending", Arrays.asList(supportTeamName, systemEmail, dataverseSiteUrl, dataverse.getAlias(), supportTeamName, systemEmail)); + List contacts = getDataverseContacts(dataverse); + List contactEmailList = new ArrayList(); + for (DvObjectContact contact : contacts) { + contactEmailList.add(contact.getEmail()); } - if (!feedbacks.isEmpty()) { - return feedbacks; + if (!contactEmailList.isEmpty()) { + contactEmails = String.join(",", contactEmailList); + // Dataverse contacts do not have a name, just email address + contactGreeting = ""; + contextIntro = BundleUtil.getStringFromBundle("contact.context.dataverse.intro", Arrays.asList(contactGreeting, userEmail, installationBrandName, dataverse.getAlias())); } else { - String dataverseContextIntroError = BundleUtil.getStringFromBundle("contact.context.dataverse.noContact"); - Feedback feedback = new Feedback(userEmail, systemEmail, messageSubject, dataverseContextIntroError + userMessage + dataverseContextEnding); - feedbacks.add(feedback); - return feedbacks; + // No contacts + contextIntro = BundleUtil.getStringFromBundle("contact.context.dataverse.noContact"); + contactEmails = systemEmail; + ccEmails = null; } - } else if (recipient.isInstanceofDataset()) { - Dataset dataset = (Dataset) recipient; + } else if (feedbackTarget.isInstanceofDataset()) { + // Dataset target + Dataset dataset = (Dataset) feedbackTarget; String datasetTitle = dataset.getLatestVersion().getTitle(); String datasetPid = dataset.getGlobalId().asString(); - String datasetContextEnding = BundleUtil.getStringFromBundle("contact.context.dataset.ending", Arrays.asList(supportTeamName, systemEmail, dataverseSiteUrl, dataset.getGlobalId().asString(), supportTeamName, systemEmail)); - List datasetContacts = getDatasetContacts(dataset); - for (DvObjectContact datasetContact : datasetContacts) { - String contactFullName = getGreeting(datasetContact); - String datasetContextIntro = BundleUtil.getStringFromBundle("contact.context.dataset.intro", Arrays.asList(contactFullName, userEmail, installationBrandName, datasetTitle, datasetPid)); - Feedback feedback = new Feedback(userEmail, datasetContact.getEmail(), messageSubject, datasetContextIntro + userMessage + datasetContextEnding); - feedbacks.add(feedback); + contextEnding = BundleUtil.getStringFromBundle("contact.context.dataset.ending", Arrays.asList(supportTeamName, systemEmail, dataverseSiteUrl, datasetPid, supportTeamName, systemEmail)); + List contacts = getDatasetContacts(dataset); + List contactEmailList = new ArrayList(); + List contactNameList = new ArrayList(); + + for (DvObjectContact contact : contacts) { + String name = getContactName(contact); + if (name != null) { + contactNameList.add(name); + } + contactEmailList.add(contact.getEmail()); } - if (!feedbacks.isEmpty()) { - return feedbacks; + if (!contactEmailList.isEmpty()) { + contactEmails = String.join(",", contactEmailList); + contactGreeting = getGreeting(contactNameList); + + contextIntro = BundleUtil.getStringFromBundle("contact.context.dataset.intro", Arrays.asList(contactGreeting, userEmail, installationBrandName, datasetTitle, datasetPid)); } else { - // TODO: Add more of an intro for the person receiving the system email in this "no dataset contact" scenario? - Feedback feedback = new Feedback(userEmail, systemEmail, messageSubject, NO_DATASET_CONTACT_INTRO + userMessage + datasetContextEnding); - feedbacks.add(feedback); - return feedbacks; + // No contacts + // TODO: Add more of an intro for the person receiving the system email in this + // "no dataset contact" scenario? + contextIntro = NO_DATASET_CONTACT_INTRO; + contactEmails = systemEmail; + ccEmails = null; } } else { - DataFile datafile = (DataFile) recipient; + // DataFile target + DataFile datafile = (DataFile) feedbackTarget; String datasetTitle = datafile.getOwner().getLatestVersion().getTitle(); String datasetPid = datafile.getOwner().getGlobalId().asString(); String filename = datafile.getFileMetadatas().get(0).getLabel(); - List datasetContacts = getDatasetContacts(datafile.getOwner()); - String fileContextEnding = BundleUtil.getStringFromBundle("contact.context.file.ending", Arrays.asList(supportTeamName, systemEmail, dataverseSiteUrl, datafile.getId().toString(), supportTeamName, systemEmail)); - for (DvObjectContact datasetContact : datasetContacts) { - String contactFullName = getGreeting(datasetContact); - String fileContextIntro = BundleUtil.getStringFromBundle("contact.context.file.intro", Arrays.asList(contactFullName, userEmail, installationBrandName, filename, datasetTitle, datasetPid)); - Feedback feedback = new Feedback(userEmail, datasetContact.getEmail(), messageSubject, fileContextIntro + userMessage + fileContextEnding); - feedbacks.add(feedback); + List contacts = getDatasetContacts(datafile.getOwner()); + contextEnding = BundleUtil.getStringFromBundle("contact.context.file.ending", Arrays.asList(supportTeamName, systemEmail, dataverseSiteUrl, datafile.getId().toString(), supportTeamName, systemEmail)); + List contactEmailList = new ArrayList(); + List contactNameList = new ArrayList(); + + for (DvObjectContact contact : contacts) { + String name = getContactName(contact); + if (name != null) { + contactNameList.add(name); + } + contactEmailList.add(contact.getEmail()); } - if (!feedbacks.isEmpty()) { - return feedbacks; + if (!contactEmailList.isEmpty()) { + contactEmails = String.join(",", contactEmailList); + contactGreeting = getGreeting(contactNameList); + + contextIntro = BundleUtil.getStringFromBundle("contact.context.file.intro", Arrays.asList(contactGreeting, userEmail, installationBrandName, filename, datasetTitle, datasetPid)); } else { - // TODO: Add more of an intro for the person receiving the system email in this "no dataset contact" scenario? - Feedback feedback = new Feedback(userEmail, systemEmail, messageSubject, NO_DATASET_CONTACT_INTRO + userMessage + fileContextEnding); - feedbacks.add(feedback); - return feedbacks; + // No contacts + // TODO: Add more of an intro for the person receiving the system email in this + // "no dataset contact" scenario? + contextIntro = NO_DATASET_CONTACT_INTRO; + contactEmails = systemEmail; + ccEmails = null; } } } else { + // No target messageSubject = BundleUtil.getStringFromBundle("contact.context.subject.support", Arrays.asList(installationBrandName, messageSubject)); - String noDvObjectContextIntro = BundleUtil.getStringFromBundle("contact.context.support.intro", Arrays.asList(supportTeamName, userEmail)); - String noDvObjectContextEnding = BundleUtil.getStringFromBundle("contact.context.support.ending", Arrays.asList("")); - Feedback feedback = new Feedback(userEmail, systemEmail, messageSubject, noDvObjectContextIntro + userMessage + noDvObjectContextEnding); - feedbacks.add(feedback); - return feedbacks; + contextIntro = BundleUtil.getStringFromBundle("contact.context.support.intro", Arrays.asList(supportTeamName, userEmail)); + contextEnding = BundleUtil.getStringFromBundle("contact.context.support.ending", Arrays.asList("")); + contactEmails = systemEmail; + ccEmails = null; } + feedback = new Feedback(userEmail, contactEmails, ccEmails, messageSubject, contextIntro + userMessage + contextEnding); + return feedback; } private static boolean isLoggedIn(DataverseSession dataverseSession) { @@ -156,30 +191,53 @@ private static List getDatasetContacts(Dataset dataset) { } /** - * When contacts are people we suggest that they be stored as "Simpson, - * Homer" so the idea of this method is that it returns "Homer Simpson", if - * it can. + * When contacts are people we suggest that they be stored as "Simpson, Homer" + * so the idea of this method is that it returns "Homer Simpson", if it can. * * Contacts don't necessarily have to be people, however. They can be - * organizations. We ran into similar trouble (but for authors) when - * implementing Schema.org JSON-LD support. See getJsonLd on DatasetVersion. - * Some day it might be nice to store whether an author or a contact is a - * person or an organization. + * organizations. This method uses the algorithm to detect whether an entry is a + * Person or Organization and relies on it to create a full name, i.e. removing + * the comma and reversion the order of names for a Person but not changing the + * string for an Organization. + */ + private static String getContactName(DvObjectContact dvObjectContact) { + String contactName = dvObjectContact.getName(); + String name = null; + if (contactName != null) { + JsonObject entity = PersonOrOrgUtil.getPersonOrOrganization(contactName, false, false); + if (entity.getBoolean("isPerson") && entity.containsKey("givenName") && entity.containsKey("familyName")) { + name = entity.getString("givenName") + " " + entity.getString("familyName"); + } else { + name = entity.getString("fullName"); + } + } + return name; + + } + + /** + * Concatenates names using commas and a final 'and' and creates the greeting + * string, e.g. "Hello Homer Simpson, Bart Simson, and Marge Simpson" */ - private static String getGreeting(DvObjectContact dvObjectContact) { - logger.fine("dvObjectContact: " + dvObjectContact); - try { - String name = dvObjectContact.getName(); - logger.fine("dvObjectContact name: " + name); - String lastFirstString = dvObjectContact.getName(); - String[] lastFirstParts = lastFirstString.split(","); - String last = lastFirstParts[0]; - String first = lastFirstParts[1]; - return BundleUtil.getStringFromBundle("contact.context.dataset.greeting.helloFirstLast", Arrays.asList(first.trim(), last.trim())); - } catch (Exception ex) { - logger.warning("problem in getGreeting: " + ex); + private static String getGreeting(List contactNameList) { + int size = contactNameList.size(); + String nameString; + String finalName = null; + // Treat the final name separately + switch (size) { + case 0: return BundleUtil.getStringFromBundle("contact.context.dataset.greeting.organization"); + case 1: + nameString = contactNameList.get(0); + break; + case 2: + nameString = contactNameList.get(0) + " and " + contactNameList.get(1); + break; + default: + finalName = contactNameList.remove(size - 1); + nameString = String.join(",", contactNameList) + ", and " + finalName; } + return BundleUtil.getStringFromBundle("contact.context.dataset.greeting.helloFirstLast", Arrays.asList(nameString)); } } diff --git a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java index 86130f5146e..49fcb7e64f6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java +++ b/src/main/java/edu/harvard/iq/dataverse/settings/JvmSettings.java @@ -106,6 +106,11 @@ public enum JvmSettings { HANDLENET_KEY_PATH(SCOPE_PID_HANDLENET_KEY, "path", "dataverse.handlenet.admcredfile"), HANDLENET_KEY_PASSPHRASE(SCOPE_PID_HANDLENET_KEY, "passphrase", "dataverse.handlenet.admprivphrase"), + // MAIL SETTINGS + SCOPE_MAIL(PREFIX, "mail"), + SUPPORT_EMAIL(SCOPE_MAIL, "support-email"), + CC_SUPPORT_ON_CONTACT_EMAIL(SCOPE_MAIL, "cc-support-on-contact-email"), + ; private static final String SCOPE_SEPARATOR = "."; diff --git a/src/main/java/propertyFiles/Bundle.properties b/src/main/java/propertyFiles/Bundle.properties index 45807dc7cde..fcf754374b1 100644 --- a/src/main/java/propertyFiles/Bundle.properties +++ b/src/main/java/propertyFiles/Bundle.properties @@ -145,6 +145,7 @@ contact.header=Contact {0} contact.dataverse.header=Email Dataverse Contact contact.dataset.header=Email Dataset Contact contact.to=To +contact.cc=CC contact.support=Support contact.from=From contact.from.required=User email is required. @@ -169,7 +170,7 @@ contact.context.subject.support={0} support request: {1} contact.context.dataverse.intro={0}You have just been sent the following message from {1} via the {2} hosted dataverse named "{3}":\n\n---\n\n contact.context.dataverse.ending=\n\n---\n\n{0}\n{1}\n\nGo to dataverse {2}/dataverse/{3}\n\nYou received this email because you have been listed as a contact for the dataverse. If you believe this was an error, please contact {4} at {5}. To respond directly to the individual who sent the message, simply reply to this email. contact.context.dataverse.noContact=There is no contact address on file for this dataverse so this message is being sent to the system address.\n\n -contact.context.dataset.greeting.helloFirstLast=Hello {0} {1}, +contact.context.dataset.greeting.helloFirstLast=Hello {0}, contact.context.dataset.greeting.organization=Attention Dataset Contact: contact.context.dataset.intro={0}\n\nYou have just been sent the following message from {1} via the {2} hosted dataset titled "{3}" ({4}):\n\n---\n\n contact.context.dataset.ending=\n\n---\n\n{0}\n{1}\n\nGo to dataset {2}/dataset.xhtml?persistentId={3}\n\nYou received this email because you have been listed as a contact for the dataset. If you believe this was an error, please contact {4} at {5}. To respond directly to the individual who sent the message, simply reply to this email. diff --git a/src/main/webapp/contactFormFragment.xhtml b/src/main/webapp/contactFormFragment.xhtml index 264fde98545..cb4eb3d0872 100644 --- a/src/main/webapp/contactFormFragment.xhtml +++ b/src/main/webapp/contactFormFragment.xhtml @@ -16,6 +16,12 @@

#{sendFeedbackDialog.getMessageTo()}

+
+ +
+

#{sendFeedbackDialog.getMessageCC()}

+
+
diff --git a/src/test/java/edu/harvard/iq/dataverse/feedback/FeedbackUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/feedback/FeedbackUtilTest.java index 2c91eebbc83..47e0f6da20e 100644 --- a/src/test/java/edu/harvard/iq/dataverse/feedback/FeedbackUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/feedback/FeedbackUtilTest.java @@ -181,9 +181,8 @@ public void testGatherFeedbackOnDataverse() { String messageSubject = "nice dataverse"; String userMessage = "Let's talk!"; System.out.println("first gather feedback"); - List feedbacks1 = FeedbackUtil.gatherFeedback(dataverse, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - Feedback feedback = feedbacks1.get(0); - assertEquals(installationBrandName + " contact: " + messageSubject, feedback.getSubject()); + Feedback feedback1 = FeedbackUtil.gatherFeedback(dataverse, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, true); + assertEquals(installationBrandName + " contact: " + messageSubject, feedback1.getSubject()); String expectedBody = "You have just been sent the following message from " + userEmail + " " + "via the " + installationBrandName + " hosted dataverse named \"dvAlias1\":\n\n" @@ -197,23 +196,26 @@ public void testGatherFeedbackOnDataverse() { + "If you believe this was an error, please contact " + supportTeamName + " at " + systemEmail + ". " + "To respond directly to the individual who sent the message, simply reply to this email."; - System.out.println("body:\n\n" + feedback.getBody()); - assertEquals(expectedBody, feedback.getBody()); - assertEquals("dvContact1@librascholar.edu", feedback.getToEmail()); - assertEquals("personClickingContactOrSupportButton@example.com", feedback.getFromEmail()); - JsonObject jsonObject = feedback.toJsonObjectBuilder().build(); + System.out.println("body:\n\n" + feedback1.getBody()); + assertEquals(expectedBody, feedback1.getBody()); + assertEquals("dvContact1@librascholar.edu,dvContact2@librascholar.edu", feedback1.getToEmail()); + assertEquals(systemEmail, feedback1.getCcEmail()); + + assertEquals("personClickingContactOrSupportButton@example.com", feedback1.getFromEmail()); + JsonObject jsonObject = feedback1.toJsonObjectBuilder().build(); System.out.println("json: " + jsonObject); assertEquals("personClickingContactOrSupportButton@example.com", jsonObject.getString("fromEmail")); - assertEquals("dvContact1@librascholar.edu", jsonObject.getString("toEmail")); + assertEquals("dvContact1@librascholar.edu,dvContact2@librascholar.edu", jsonObject.getString("toEmail")); + assertEquals(systemEmail, jsonObject.getString("ccEmail")); assertEquals(installationBrandName + " contact: " + "nice dataverse", jsonObject.getString("subject")); dataverse.setDataverseContacts(new ArrayList<>()); System.out.println("second gather feedback"); - List feedbacks2 = FeedbackUtil.gatherFeedback(dataverse, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - System.out.println("feedbacks2: " + feedbacks2); - feedback = feedbacks2.get(0); - assertEquals("support@librascholar.edu", feedback.getToEmail()); - System.out.println("body:\n\n" + feedback.getBody()); - assertTrue(feedback.getBody().startsWith("There is no contact address on file for this dataverse so this message is being sent to the system address.")); + Feedback feedback2 = FeedbackUtil.gatherFeedback(dataverse, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); + System.out.println("feedbacks2: " + feedback2); + assertEquals(systemEmail, feedback2.getToEmail()); + assertEquals(null, feedback2.getCcEmail()); + System.out.println("body:\n\n" + feedback2.getBody()); + assertTrue(feedback2.getBody().startsWith("There is no contact address on file for this dataverse so this message is being sent to the system address.")); } @Test @@ -236,17 +238,18 @@ public void testGatherFeedbackOnDataset() { DataverseSession dataverseSession = null; String messageSubject = "nice dataset"; String userMessage = "Let's talk!"; - List feedbacks = FeedbackUtil.gatherFeedback(dataset, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - System.out.println("feedbacks: " + feedbacks); - assertEquals(2, feedbacks.size()); - Feedback feedback = feedbacks.get(0); + Feedback feedback = FeedbackUtil.gatherFeedback(dataset, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, true); + System.out.println("feedbacks: " + feedback); System.out.println("Subject: " + feedback.getSubject()); System.out.println("Body: " + feedback.getBody()); System.out.println("From: " + feedback.getFromEmail()); System.out.println("To: " + feedback.getToEmail()); - assertEquals("ContactEmail1@mailinator.com", feedback.getToEmail()); + System.out.println("CC: " + feedback.getCcEmail()); + + assertEquals("ContactEmail1@mailinator.com,ContactEmail2@mailinator.com", feedback.getToEmail()); + assertEquals(systemEmail, feedback.getCcEmail()); assertEquals(installationBrandName + " contact: " + messageSubject, feedback.getSubject()); - String expected = "Hello Tom Brady,\n\n" + String expected = "Hello Tom Brady and Homer Simpson,\n\n" // FIXME: change from "personClickingContactOrSupportButton@example.com" to "Homer Simpson" or whatever (add to contact form). + "You have just been sent the following message from " + userEmail + " " + "via the " + installationBrandName + " hosted dataset " @@ -284,15 +287,15 @@ public void testGatherFeedbackOnDatasetNoContacts() { DataverseSession dataverseSession = null; String messageSubject = "nice dataset"; String userMessage = "Let's talk!"; - List feedbacks = FeedbackUtil.gatherFeedback(dataset, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - System.out.println("feedbacks: " + feedbacks); - assertEquals(1, feedbacks.size()); - Feedback feedback = feedbacks.get(0); + Feedback feedback = FeedbackUtil.gatherFeedback(dataset, dataverseSession, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); System.out.println("Subject: " + feedback.getSubject()); System.out.println("Body: " + feedback.getBody()); System.out.println("From: " + feedback.getFromEmail()); System.out.println("To: " + feedback.getToEmail()); + System.out.println("CC: " + feedback.getCcEmail()); + assertEquals(systemEmail, feedback.getToEmail()); + assertEquals(null, feedback.getCcEmail()); assertEquals(installationBrandName + " contact: " + messageSubject, feedback.getSubject()); String expected = "There is no contact address on file for this dataset so this message is being sent to the system address.\n\n" // FIXME: Add more context for person who receives systemEmail messages. @@ -357,8 +360,7 @@ public void testGatherFeedbackOnFile() { String messageSubject = "nice file"; String userMessage = "Let's talk!"; - List feedbacks = FeedbackUtil.gatherFeedback(dataFile, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - Feedback feedback = feedbacks.get(0); + Feedback feedback = FeedbackUtil.gatherFeedback(dataFile, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); System.out.println("feedback: " + feedback); System.out.println("Subject: " + feedback.getSubject()); System.out.println("Body: " + feedback.getBody()); @@ -425,8 +427,7 @@ public void testGatherFeedbackOnFileNoContacts() { String messageSubject = "nice file"; String userMessage = "Let's talk!"; - List feedbacks = FeedbackUtil.gatherFeedback(dataFile, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - Feedback feedback = feedbacks.get(0); + Feedback feedback = FeedbackUtil.gatherFeedback(dataFile, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); System.out.println("feedback: " + feedback); System.out.println("Subject: " + feedback.getSubject()); System.out.println("Body: " + feedback.getBody()); @@ -443,9 +444,7 @@ public void testGatherFeedbackFromSupportButtonNullSession() { String messageSubject = "I'm clicking the support button."; String userMessage = "Help!"; DvObject nullDvObject = null; - List feedbacks1 = FeedbackUtil.gatherFeedback(nullDvObject, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - System.out.println("feedbacks1: " + feedbacks1); - Feedback feedback = feedbacks1.get(0); + Feedback feedback = FeedbackUtil.gatherFeedback(nullDvObject, dataverseSessionNull, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); assertEquals(installationBrandName + " support request: " + messageSubject, feedback.getSubject()); String expectedBody = "LibraScholar SWAT Team,\n\n" @@ -460,15 +459,11 @@ public void testGatherFeedbackFromSupportButtonNullSession() { assertEquals("support@librascholar.edu", feedback.getToEmail()); assertEquals("personClickingContactOrSupportButton@example.com", feedback.getFromEmail()); InternetAddress nullSystemAddress = null; - List feedbacks2 = FeedbackUtil.gatherFeedback(nullDvObject, dataverseSessionNull, messageSubject, userMessage, nullSystemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - assertEquals(1, feedbacks2.size()); - feedback = feedbacks2.get(0); - assertEquals(null, feedback.getToEmail()); + Feedback feedback2 = FeedbackUtil.gatherFeedback(nullDvObject, dataverseSessionNull, messageSubject, userMessage, nullSystemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); + assertEquals(null, feedback2.getToEmail()); String nullUserMessage = null; - List feedbacks3 = FeedbackUtil.gatherFeedback(nullDvObject, dataverseSessionNull, messageSubject, nullUserMessage, nullSystemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - assertEquals(1, feedbacks3.size()); - feedback = feedbacks3.get(0); - assertEquals(null, feedback.getToEmail()); + Feedback feedback3 = FeedbackUtil.gatherFeedback(nullDvObject, dataverseSessionNull, messageSubject, nullUserMessage, nullSystemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); + assertEquals(null, feedback3.getToEmail()); } @Test @@ -479,8 +474,7 @@ public void testGatherFeedbackFromSupportButtonLoggedIn() { String messageSubject = "I'm clicking the support button."; String userMessage = "Help!"; DvObject dvObject = null; - List feedbacks = FeedbackUtil.gatherFeedback(dvObject, dataverseSessionAuthenticated, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName); - Feedback feedback = feedbacks.get(0); + Feedback feedback = FeedbackUtil.gatherFeedback(dvObject, dataverseSessionAuthenticated, messageSubject, userMessage, systemAddress, userEmail, baseUrl, installationBrandName, supportTeamName, false); assertEquals(messageSubject, feedback.getSubject()); assertEquals("Help!", feedback.getBody()); assertEquals("support@librascholar.edu", feedback.getToEmail()); diff --git a/src/test/java/edu/harvard/iq/dataverse/util/PersonOrOrgUtilTest.java b/src/test/java/edu/harvard/iq/dataverse/util/PersonOrOrgUtilTest.java index b22f18ca787..97d7ab45c7f 100644 --- a/src/test/java/edu/harvard/iq/dataverse/util/PersonOrOrgUtilTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/util/PersonOrOrgUtilTest.java @@ -86,6 +86,10 @@ public void testName() { verifyIsPerson("Francesco", "Francesco", null); // test only family name verifyIsPerson("Cadili", null, null); + + verifyIsPerson("kcjim11, kcjim11", null, null); + + verifyIsPerson("Bartholomew 3, James", "James", "Bartholomew 3"); } private void verifyIsOrganization(String fullName) { diff --git a/tests/data/datasetContacts1.json b/tests/data/datasetContacts1.json index 3953fc6daef..8c4a7cb2b11 100644 --- a/tests/data/datasetContacts1.json +++ b/tests/data/datasetContacts1.json @@ -60,7 +60,7 @@ "typeName": "datasetContactName", "multiple": false, "typeClass": "primitive", - "value": "LastContact2, FirstContact2" + "value": "Simpson, Homer" }, "datasetContactAffiliation": { "typeName": "datasetContactAffiliation",